The biggest thing you lose is polymorphic recursion. View the okasaki list:
data Cat qa = Empty | Cat a (q (Cat qa))
We can write
instance Foldable q => Foldable (Cat q) where foldMap _ Empty = mempty foldMap f (Cat aq) = fa <> foldMap (foldMap f) q
But if we try to use only MonoFoldable , we are stuck. Necessary instance restriction on q , forall x . (MonoFoldable (qx), Element (qx) ~ x) forall x . (MonoFoldable (qx), Element (qx) ~ x) cannot be expressed in any usual way. It is probably possible to get around this with Data.Constraint.Forall , but it gets pretty ugly.
A smaller problem is that the code can get more complex type signatures. For instance,
osum :: (MonoFoldable c, Num (Element c)) => c -> Element c
amazes me as below
sum :: (Foldable f, Num n) => fn -> n
Easy MonoFoldable : change MonoFoldable definition to
class (a ~ Element c) => MonoFoldable' ac where ...
which will give you
osum' :: (MonoFoldable' nc, Num n) => c -> n
Alternatively, scrap Element in general and use
class MonoFoldable'' ac | c -> a
which gives a similarly simplified signature.
Unfortunately, Michael Snoyman does not agree with me on this issue. I can write my own wrapper package for a while to open my preferred API.