{-# LANGUAGE ExistentialQuantification #-} {-# LANGUAGE RankNTypes #-} import Control.Lens (Getting, foldMapOf) data Fold i o = forall m . Monoid m => Fold (i -> m) (m -> o) instance Functor (Fold i) where fmap k (Fold tally summarize) = Fold tally (k . summarize) instance Applicative (Fold i) where pure o = Fold (\_ -> ()) (\_ -> o) Fold tallyF summarizeF <*> Fold tallyX summarizeX = Fold tally summarize where tally i = (tallyF i, tallyX i) summarize (nF, nX) = summarizeF nF (summarizeX nX) focus :: (forall m . Monoid m => Getting m b a) -> Fold a o -> Fold b o focus lens (Fold tally summarize) = Fold (foldMapOf lens tally) summarize