I have defined different types :
type TypeNull() = class end
type MyType1 = {
a:int;
b:int
}
type MyType2 = {
a:string;
b:int
}
type MyType3 = {
a:string;
b:DateTime
}
and different disciminated union that use them :
type myDU =
| A of int
| B of string
| C of string
type myDU2 =
| D of MyType1
| E of MyType2
| F of TypeNull
I have on function that map myDU to 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())]
and then two tests to test equality :
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
Which in fsi gives :
val applyArray : _arg1:myDU -> myDU2 list
val arrayValueEquals : bool = true
val arrayValueNullEquals : bool = false
My question is as follows, why does the first test succeeds and not the second one?
here is the complete gist :
// 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
In F# there is something called Structural Equality.
In short: lists, arrays and Discriminated Unions support equality if their elements do support equality. For lists it will be an element by element comparison.
Basic Discriminated Unions support Equality out-of-the-box but objects don't and that's why once you add TypeNull
to the list the comparison fails.
Try simply this:
type TypeNull() = class end
TypeNull() = TypeNull() // false
then
let actual = TypeNull()
let expected = TypeNull()
actual = expected // false
so, unless you explicitly define equality for your object, the default behaviour is that it will yield true only if the two instances are the same:
type TypeNull() = class end
let a = TypeNull()
let actual = a
let expected = a
actual = expected // true
but with DUs it works automatically:
type TypeNull = TypeNull
TypeNull = TypeNull // true
then
let actual = TypeNull
let expected = TypeNull
actual = expected // True
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With