2010-04-25

Isn't that funny?...
class SuperType a b c | a b -> c
class Coerce a b where
    coerce :: a -> b

instance (Coerce a c, Coerce b d) => Coerce (a, b) (c, d) where
    coerce (a, b) = (coerce a, coerce b)

coerceSuper :: (SuperType a b c, Coerce a c, Coerce b c) => (a, b) -> (c, c)
coerceSuper = coerce

instance (Integral a, Integral b) => SuperType a b Integer
    -- I'm too lazy to enumerate supertype for all pairs

instance Integral a => Coerce a Integer where coerce = toInteger

-- ANum
class (Integral a, Num a) => NumCoerce a
instance (Integral a, Num a) => NumCoerce a

data ANum = forall a . NumCoerce a => ANum a

instance Show ANum where showsPrec n (ANum a) = showsPrec n a

instance Eq ANum where
    (ANum a) == (ANum b) = (uncurry (==) . coerceSuper) (a,b)

instance Num ANum where
    (ANum a) + (ANum b) = (ANum . uncurry (+) . coerceSuper) (a,b)
    (ANum a) * (ANum b) = (ANum . uncurry (*) . coerceSuper) (a,b)
    (ANum a) - (ANum b) = (ANum . uncurry (-) . coerceSuper) (a,b)
    negate (ANum a) = ANum (negate a)
    abs (ANum a) = ANum (abs a)
    signum (ANum a) = ANum (signum a)
    fromInteger = ANum
One thing I really miss is nice way to create type-sets like NumCoerce a