{-# OPTIONS_GHC -fglasgow-exts #-} ----------------------------------------------------------------------------- -- | -- Module : Control.Monad.Free -- Copyright : (C) 2008 Edward Kmett -- License : BSD-style (see the file LICENSE) -- -- Maintainer : Edward Kmett -- Stability : experimental -- Portability : portable -- -- See for -- the background on rep, abs and improve and their use. NB: the C type -- in that paper is just the right Kan extension of a monad -- along itself, also known as the monad generated by a functor: -- ---------------------------------------------------------------------------- module Control.Monad.Free ( module Control.Monad.Parameterized , PFree , Free , inFree , runFree , cataFree , free -- * Improving asymptotic performance with right Kan extensions , FreeLike(wrap) , improve ) where import Prelude hiding ((.),id,abs) import Control.Category import Control.Category.Cartesian import Control.Functor import Control.Functor.Combinators.Biff import Control.Functor.KanExtension import Control.Functor.Fix import Control.Monad.Parameterized import Control.Monad.Identity type Free f = Fix (PFree f) inFree :: f (Free f a) -> Free f a inFree = InB . Biff . Right runFree :: Free f a -> Either a (f (Free f a)) runFree = first runIdentity . runBiff . outB cataFree :: Functor f => (c -> a) -> (f a -> a) -> Free f c -> a cataFree l r = (l . runIdentity ||| r . fmap (cataFree l r)) . runBiff . outB free :: Either a (f (Free f a)) -> Free f a free = InB . Biff . first Identity class (Functor f, Monad m) => FreeLike f m where wrap :: f (m a) -> m a instance FreeLike f m => FreeLike f (Ran m m) where wrap t = Ran (wrap . flip fmap t . flip runRan) instance Functor f => FreeLike f (Free f) where wrap = inFree improve :: Functor f => (forall m. FreeLike f m => m a) -> Free f a improve m = abs m