Thursday, 15 May 2014

f# - The correct way to override Equals etc. in DU with CustomEquality and CustomComparison? -



f# - The correct way to override Equals etc. in DU with CustomEquality and CustomComparison? -

i came across situation i'd compare discriminated union has 1 case isn't comparable straight , have no need utilize in (custom) comparison. reason, wrote customequality , customcomparison functions. alas stackoverflow , in general i'm uncertain how handle kind of equality override situation in f#. read equality , comparing constraints in f# don syme, chris smith's f# language details (gotchas).

<edit: pointed out in comments , context, should done funky case? entertaining similar thought how create job queue using mailboxprocessor? wherein i'd queue dus used perform functions or command state machine.

looking @ other post (i refrain producing code here), uses elegantly mailboxprocessor see has similar problem , similar idea. i'm not sure if design improve or there way compare functions , in event have more questions regarding (with c# background).

questions:

how avoid stackoverflow in equals? (probably simple, but...) should generic icomparable implemented? should static fellow member (=) etc. overloaded per chris' blog post? what else should overloaded in dus in similar situation? should iequatable implemented in case there performance implementations?

i think of these answered looking @ il (e.g. if compiler generates iequatable dus), create sure haven't overlooked anything.

the code

[<customequality; customcomparison>] type funkyunion = | case1 | case2 | funky of (unit -> unit) override x.equals(obj) = //this here cause stackoverflow occur... match obj | :? funkyunion y -> (x = y) | _ -> false override x.gethashcode() = match x | case1 -> 1 | case2 -> 2 | _ -> 3 interface system.icomparable fellow member x.compareto yobj = match yobj | :? funkyunion y -> compare x y | _ -> invalidarg "yobj" "cannot compare value of different types" interface system.icomparable<funkyunion> fellow member x.compareto(y) = compare x y [<entrypoint>] allow main argv = allow funky1 = funkyunion.case1 allow funky2 = funkyunion.case2 if funky1 = funky2 printfn "!!!" printfn "!" 0

you're getting stack overflow in equals, because you're using = on same type you're implementing equals for. equals calls =, = calls equals, , on...

what want equals this:

override this.equals(o) = match o | :? funkyunion fu -> match this, fu | case1, case1 | case2, case2 -> true | funky f1, funky f2 -> (* whatever want case *) | _, _ -> false | _ -> false

you can update compareto in similar way. should started.

f#

No comments:

Post a Comment