[Haskell-cafe] How to design default implementations of type class methods?

ajb at spamcop.net ajb at spamcop.net
Wed Nov 8 21:01:54 EST 2006


G'day all.

Quoting Henning Thielemann <lemming at henning-thielemann.de>:

> I like to hear some opinions about how to implement class method defaults.

In this case, don't.  Use instance defaults instead.

class (Eq a) => Ring a where
    (*),(+),(-) :: a -> Integer
    zero, one :: a

    negate :: a -> a
    negate = (zero -)

    isZero :: a -> Bool
    isZero = (==zero)


class (Ring a) => RingWithNorm a where
    nu :: a -> Integer

class (RingWithNorm a) => EuclideanDomain a where
    divMod :: a -> a -> (a,a)

class (RingWithNorm a) => GCD a where
    gcd :: a -> a -> a

instance (EuclideanDomain a) => GCD a where
    gcd = {- Euclidean GCD algorithm; detail omitted -}

Then if you have some other domain where GCD applies, you can create
other instances as needed:

class (RingWithNorm a) => SteinDomain a where
    smallestPrime :: a
    steinDecompose :: a -> Maybe (a,a)

    -- scale p q = p/q
    --     where nu q < nu smallestPrime
    scale :: a -> a -> a

instance (SteinDomain a) => GCD a where
    gcd a b
      | nu a < nu b = gcd b a
      | a == b = a
      | otherwise = case (steinDecompose a, steinDecompose b) of
          (Nothing,_) -> b
          (_,Nothing) -> a
          (Just (pa,ca), Just (pb,cb))
            | isZero ca && isZero cb -> smallestPrime * gcd pa pb
            | isZero cb -> gcd a pb
            | otherwise -> gcd (pa - scale (ca*pb) cb) b

Cheers,
Andrew Bromage


More information about the Haskell-Cafe mailing list