Real World Haskell has this example:
class BasicEq3 a where
isEqual3 :: a -> a -> Bool
isEqual3 x y = not (isNotEqual3 x y)
isNotEqual3 ::
In my personal opinion, the defaulting mechanism is unnecessary and unwise. It would be easy for the class author to just provide the defaults as ordinary functions:
notEq3FromEq3 :: (a -> a -> Bool) -> (a -> a -> Bool)
notEq3FromEq3 eq3 = (\x y -> not (eq3 x y))
eq3FromNotEq3 :: (a -> a -> Bool) -> (a -> a -> Bool)
eq3FromNotEq3 ne3 = (\x y -> not (ne3 x y))
(In fact, these two definitions are equal, but that would not be true in general). Then an instance looks like:
instance BasicEq3 Bool where
isEqual3 True True = True
isEqual3 False False = True
isEqual3 _ _ = False
isNotEqual3 = notEq3FromEq3 isEqual3
and no defaults are required. Then GHC can warn you if you don't provide the definition, and any unpleasant loops have to be explicitly written by you into your code.
This does remove the neat ability to add new methods to a class with default definitions without affecting existing instances, but that's not so huge a benefit in my view. The above approach is also in principle more flexible: you could e.g. provide functions that allowed an Ord instance to choose any comparison operator to implement.