类型提供程序中的奇怪无行为

时间:2013-07-07 20:13:56

标签: f# type-providers

有一个类型提供程序,它有三个属性'a','b'和'c',分别是'string','string option'和'int option'。

如果我在这些属性中有“”,“无”和“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只是一个null,在.Net中可以有两个空值不同吗?

与大多数F#类型一样,元组具有结构上的相同性,因此它应该可以工作。 我得到一个带有Message:

的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

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

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

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

除了类型提供程序之外,我无法使用其他任何内容重现此行为。

1 个答案:

答案 0 :(得分:5)

我们已经被这几次咬过了,所以我们在此创建a specific note

  

FsUnit使用type test来实现其DSL。类型推断在此DSL上不起作用,因此请确保两个比较值属于同一类型。

例如,对于某些通用值,例如TrueFalse等,您需要指定其类型(formula<fol>.Trueformula<fol>.False等),否则这些值将被比较为obj类型。

如果你看一下how FsUnit is implemented,,它实际上并不是类型安全的。我相信Jack P.'s pull request是使FsUnit更加类型安全的一步。这似乎是一个改善FsUnit的领域。