How to do the equivalent of pattern matching on native .NET types?

时间:2016-10-20 12:59:36

标签: f# quotations

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 Types, 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.

1 个答案:

答案 0 :(得分:2)

运行时类型推断?在编译时未知的类型?不,对不起,不存在,你必须自己建一个。

要检查特定类型是否是特定泛型类型的实例,您需要首先查看它是否是通用的,然后获取其通用定义,并进行比较:

if x.IsGenericType && (x.GetGenericTypeDefinition() = typeof<System.Tuple<_>>.GetGenericTypeDefinition()) then "tuple" else "not"

请注意,不只有一个Tuple类型,但很多 - Tuple<_>Tuple<_,_>Tuple<_,_,_>等等 - 最多8个。

同样适用于FSharpFunc

if x.IsGenericType && (x.GetGenericTypeDefinition() = typeof<FSharpFunc<_,_>>.GetGenericTypeDefinition()) then "function" else "not"

要获取类型的通用参数,请使用.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"