Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The relationship between type classes - dependency vs using instance

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?


1 Answers

The first version says "monoids are semigroups, with the additional property mempty".

The second certain says "all types are semigroups, provided they are also monoids". Unless you're happy to turn on overlapping instances you can't add any other instances, so this amounts to "a type is a semigroup if and only if it is a monoid"; exactly backwards from the true relationship.

I would almost always prefer the former. Yes, it forces someone wanting to add a Monoid instance to also write a Semigroup instance, but the real "work" they have to do is the same either way: decide on implementations for mempty and mappend. The only thing you save them from by using the second approach is a little boilerplate.

like image 129
Ben Avatar answered Aug 28 '26 16:08

Ben



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!