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 inequals
? (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