在列表中测试与Dicriminated union的相等性

Wat*_*son 4 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
}
Run Code Online (Sandbox Code Playgroud)

和使用它们的不同的歧视联盟:

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

type myDU2 =
    | D of MyType1
    | E of MyType2
    | F of TypeNull
Run Code Online (Sandbox Code Playgroud)

我有功能将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())]
Run Code Online (Sandbox Code Playgroud)

然后两个测试平等的测试:

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
Run Code Online (Sandbox Code Playgroud)

在fsi中给出了:

val applyArray : _arg1:myDU -> myDU2 list
val arrayValueEquals : bool = true
val arrayValueNullEquals : bool = false
Run Code Online (Sandbox Code Playgroud)

我的问题如下,为什么第一次测试成功而不是第二次?

这是完整的要点:

// 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
Run Code Online (Sandbox Code Playgroud)

Gus*_*Gus 7

在F#中有一种称为结构平等的东西.

简而言之:如果列表,数组和Discriminated Unions的元素支持相等,则它们支持相等.对于列表,它将是元素比较的元素.

基本歧视联盟支持开箱即用的平等,但对象不支持,这就是为什么一旦你添加TypeNull到列表,比较失败.

试试这个:

type TypeNull() = class end
TypeNull() = TypeNull() // false
Run Code Online (Sandbox Code Playgroud)

然后

let actual = TypeNull()
let expected = TypeNull()
actual = expected // false
Run Code Online (Sandbox Code Playgroud)

所以,除非你明确定义对象的相等性,否则默认行为是只有当两个实例相同时它才会生成true:

type TypeNull() = class end
let a = TypeNull()
let actual = a
let expected = a
actual = expected // true
Run Code Online (Sandbox Code Playgroud)

但是使用DU它会自动运行:

type TypeNull = TypeNull
TypeNull = TypeNull // true
Run Code Online (Sandbox Code Playgroud)

然后

let actual = TypeNull
let expected = TypeNull
actual = expected // True
Run Code Online (Sandbox Code Playgroud)