How make .NET Mutable Dictionary<T, T> with StructuralComparison & Equality in F# -


i know f# have map, wanna use .net dictionary. dict have key string , values f# values + dict, ie:

type exprc =      | strc of string     | boolc of bool     | intc of int32     | decc of decimal     | arrayc of int * array<exprc>     | relc of relationc , relationc = dictionary<string, exprc>         

now, problem wanna solve how provide relationc type structural equality. if required encapsulate actual storage, how create container replacement dictionary, use mutable operations , have structural equality?


with current answer, code not work (of curse implementation not complete, however, not compile):

[<customequality; customcomparison>] type mydict() =     inherit dictionary<string, exprc>()     override this.equals x =         match x         | :? mydict y -> (this = y)         | _ -> false      override this.gethashcode () =         hash      interface system.icomparable       member x.compareto yobj =           match yobj           | :? mydict y -> compare x y           | _ -> invalidarg "mydict" "cannot compare values of different types"  , [<structuralequality;structuralcomparison>] exprc =     | intc of int     | strc of string     | mapc of mydict 

this error:

error fs0377: type uses invalid mix of attributes 'noequality', 'referenceequality', 'structuralequality', 'nocomparison' , 'structuralcomparison' (fs0377)

if absolutely must use dictionary<string, exprc>, derive dictionary<'k, 'v> , override equals:

type mydict() =     inherit dictionary<string, exprc>()     override this.equals x =         true // real implementation goes here     override this.gethashcode () =         0 // real implementation goes here 

here, you'd need implement equals have structural equality, , you'll need implement gethashcode match equals implementation.

another alternative, if don't need concrete class dictionary<'k, 'v>, define own class implements idictionary<tkey, tvalue>.

while possible, sounds lot of work. it'd easier use map, has structural equality default:

let m1 = map.oflist [("foo", 1); ("bar", 2); ("baz", 3)] let m2 = map.oflist [("bar", 2); ("foo", 1); ("baz", 3)] let m3 = map.oflist [("bar", 2); ("foo", 1); ("baz", 4)]  > m1 = m2;; val : bool = true > m1 = m3;; val : bool = false 

Comments