packages feed

category-extras-0.50.3: src/Control/Monad/Free.hs

{-# OPTIONS_GHC -fglasgow-exts #-}
-----------------------------------------------------------------------------
-- |
-- Module      :  Control.Monad.Free
-- Copyright   :  (C) 2008 Edward Kmett
-- License     :  BSD-style (see the file LICENSE)
--
-- Maintainer  :  Edward Kmett <ekmett@gmail.com>
-- Stability   :  experimental
-- Portability :  portable
--
-- See <http://wwwtcs.inf.tu-dresden.de/%7Evoigt/mpc08.pdf> 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:
-- <http://www.tac.mta.ca/tac/volumes/10/19/10-19.ps>
----------------------------------------------------------------------------
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