```{- |
as explained in

* Janis Voigtlander, /Asymptotic Improvement of Computations over Free Monads, MPC'08/

The solution is to redefine the Free datatype in CPS,
similar to what is done in difference lists to solve the problem on quadratic append
for lists.
-}
{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE FlexibleContexts, FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}

C(..), rep, improve
) where

import Control.Applicative

newtype C mu a = C (forall b. (a -> mu b) -> mu b)

rep :: Monad mu => mu a -> C mu a
rep m = C (m >>=)

improve :: Monad mu => C mu a -> mu a
improve (C p) = p return

instance Functor (C mu) where
fmap f (C m) = C (\h -> m (h.f))
--  fmap f (C m) = C (m . (.f))

return a = C (\h -> h a)
C p >>= k = C (\h -> p (\a -> case k a of C q -> q h))

instance Applicative (C mu) where
pure = return
(<*>) = ap

instance Functor f => MonadFree f (C (Free f)) where
wrap t = C (\h -> wrap (fmap (\(C p) -> p h) t))
free   = rep . (fmap.fmap.fmap) rep . free . improve

instance (Monad m, Functor f) => MonadFree f (C (FreeT f m)) where
wrap t = C (\h -> wrap (fmap (\(C p) -> p h) t))
free   = rep . (liftM.fmap.fmap) rep . free . improve