let print_type_c (x: Type)=
if x = typeof<Int32> then "int"
elif x = typeof<Single> then "float"
elif x = typeof<Tuple<_>> then "tuple"
elif x = typeof<FSharpFunc<Tuple<'inp>,'out>> then "function..."
else failwithf "Not supported(%A)" x
print_type_c (typeof<int>) // prints int
print_type_c (typeof<float32>) // prints float
print_type_c (typeof<int*int>) // throw an exception
I am trying to build a primitive F# quotations to Cuda compiler and I need to figure out how to translate tuple types to C struct types in function declarations, but I am really not familiar with how the .NET machinery works. It is disappointing that F# quotations do not return you a nice AST based on discriminated unions which would make everything explicit, but unless I want to do the typechecking myself, I'll have work with this.
What I am asking is - is there a way to the crappy piece of code above with pattern matching on .NET Type
s, because the above is clearly not working.
Edit: The question is not a duplicate because that linked question is asking how to print the properties of F# records, while I am asking how to print the types of native .NET types (including functions) inside F# quotations. A visual scan of the accepted answer here and there should show that they are completely different and not even using the same functions.
Runtime type inference? On types not known at compile time? No, sorry, doesn't exist, you'll have to build one yourself.
To check if a particular type is an instance of a specific generic type, you need to see if it's generic in the first place, and then get its generic definition, and compare that:
if x.IsGenericType && (x.GetGenericTypeDefinition() = typeof<System.Tuple<_>>.GetGenericTypeDefinition()) then "tuple" else "not"
Note that there is not just one Tuple
type, but many - Tuple<_>
, Tuple<_,_>
, Tuple<_,_,_>
, and so on - up to 8.
Same goes for FSharpFunc
:
if x.IsGenericType && (x.GetGenericTypeDefinition() = typeof<FSharpFunc<_,_>>.GetGenericTypeDefinition()) then "function" else "not"
To get generic arguments of a type, use .GetGenericArguments()
:
if x.IsGenericType && (x.GetGenericTypeDefinition() = typeof<FSharpFunc<_,_>>.GetGenericTypeDefinition())
then
sprintf "function %s -> %s" (x.GetGenericArguments().[0].Name) (x.GetGenericArguments().[1].Name)
else
"not function"