如何对本机 .NET 类型进行模式匹配?

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

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

我正在尝试为 Cuda 编译器构建原始 F# 引用,我需要弄清楚如何在函数声明中将元组类型转换为 C 结构类型,但我真的不熟悉 .NET 机制的工作原理。令人失望的是,F# 引语没有 return 你是一个基于可区分联合的好 AST,它会使所有内容都明确,但除非我想自己进行类型检查,否则我将使用它。

我想问的是 - 有没有办法在 .NET Types 上使用模式匹配来处理上面那段蹩脚的代码,因为上面的代码显然不起作用。

编辑:这个问题不是重复的,因为那个链接的问题是问如何打印 F# 记录的属性,而我问的是如何在 F# 引号内打印本机 .NET 类型(包括函数)的类型。在这里和那里接受的答案的视觉扫描应该表明它们是完全不同的,甚至没有使用相同的功能。

运行时类型推断?关于编译时未知的类型?不,抱歉,不存在,您必须自己构建一个。

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

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"