3

有一个类型提供程序,分别具有“string”、“string option”和“int option”类型的三个属性“a”、“b”和“c”。

当我在这些属性中有一个带有 ""、None 和 Some 1 的实例时,这会失败:

(row1.a, row1.b, row1.c) |> should equal ("", None, Some 1)

但所有这些工作正常:

row1.a |> should equal ""

row1.b |> should equal None

row1.c |> should equal (Some 1)

("", None, Some 1) |> should equal ("", None, Some 1)

这怎么可能?什么可以使 b 中的 None 与任何其他 None 不同?编译后,None只是一个空值,.Net中两个空值可以不同吗?

与大多数 F# 类型一样,元组具有结构相等性,因此它应该可以工作。我收到带有消息的 NUnit.Framework.AssertionException:

Expected: <(, , Some(1))>
But was:  <(, , Some(1))>

NUnit 只是调用 .Equals,所以这就是问题所在。

这也失败了:

(row1.a, row1.b, row1.c).Equals(("", None, Some 1)) |> should equal true

的运行时类型row1is System.Tuple<string,Microsoft.FSharp.Core.FSharpOption<string>,Microsoft.FSharp.Core.FSharpOption<int>>,所以即使这样在理论上也应该有效:

row1 |> should equal ("", None, Some 1)

事实上,当元组中没有时它None会这样做。

除了类型提供程序,我无法用其他任何东西重现这种行为。

4

1 回答 1

5

我们已经被这个咬了好几次了,所以我们为此创建一个特定的注释

FsUnit 使用类型测试来实现其 DSL。类型推断不适用于此 DSL,因此请确保两个比较值属于同一类型。

例如,对于一些通用值,如True,False等,您需要指定它们的类型(如formula<fol>.True,formula<fol>.False等),否则这些值将被比较为 type obj

如果你看一下 FsUnit 是如何实现的,它并不是真正的类型安全的。我相信Jack P. 的 pull request是朝着使 FsUnit 更加类型安全迈出的一步。这似乎是一个改进 FsUnit 的领域。

于 2013-07-07T21:36:40.403 回答