[Haskell-cafe] Numerics & implementing different instances of the same class

Dan Weston westondan at imageworks.com
Fri Dec 12 22:08:09 EST 2008


What about something like

data AddMult a b = AddMult a b

class Monoid a where
   operation :: a -> a -> a
   identity  :: a

instance (Monoid a, Monoid b) => Monoid (AddMult a b) where
   operation  (AddMult a1 m1)
              (AddMult a2 m2)
            =  AddMult (operation a1 a2)
                       (operation m1 m2)
   identity =  AddMult identity identity

class Commutative a where
   -- Nothing, this is a programmer proof obligation

class Monoid a => Group a where
   inverse :: a -> a

class (Commutative a, Group a) => AbelianGroup a where

class (AbelianGroup a, AbelianGroup b) => Field a b where

instance AbelianGroup a => Field a a where


George Pollard wrote:
> Is there a good way of doing this? My running example is Monoid:
> 
>> class Monoid a where
>> 	operation :: a -> a -> a
>> 	identity :: a
> 
> With the obvious examples on Num:
> 
>> instance (Num a) => Monoid a where
>> 	operation = (+)
>> 	identity = 1
>>
>> instance (Num a) => Monoid a where
>> 	operation = (*)
>> 	identity = 0
> 
> Of course, this won't work. I could introduce a newtype wrapper:
> 
>> newtype (Num a) => MulNum a = MulNum a
>> newtype (Num a) => AddNum a = AddNum a
>>
>> instance (Num a) => Monoid (MulNum a) where
>> 	operation (MulNum x) (MulNum y) = MulNum (x * y)
>> 	identity = MulNum 1
>>
>> instance (Num a) => Monoid (AddNum a) where ... -- etc
> 
> However, when it comes to defining (e.g.) a Field class you have two
> Abelian groups over the same type, which won't work straight off:
> 
>> class Field a where ...
>> instance (AbelianGroup a, AbelianGroup a) => Field a where ...
> 
> Could try using the newtypes again:
>> instance (AbelianGroup (x a), AbelianGroup (y a) => Field a where ...
> 
> ... but this requires undecidable instances. I'm not even sure if it
> will do what I want. (For one thing it would also require an indication
> of which group distributes over the other, and this may restore
> decidability.)
> 
> I'm beginning to think that the best way to do things would be to drop
> the newtype wrappers and include instead an additional parameter of a
> type-level Nat to allow multiple definitions per type. Is this a good
> way to do things?
> 
> Has anyone else done something similar? I've taken a look at the Numeric
> Prelude but it seems to be doing things a bit differently. (e.g. there
> aren't constraints on Ring that require Monoid, etc)
> 
> - George
> 




More information about the Haskell-Cafe mailing list