Control.Monad.Free.Church

free-5.2: Monads for free

Copyright | (C) 2011-2015 Edward Kmett
License | BSD-style (see the file LICENSE)
Maintainer | Edward Kmett <ekmett@gmail.com>
Stability | provisional
Portability | non-portable (rank-2 polymorphism)
Safe Haskell | Safe
Language | Haskell2010

Control.Monad.Free.Church

Description

"Free Monads for Less"

The most straightforward way of implementing free monads is as a recursive datatype that allows for arbitrarily deep nesting of the base functor. This is akin to a tree, with the leaves containing the values, and the nodes being a level of `Functor` over subtrees.

For each time that the `fmap` or `>>=` operations is used, the old tree is traversed up to the leaves, a new set of nodes is allocated, and the old ones are garbage collected. Even if the Haskell runtime optimizes some of the overhead through laziness and generational garbage collection, the asymptotic runtime is still quadratic.

On the other hand, if the Church encoding is used, the tree only needs to be constructed once, because:

- All uses of `fmap` are collapsed into a single one, so that the values on the _leaves_ are transformed in one pass.

    fmap f . fmap g == fmap (f . g)

- All uses of `>>=` are right associated, so that every new subtree created is final.

    (m >>= f) >>= g == m >>= (\x -> f x >>= g)

Asymptotically, the Church encoding supports the monadic operations more efficiently than the naïve `Free`.

This is based on the "Free Monads for Less" series of articles by Edward Kmett:

- Free monads for less — Part 1
- Free monads for less — Part 2

Synopsis

- newtype F (f :: Type -> Type) a = F {
  - runF :: forall r. (a -> r) -> (f r -> r) -> r
  }
- improve :: forall (f :: Type -> Type) a. Functor f => (forall (m :: Type -> Type). MonadFree f m => m a) -> Free f a
- fromF :: forall (f :: Type -> Type) m a. MonadFree f m => F f a -> m a
- iter :: (f a -> a) -> F f a -> a
- iterM :: Monad m => (f (m a) -> m a) -> F f a -> m a
- toF :: forall (f :: Type -> Type) a. Functor f => Free f a -> F f a
- retract :: Monad m => F m a -> m a
- hoistF :: (forall x. f x -> g x) -> F f a -> F g a
- foldF :: Monad m => (forall x. f x -> m x) -> F f a -> m a
- class Monad m => MonadFree (f :: Type -> Type) (m :: Type -> Type) | m -> f where
  - wrap :: f (m a) -> m a
- liftF :: (Functor f, MonadFree f m) => f a -> m a
- cutoff :: forall (f :: Type -> Type) a. Functor f => Integer -> F f a -> F f (Maybe a)

# Documentation

newtype F (f :: Type -> Type) a #

The Church-encoded free monad for a functor `f`.

It is asymptotically more efficient to use (`>>=`) for `F` than it is to (`>>=`) with `Free`.

https://ekmett.github.io/reader/2011/free-monads-for-less-2/

Constructors

F |
Fields runF :: forall r. (a -> r) -> (f r -> r) -> r

#### Instances

Instances details

MonadTrans F # |
Instance details Defined in Control.Monad.Free.Church Methods lift :: Monad m => m a -> F m a #
Functor f => MonadFree f (F f) # |
Instance details Defined in Control.Monad.Free.Church Methods wrap :: f (F f a) -> F f a #
MonadReader e m => MonadReader e (F m) # |
Instance details Defined in Control.Monad.Free.Church Methods ask :: F m e # local :: (e -> e) -> F m a -> F m a # reader :: (e -> a) -> F m a #
MonadState s m => MonadState s (F m) # |
Instance details Defined in Control.Monad.Free.Church Methods get :: F m s # put :: s -> F m () # state :: (s -> (a, s)) -> F m a #
MonadWriter w m => MonadWriter w (F m) # |
Instance details Defined in Control.Monad.Free.Church Methods writer :: (a, w) -> F m a # tell :: w -> F m () # listen :: F m a -> F m (a, w) # pass :: F m (a, w -> w) -> F m a #
Foldable1 f => Foldable1 (F f) # |
Instance details Defined in Control.Monad.Free.Church Methods fold1 :: Semigroup m => F f m -> m # foldMap1 :: Semigroup m => (a -> m) -> F f a -> m # foldMap1' :: Semigroup m => (a -> m) -> F f a -> m # toNonEmpty :: F f a -> NonEmpty a # maximum :: Ord a => F f a -> a # minimum :: Ord a => F f a -> a # head :: F f a -> a # last :: F f a -> a # foldrMap1 :: (a -> b) -> (a -> b -> b) -> F f a -> b # foldlMap1' :: (a -> b) -> (b -> a -> b) -> F f a -> b # foldlMap1 :: (a -> b) -> (b -> a -> b) -> F f a -> b # foldrMap1' :: (a -> b) -> (a -> b -> b) -> F f a -> b #
Alternative f => Alternative (F f) # | This violates the Alternative laws, handle with care.
Instance details Defined in Control.Monad.Free.Church Methods empty :: F f a # (<|>) :: F f a -> F f a -> F f a # some :: F f a -> F f [a] # many :: F f a -> F f [a] #
Applicative (F f) # |
Instance details Defined in Control.Monad.Free.Church Methods pure :: a -> F f a # (<*>) :: F f (a -> b) -> F f a -> F f b # liftA2 :: (a -> b -> c) -> F f a -> F f b -> F f c # (*>) :: F f a -> F f b -> F f b # (<*) :: F f a -> F f b -> F f a #
Functor (F f) # |
Instance details Defined in Control.Monad.Free.Church Methods fmap :: (a -> b) -> F f a -> F f b # (<$) :: a -> F f b -> F f a #
Monad (F f) # |
Instance details Defined in Control.Monad.Free.Church Methods (>>=) :: F f a -> (a -> F f b) -> F f b # (>>) :: F f a -> F f b -> F f b # return :: a -> F f a #
MonadPlus f => MonadPlus (F f) # | This violates the MonadPlus laws, handle with care.
Instance details Defined in Control.Monad.Free.Church Methods mzero :: F f a # mplus :: F f a -> F f a -> F f a #
MonadFix (F f) # |
Instance details Defined in Control.Monad.Free.Church Methods mfix :: (a -> F f a) -> F f a #
Foldable f => Foldable (F f) # |
Instance details Defined in Control.Monad.Free.Church Methods fold :: Monoid m => F f m -> m # foldMap :: Monoid m => (a -> m) -> F f a -> m # foldMap' :: Monoid m => (a -> m) -> F f a -> m # foldr :: (a -> b -> b) -> b -> F f a -> b # foldr' :: (a -> b -> b) -> b -> F f a -> b # foldl :: (b -> a -> b) -> b -> F f a -> b # foldl' :: (b -> a -> b) -> b -> F f a -> b # foldr1 :: (a -> a -> a) -> F f a -> a # foldl1 :: (a -> a -> a) -> F f a -> a # toList :: F f a -> [a] # null :: F f a -> Bool # length :: F f a -> Int # elem :: Eq a => a -> F f a -> Bool # maximum :: Ord a => F f a -> a # minimum :: Ord a => F f a -> a # sum :: Num a => F f a -> a # product :: Num a => F f a -> a #
Traversable f => Traversable (F f) # |
Instance details Defined in Control.Monad.Free.Church Methods traverse :: Applicative f0 => (a -> f0 b) -> F f a -> f0 (F f b) # sequenceA :: Applicative f0 => F f (f0 a) -> f0 (F f a) # mapM :: Monad m => (a -> m b) -> F f a -> m (F f b) # sequence :: Monad m => F f (m a) -> m (F f a) #
MonadCont m => MonadCont (F m) # |
Instance details Defined in Control.Monad.Free.Church Methods callCC :: ((a -> F m b) -> F m a) -> F m a #
Apply (F f) # |
Instance details Defined in Control.Monad.Free.Church Methods (<.>) :: F f (a -> b) -> F f a -> F f b # (.>) :: F f a -> F f b -> F f b # (<.) :: F f a -> F f b -> F f a # liftF2 :: (a -> b -> c) -> F f a -> F f b -> F f c #
Bind (F f) # |
Instance details Defined in Control.Monad.Free.Church Methods (>>-) :: F f a -> (a -> F f b) -> F f b # join :: F f (F f a) -> F f a #
Traversable1 f => Traversable1 (F f) # |
Instance details Defined in Control.Monad.Free.Church Methods traverse1 :: Apply f0 => (a -> f0 b) -> F f a -> f0 (F f b) # sequence1 :: Apply f0 => F f (f0 b) -> f0 (F f b) #

improve :: forall (f :: Type -> Type) a. Functor f => (forall (m :: Type -> Type). MonadFree f m => m a) -> Free f a #

Improve the asymptotic performance of code that builds a free monad with only binds and returns by using `F` behind the scenes.

This is based on the "Free Monads for Less" series of articles by Edward Kmett:

- Free monads for less — Part 1
- Free monads for less — Part 2

and "Asymptotic Improvement of Computations over Free Monads" by Janis Voightländer.

fromF :: forall (f :: Type -> Type) m a. MonadFree f m => F f a -> m a #

Convert to another free monad representation.

iter :: (f a -> a) -> F f a -> a #

Tear down a `Free` `Monad` using iteration.

iterM :: Monad m => (f (m a) -> m a) -> F f a -> m a #

Like iter for monadic values.

toF :: forall (f :: Type -> Type) a. Functor f => Free f a -> F f a #

Generate a Church-encoded free monad from a `Free` monad.

retract :: Monad m => F m a -> m a #

`retract` is the left inverse of `lift` and `liftF`

    retract . lift = id
    retract . liftF = id

hoistF :: (forall x. f x -> g x) -> F f a -> F g a #

Lift a natural transformation from `f` to `g` into a natural transformation from `F f` to `F g`.

foldF :: Monad m => (forall x. f x -> m x) -> F f a -> m a #

The very definition of a free monad is that given a natural transformation you get a monad homomorphism.

class Monad m => MonadFree (f :: Type -> Type) (m :: Type -> Type) | m -> f where #

Monads provide substitution (`fmap`) and renormalization (`join`):

    m >>= f = join (fmap f m)

A free `Monad` is one that does no work during the normalization step beyond simply grafting the two monadic values together.

`[]` is not a free `Monad` (in this sense) because ``join` [[a]]` smashes the lists flat.

On the other hand, consider:

    data Tree a = Bin (Tree a) (Tree a) | Tip a

    instance Monad Tree where
      return = Tip
      Tip a >>= f = f a
      Bin l r >>= f = Bin (l >>= f) (r >>= f)

This `Monad` is the free `Monad` of Pair:

    data Pair a = Pair a a

And we could make an instance of `MonadFree` for it directly:

    instance MonadFree Pair Tree where
       wrap (Pair l r) = Bin l r

Or we could choose to program with ``Free` Pair` instead of `Tree` and thereby avoid having to define our own `Monad` instance.

Moreover, Control.Monad.Free.Church provides a `MonadFree` instance that can improve the asymptotic complexity of code that constructs free monads by effectively reassociating the use of (`>>=`). You may also want to take a look at the `kan-extensions` package (http://hackage.haskell.org/package/kan-extensions).

See `Free` for a more formal definition of the free `Monad` for a `Functor`.

Minimal complete definition

Nothing

Methods

wrap :: f (m a) -> m a #

Add a layer.

    wrap (fmap f x) ≡ wrap (fmap return x) >>= f

default wrap :: forall (t :: (Type -> Type) -> Type -> Type) (n :: Type -> Type) a. (m ~ t n, MonadTrans t, MonadFree f n, Functor f) => f (m a) -> m a #

#### Instances

Instances details

Monad m => MonadFree Identity (IterT m) # |
Instance details Defined in Control.Monad.Trans.Iter Methods wrap :: Identity (IterT m a) -> IterT m a #
Functor f => MonadFree f (Free f) # |
Instance details Defined in Control.Monad.Free Methods wrap :: f (Free f a) -> Free f a #
Applicative f => MonadFree f (Free f) # |
Instance details Defined in Control.Monad.Free.Ap Methods wrap :: f (Free f a) -> Free f a #
Functor f => MonadFree f (F f) # |
Instance details Defined in Control.Monad.Free.Church Methods wrap :: f (F f a) -> F f a #
(Functor f, MonadFree f m) => MonadFree f (MaybeT m) # |
Instance details Defined in Control.Monad.Free.Class Methods wrap :: f (MaybeT m a) -> MaybeT m a #
(Functor f, Monad m) => MonadFree f (FreeT f m) # |
Instance details Defined in Control.Monad.Trans.Free Methods wrap :: f (FreeT f m a) -> FreeT f m a #
(Applicative f, Monad m) => MonadFree f (FreeT f m) # |
Instance details Defined in Control.Monad.Trans.Free.Ap Methods wrap :: f (FreeT f m a) -> FreeT f m a #
MonadFree f (FT f m) # |
Instance details Defined in Control.Monad.Trans.Free.Church Methods wrap :: f (FT f m a) -> FT f m a #
(Functor f, MonadFree f m) => MonadFree f (ExceptT e m) # |
Instance details Defined in Control.Monad.Free.Class Methods wrap :: f (ExceptT e m a) -> ExceptT e m a #
(Functor f, MonadFree f m) => MonadFree f (IdentityT m) # |
Instance details Defined in Control.Monad.Free.Class Methods wrap :: f (IdentityT m a) -> IdentityT m a #
(Functor f, MonadFree f m) => MonadFree f (ReaderT e m) # |
Instance details Defined in Control.Monad.Free.Class Methods wrap :: f (ReaderT e m a) -> ReaderT e m a #
(Functor f, MonadFree f m) => MonadFree f (StateT s m) # |
Instance details Defined in Control.Monad.Free.Class Methods wrap :: f (StateT s m a) -> StateT s m a #
(Functor f, MonadFree f m) => MonadFree f (StateT s m) # |
Instance details Defined in Control.Monad.Free.Class Methods wrap :: f (StateT s m a) -> StateT s m a #
(Functor f, MonadFree f m, Monoid w) => MonadFree f (WriterT w m) # |
Instance details Defined in Control.Monad.Free.Class Methods wrap :: f (WriterT w m a) -> WriterT w m a #
(Functor f, MonadFree f m, Monoid w) => MonadFree f (WriterT w m) # |
Instance details Defined in Control.Monad.Free.Class Methods wrap :: f (WriterT w m a) -> WriterT w m a #
(Functor f, MonadFree f m) => MonadFree f (ContT r m) # |
Instance details Defined in Control.Monad.Free.Class Methods wrap :: f (ContT r m a) -> ContT r m a #
(Functor f, MonadFree f m, Monoid w) => MonadFree f (RWST r w s m) # |
Instance details Defined in Control.Monad.Free.Class Methods wrap :: f (RWST r w s m a) -> RWST r w s m a #
(Functor f, MonadFree f m, Monoid w) => MonadFree f (RWST r w s m) # |
Instance details Defined in Control.Monad.Free.Class Methods wrap :: f (RWST r w s m a) -> RWST r w s m a #

liftF :: (Functor f, MonadFree f m) => f a -> m a #

A version of lift that can be used with just a Functor for f.

cutoff :: forall (f :: Type -> Type) a. Functor f => Integer -> F f a -> F f (Maybe a) #

Cuts off a tree of computations at a given depth. If the depth is 0 or less, no computation nor monadic effects will take place.

Some examples (`n ≥ 0`):

    cutoff 0     _        == return Nothing

    cutoff (n+1) . return == return . Just

    cutoff (n+1) . lift   == lift . liftM Just

    cutoff (n+1) . wrap   == wrap . fmap (cutoff n)

Calling ``retract` . `cutoff` n` is always terminating, provided each of the steps in the iteration is terminating.