Let's say I want to define my own type classes for semigroup and monoid. So I write this code:
class Semigroup g where
(<>) :: g -> g -> g
class Semigroup m => Monoid m where
mempty :: m
But there's another way I could define the relationship between those type classes, with some extensions:
class Semigroup g where
gappend :: g -> g -> g
class Monoid m where
mempty :: m
mappend :: m -> m -> m
instance Monoid m => Semigroup m where
gappend = mappend
The latter design has an advantage - Later I can add more instances for Monoid. For example, if I have a typeclass for a vector space I can later make it an additive group without having to specify it in the class declaration. On the other hand, I am forced to use flexible instances and undecidable instances.
My question is - what is the best design for this particular case?