F #, which implements equality only when the base type

EDIT: From the answer and comments added so far that I did not correctly explain what I want. Here is an example:

// type not supporting any type of comparison
[<NoEquality>]
[<NoComparison>]
type blah () =
    member x.huha = 0

// make a map, turns out to work whether x supports equality or not
let inline tt x =
    Map.ofList [1, x]       

let test () =
    // maps can be compared for equality if the argument can
    if (tt 1 = tt 2) then failwithf "strange"

    // maps can be made no matter if the argument supports equality
    if (tt (blah ())).Count <> 1 then failwithf "size"

    // this does not compile
    if tt (blah ()) = tt (blah ()) then ....

In short, I want my own type to behave just like the map above. Therefore, it must maintain equality when the type argument does, and should not when the type argument does not work. I also want typechecker to stop me using equality when it is not supported, since it can explicitly do this for built-in types. Thanks again.

: F # , . , Map<'k, 'd> iff 'd ( ). ? , , . .

[<NoComparison>]
type test_fails<[<EqualityConditionalOn>]'a> (content:'a) =

    let eq_impl (x:test_fails<'a>) (y:obj) =
        let y = y :?> test_fails<'a>
        x.content = y.content

    member x.content = content

    override x.Equals (y:obj) =
        eq_impl x y

[<NoComparison>]
type test_compiles<'a when 'a : equality> (content:'a) =

    let eq_impl (x:test_compiles<'a>) (y:obj) =
        let y = y :?> test_compiles<'a>
        x.content = y.content

    member x.content = content

    override x.Equals (y:obj) =
        eq_impl x y
+4
2

: [<EqualityConditionalOn>] .

, : Unchecked.equals = ( ' 'a). Unchecked.equals , . , / , ; , Object.Equals(obj).

+6

, , eq_impl = x.content y.content, , . , Object.ReferenceEquals ? , .

+2

Source: https://habr.com/ru/post/1530985/


All Articles