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

Gus*_*rra 3 f# type-providers

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

当我在这些属性中有"","无"和"1"的实例时,会失败:

(row1.a, row1.b, row1.c) |> should equal ("", None, Some 1)
Run Code Online (Sandbox Code Playgroud)

但所有这些工作都很好:

row1.a |> should equal ""

row1.b |> should equal None

row1.c |> should equal (Some 1)

("", None, Some 1) |> should equal ("", None, Some 1)
Run Code Online (Sandbox Code Playgroud)

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

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

Expected: <(, , Some(1))>
But was:  <(, , Some(1))>
Run Code Online (Sandbox Code Playgroud)

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

这也失败了:

(row1.a, row1.b, row1.c).Equals(("", None, Some 1)) |> should equal true
Run Code Online (Sandbox Code Playgroud)

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

row1 |> should equal ("", None, Some 1)
Run Code Online (Sandbox Code Playgroud)

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

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

pad*_*pad 5

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

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

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

如果你看看如何实现FsUnit,它实际上并不是类型安全的.我相信Jack P.的拉动请求是使FsUnit更加类型安全的一步.它似乎是一个改善FsUnit的领域.