Here is another way to
look at it: when you say
class LeftModule Whole m => Additive m
you are closer to specifying an *instance* relation than a
*class constraint* relation.
This is very true.
However, as mentioned at the outset specifying such
instance requires newtype noise (on m, to avoid incoherent
overlap with the other instances) that leads to a particularly
hideous programming style.
newtype NaturalModule m = NaturalModule { runNaturalModule
:: m }
instance Monoidal m => LeftModule Natural (NaturalModule
m) where
It isn't so bad when working with simple examples like
fiveTimes m = runNaturalModule (5 .* NaturalModule m)
but it gets progressively worse as the hierarchy gets
deeper, and I have to deal with putting on and taking off more
and more of these silly wrappers.
Placing the superclass constraint enforces that such
instances will always be available to me, and admits optimized
implementations, which I currently have to shoehorn into the
main class and expose by convention.