F# 在列表中测试与区分并集的相等性

F# 在列表中测试与区分并集的相等性,f#,equality,discriminated-union,F#,Equality,Discriminated Union,我定义了不同的类型: type TypeNull() = class end type MyType1 = { a:int; b:int } type MyType2 = { a:string; b:int } type MyType3 = { a:string; b:DateTime } 以及使用它们的不同非限制性联盟: type myDU = | A of int | B of string | C of str

我定义了不同的类型:

type TypeNull() = class end

type MyType1 = {
    a:int;
    b:int
}

type MyType2 = {
    a:string;
    b:int
}

type MyType3 = {
    a:string;
    b:DateTime
}
以及使用它们的不同非限制性联盟:

type myDU =
    | A of int
    | B of string
    | C of string

type myDU2 =
    | D of MyType1
    | E of MyType2
    | F of TypeNull
我有一个将myDU映射到myDU2的函数:

let applyArray = function
    | A x -> [E({a="1"; b=2})]
    | B x -> [D({a=1; b=2});E({a="1"; b=2});E({a="5"; b=24})]
    | C x -> [D({a=1; b=2});E({a="1"; b=2});F(TypeNull())]
然后是两个测试来测试相等性:

let arrayValueEquals =
    let expected = [D({a=1; b=2});E({a="1"; b=2});E({a="5"; b=24})]
    let actual = applyArray <| B("xxx")
    actual = expected

let arrayValueNullEquals =
    let expected = [D({a=1; b=2});E({a="1"; b=2});F(TypeNull())]
    let actual = applyArray <| C("xxx")
    actual = expected
我的问题如下,为什么第一次测试成功而第二次测试不成功

以下是完整的要点:

// Learn more about F# at http://fsharp.net. See the 'F# Tutorial' project
// for more guidance on F# programming.

#load "Library1.fs"
open test2
open System

type TypeNull() = class end

type MyType1 = {
    a:int;
    b:int
}

type MyType2 = {
    a:string;
    b:int
}

type MyType3 = {
    a:string;
    b:DateTime
}

type myDU =
    | A of int
    | B of string
    | C of string

type myDU2 =
    | D of MyType1
    | E of MyType2
    | F of TypeNull

let applyArray = function
    | A x -> [E({a="1"; b=2})]
    | B x -> [D({a=1; b=2});E({a="1"; b=2});E({a="5"; b=24})]
    | C x -> [D({a=1; b=2});E({a="1"; b=2});F(TypeNull())]

let arrayValueEquals =
    let expected = [D({a=1; b=2});E({a="1"; b=2});E({a="5"; b=24})]
    let actual = applyArray <| B("xxx")
    actual = expected

let arrayValueNullEquals =
    let expected = [D({a=1; b=2});E({a="1"; b=2});F(TypeNull())]
    let actual = applyArray <| C("xxx")
    actual = expected
//了解更多关于F#at的信息http://fsharp.net. 参见“F#Tutorial”项目
//有关F#编程的更多指导。
#加载“Library1.fs”
开放测试2
开放系统
类型TypeNull()=类结束
类型MyType1={
a:int;
b:int
}
类型MyType2={
a:弦;
b:int
}
类型MyType3={
a:弦;
b:日期时间
}
myDU型=
|整型
|B串
|弦的C
类型myDU2=
|我的类型1的D
|MyType2的E
|类型为NULL的F
设applyArray=函数
|A x->[E({A=“1;b=2})]
|B x->[D({a=1;B=2});E({a=“1;B=2});E({a=“5;B=24})]
|cx->[D({a=1;b=2});E({a=“1;b=2});F(TypeNull())]
让ArrayValue相等=
设期望值=[D({a=1;b=2});E({a=“1;b=2});E({a=“5;b=24})]
让actual=applyArray在F#中有一个叫做

简而言之:如果列表、数组和受歧视的联合的元素支持相等,则它们支持相等。对于列表,它将是一个元素对一个元素的比较

基本的区分联合支持开箱即用的平等,但对象不支持,这就是为什么一旦将
TypeNull
添加到列表中,比较就会失败

试着简单地说:

type TypeNull() = class end
TypeNull() = TypeNull() // false
然后

因此,除非为对象显式定义相等,否则默认行为是,只有当两个实例相同时,才会产生true:

type TypeNull() = class end
let a = TypeNull()
let actual = a
let expected = a
actual = expected // true
但对于DUs,它会自动工作:

type TypeNull = TypeNull
TypeNull = TypeNull // true
然后


您是否打印出了
actual
的值以查看它是什么?我怀疑TypeNull()不是您所认为的那样。或者您是否尝试将预期和实际发送到F#Interactive以查看类型。它确实给了我:>TypeNull();;val-it:TypeNull=FSI_0002+TypeNull>let-actual=applyArray我使用type a()=类end来“模拟”type a={}。那就不一样了?是的,但在F#这不是一个歧视性的联盟。这是一个简单的对象。如果实例相同,则默认情况下对象相等。这在C#中也是一样。我会仔细考虑你今晚告诉我的。。。我必须考虑一下。有一件事我不明白,但这是一天的结束,所以..好吧,将
TypeNull()
更改为
TypeNull=TypeNull
,然后从实例中删除
()
。模仿“空记录”的方法是一个单一的歧视性联盟,就像古斯塔沃的例子一样。
type TypeNull() = class end
let a = TypeNull()
let actual = a
let expected = a
actual = expected // true
type TypeNull = TypeNull
TypeNull = TypeNull // true
let actual = TypeNull
let expected = TypeNull
actual = expected // True