[Haskell-cafe] Any precedent or plan for guaranteed-safe Eq and Ord instances?

Heinrich Apfelmus apfelmus
Wed Oct 2 09:24:39 UTC 2013


Ryan Newton wrote:
> Here are some examples:
> 
> ---------------------------------------------
> data Foo = Bar | Baz
> 
> instance Eq Foo where
>   _ == _ = True
> 
> instance Ord Foo where
>   compare Bar Bar = EQ
>   compare Bar Baz = LT
>   compare _   _   = error "I'm partial!"
> ---------------------------------------------
> 
> These would allow LVish's "runPar" to non-determinstically return Bar or
> Baz (thinking they're the same based on Eq).  Or it would allow runPar to
> nondeterministically crash based on different schedulings hitting the
> compare error or not [1].
> 
> [..]
> 
> [1] If you're curious why this happens, its because the Ord instance is
> used by, say, Data.Set and Data.Map for the keys.  If you're inserting
> elements in an arbitrary order, the final contents ARE deterministic, but
> the comparisons that are done along the way ARE NOT.

I'm not sure whether the  Eq  instance you mention is actually 
incorrect. I had always understood that  Eq  denotes an equivalence 
relation, not necessarily equality on the constructor level.

One prominent example would be equality of Data.Map itself: two maps are 
"equal" if they contain the same key-value pairs,

     map1 == map2  <=>  toAscList map1 == toAscList map2

but that doesn't mean that their internal representation -- the balanced 
tree -- is the same. Virtually all exported operations in Data.Map 
preserve this equivalence, but the library is, in principle, still able 
to distinguish "equal" maps.

In other words, equality of abstract data types is different from 
equality of algebraic data types (constructors). I don't think you'll 
ever be able to avoid this proof obligation that the public API of an 
abstract data type preserves equivalence, so that LVish will yield 
"results that are deterministic up to equivalence".


However, you are mainly focused on equality of keys for a Map. In this 
case, it might be possible to move towards pointer equality and use 
things like  Hashable  or  StableName .


Best regards,
Heinrich Apfelmus

--
http://apfelmus.nfshost.com





More information about the Haskell-Cafe mailing list