【问题标题】:A very basic Type check fails in F# ... why?F# 中一个非常基本的类型检查失败……为什么?
【发布时间】:2013-08-04 18:21:51
【问题描述】:

我写了这段代码

type Test =
    | Age of int
    | Name of string;;

let x = Age(10);;


if (x.GetType() = typeof<Test>) then printfn "true" else printfn "false";;

代码打印错误。但这让我感到困惑,因为类型 Test 不是 Age 吗?

另外,有没有更好的方法来比较 F# 中的类型,.GetType() = typeof&lt;&gt; 很长。我尝试了:?,但我认为这是用于类型转换而不是比较类型。

【问题讨论】:

  • if (x.GetType() = typeof) then printfn "true" else printfn "false";;打印错误。
  • > if (x.GetType() :? Test) then printfn "true" else printfn "false";; if (x.GetType() :? Test) then printfn "true" else printfn "false";; ----^^^^^^^^^^^^^^^^^^ 标准输入(52,5):错误 FS0193:类型约束不匹配。 Test 类型与 System.Type 类型不兼容 'Test' 类型与'System.Type' 类型不兼容
  • 你看x.GetType()的结果了吗?这样做。
  • 将 x 与 | 匹配:?测试->真| _ -> 假的;;标准输入(59,3):错误 FS0016:“测试”类型没有任何适当的子类型,不能用作类型测试或运行时强制的来源。
  • x.GetType();;验证它:System.Type = FSI_0031+Test+Age 类型为 Test+Age。嗯...现在如何比较和测试它的年龄或名称?

标签: f# f#-interactive f#-3.0


【解决方案1】:

简单的答案是,这样做:

if (x :> obj) :? Test then printfn "true" else printfn "false"

这个问题是因为 DU 的实现(使用内部类和标签)和 F# 类型系统的限制(不承认实现)。

如您所见,x 的类型是 FSI_0001+Test+Age,而 F# 不会将其识别为 Test 的子类型。

【讨论】:

  • 或者,您可以使用Type.IsSubclassOf 方法,例如x.GetType().IsSubclassOf(typeof&lt;Test&gt;)
【解决方案2】:

引用规范

已编译的联合类型 U 具有:

· 每个空联合案例 C 都有一个 CLI 静态 getter 属性 U.C。这 属性获取代表每个此类情况的单例对象。

· 一个 CLI 嵌套类型 U.C 用于每个非空联合案例 C。此类型 具有联合的每个字段的实例属性 Item1, Item2.... 如果只有一个字段,则为单个实例属性 Item。 但是,只有一种情况的编译联合类型没有 嵌套类型。相反,联合类型本身扮演了案例的角色 输入。

我们看到Age 被实现为父DU 的嵌套类型。因此,您可以使用Type.GetNestedTypes 获取 DU 的所有子类型,然后测试每个子类型以查看类型是否匹配。

【讨论】:

    【解决方案3】:

    但这让我感到困惑,因为不是颜色类型的测试?

    Color 没有类型,Test 本身就是一个类型,所以它没有类型。所以你的问题很荒谬。

    也许你的意思是问为什么答案是这样的?如果是这样,这是 F# 当前选择在内部表示此类值的方式的结果。

    【讨论】:

      猜你喜欢
      • 2017-01-10
      • 1970-01-01
      • 2021-10-24
      • 2016-07-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多