Тестирование равенства с Dicricted 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 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
Который в ФСИ дает:
val applyArray : _arg1:myDU -> myDU2 list
val arrayValueEquals : bool = true
val arrayValueNullEquals : bool = false
Мой вопрос заключается в следующем: почему первый тест проходит успешно, а не второй?
вот полная суть:
// 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
1 ответ
В F# есть нечто, называемое структурным равенством.
Вкратце: списки, массивы и Дискриминационные союзы поддерживают равенство, если их элементы поддерживают равенство. Для списков это будет поэлементное сравнение.
Основные Дискриминационные Союзы поддерживают Равенство из коробки, а объекты - нет, и поэтому после добавления TypeNull
к списку сравнение не удается.
Попробуйте просто это:
type TypeNull() = class end
TypeNull() = TypeNull() // false
затем
let actual = TypeNull()
let expected = TypeNull()
actual = expected // false
поэтому, если вы явно не определили равенство для своего объекта, поведение по умолчанию таково, что он даст значение true, только если два экземпляра одинаковы:
type TypeNull() = class end
let a = TypeNull()
let actual = a
let expected = a
actual = expected // true
но с DU он работает автоматически:
type TypeNull = TypeNull
TypeNull = TypeNull // true
затем
let actual = TypeNull
let expected = TypeNull
actual = expected // True