If you only implement the less than operator in a custom Ord instance (on the theory that “I know I only need to implement one operation to get defaults for the others, and less than makes sense, since you can get anything using less than and equals”), the compiler gives zero warnings (even with -Wall) and trying to compare anything will send your program into nasty infinite recursion. It turns out that you have to implement less than or equal to (or the ‘compare’ function), not less than. Says so in the docs for Ord, of course, but… sigh.
In related news, the new ghci debugger is quite helpful. =)
And in unrelated news, I’m finally done with grad school and fellowship applications!!
I’ve always thought this was poor. Consider the case for Eq, you could define it so == in terms of /=, and vice versa. The default with no implementation would then give you horrible recursion. Perhaps we need some notation of what you’ve given compared to what you get – comments are not sufficient.
Neil: Now that I’ve run into this problem (and spent an hour or so tracking it down) I definitely agree with you.
Hmm… it seems like it wouldn’t be that hard for the compiler to detect circular dependencies among default implementations and give you a warning if the implementation you provide leaves any cycles among the non-overridden defaults. Are there any hidden “gotchas” that I’m not thinking of here?
Brent: No, looks trivial to me! I would actually get the compiler to replace any circular dependencies with error “Method not defined at “, as well as a compile time warning. Raise a GHC bug!
There’s one more issue to consider:
Nowhere in the Haskell report does it state that x != y means the same thing as not (x == y). It’s worse with Ord, because:
nan > nan = False
but:
compare nan nan = GT
One more thing. This is dumb, but it’s not morally wrong:
class Foo a where
op1 :: a -> Bool
op2 :: a -> Bool
op1 x = True || op2 x
op2 x = False && op1 x
instance Foo Int where {}