Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Structural Equality in F#

I have a record type that includes a function:

{foo : int; bar : int -> int}

I want this type to have structural equality. Is there some way I can just mark that the bar should be ignored in equality tests? Or is there some other way around this?

like image 696
Nick Heiner Avatar asked Jun 09 '12 00:06

Nick Heiner


2 Answers

See Don's blog post on this topic, specifically the section Custom Equality and Comparison.

The example he gives is almost identical to the record structure you propose:

/// A type abbreviation indicating we’re using integers for unique stamps on objects
type stamp = int
 
/// A type containing a function that can’t be compared for equality  
 [<CustomEquality; CustomComparison>]
type MyThing =
    { Stamp: stamp;
      Behaviour: (int -> int) } 
 
    override x.Equals(yobj) =
        match yobj with
        | :? MyThing as y -> (x.Stamp = y.Stamp)
        | _ -> false
 
    override x.GetHashCode() = hash x.Stamp
    interface System.IComparable with
      member x.CompareTo yobj =
          match yobj with
          | :? MyThing as y -> compare x.Stamp y.Stamp
          | _ -> invalidArg "yobj" "cannot compare values of different types"
like image 116
Stephen Swensen Avatar answered Nov 08 '22 16:11

Stephen Swensen


To answer more specifically your original question, you can create a custom type whose comparison between instances is always true:

[<CustomEquality; NoComparison>]
type StructurallyNull<'T> =
    { v: 'T } 

    override x.Equals(yobj) =
        match yobj with
        | :? StructurallyNull<'T> -> true
        | _ -> false

    override x.GetHashCode() = 0

You can then use it this way:

type MyType = { 
    foo: int; 
    bar: StructurallyNull<int -> int> 
}
like image 25
FremyCompany Avatar answered Nov 08 '22 15:11

FremyCompany