For instance, a computation involving commands to read and write from the prompt:

First we describe the "commands" of our computation as a Functor data type

```
{-# LANGUAGE DeriveFunctor #-}
data TeletypeF next
= PrintLine String next
| ReadLine (String -> next)
deriving Functor
```

Then we use `Free`

to create the "Free Monad over `TeletypeF`

" and build some basic operations.

```
import Control.Monad.Free (Free, liftF, iterM)
type Teletype = Free TeletypeF
printLine :: String -> Teletype ()
printLine str = liftF (PrintLine str ())
readLine :: Teletype String
readLine = liftF (ReadLine id)
```

Since `Free f`

is a `Monad`

whenever `f`

is a `Functor`

, we can use the standard `Monad`

combinators (including `do`

notation) to build `Teletype`

computations.

```
import Control.Monad -- we can use the standard combinators
echo :: Teletype ()
echo = readLine >>= printLine
mockingbird :: Teletype a
mockingbird = forever echo
```

Finally, we write an "interpreter" turning `Teletype a`

values into something we know how to work with like `IO a`

```
interpretTeletype :: Teletype a -> IO a
interpretTeletype = foldFree run where
run :: TeletypeF a -> IO a
run (PrintLine str x) = putStrLn *> return x
run (ReadLine f) = fmap f getLine
```

Which we can use to "run" the `Teletype a`

computation in `IO`

```
> interpretTeletype mockingbird
hello
hello
goodbye
goodbye
this will go on forever
this will go on forever
```

Compare the definition of `Free`

to that of `Fix`

:

```
data Free f a = Return a
| Free (f (Free f a))
newtype Fix f = Fix { unFix :: f (Fix f) }
```

In particular, compare the type of the `Free`

constructor with the type of the `Fix`

constructor. `Free`

layers up a functor just like `Fix`

, except that `Free`

has an additional `Return a`

case.

There are some functions to help tear down `Free`

computations by interpreting them into another monad `m`

: `iterM :: (Functor f, Monad m) => (f (m a) -> m a) -> (Free f a -> m a)`

and `foldFree :: Monad m => (forall x. f x -> m x) -> (Free f a -> m a)`

. What are they doing?

First let's see what it would take to tear down an interpret a `Teletype a`

function into `IO`

manually. We can see `Free f a`

as being defined

```
data Free f a
= Pure a
| Free (f (Free f a))
```

The `Pure`

case is easy:

```
interpretTeletype :: Teletype a -> IO a
interpretTeletype (Pure x) = return x
interpretTeletype (Free teletypeF) = _
```

Now, how to interpret a `Teletype`

computation that was built with the `Free`

constructor? We'd like to arrive at a value of type `IO a`

by examining `teletypeF :: TeletypeF (Teletype a)`

. To start with, we'll write a function `runIO :: TeletypeF a -> IO a`

which maps a single layer of the free monad to an `IO`

action:

```
runIO :: TeletypeF a -> IO a
runIO (PrintLine msg x) = putStrLn msg *> return x
runIO (ReadLine k) = fmap k getLine
```

Now we can use `runIO`

to fill in the rest of `interpretTeletype`

. Recall that `teletypeF :: TeletypeF (Teletype a)`

is a layer of the `TeletypeF`

functor which contains the rest of the `Free`

computation. We'll use `runIO`

to interpret the outermost layer (so we have `runIO teletypeF :: IO (Teletype a)`

) and then use the `IO`

monad's `>>=`

combinator to interpret the returned `Teletype a`

.

```
interpretTeletype :: Teletype a -> IO a
interpretTeletype (Pure x) = return x
interpretTeletype (Free teletypeF) = runIO teletypeF >>= interpretTeletype
```

The definition of `foldFree`

is just that of `interpretTeletype`

, except that the `runIO`

function has been factored out. As a result, `foldFree`

works independently of any particular base functor and of any target monad.

```
foldFree :: Monad m => (forall x. f x -> m x) -> Free f a -> m a
foldFree eta (Pure x) = return x
foldFree eta (Free fa) = eta fa >>= foldFree eta
```

`foldFree`

has a rank-2 type: `eta`

is a natural transformation. We could have given `foldFree`

a type of `Monad m => (f (Free f a) -> m (Free f a)) -> Free f a -> m a`

, but that gives `eta`

the liberty of inspecting the `Free`

computation inside the `f`

layer. Giving `foldFree`

this more restrictive type ensures that `eta`

can only process a single layer at a time.

`iterM`

does give the folding function the ability to examine the subcomputation. The (monadic) result of the previous iteration is available to the next, inside `f`

's parameter. `iterM`

is analogous to a *paramorphism* whereas `foldFree`

is like a *catamorphism*.

```
iterM :: (Monad m, Functor f) => (f (m a) -> m a) -> Free f a -> m a
iterM phi (Pure x) = return x
iterM phi (Free fa) = phi (fmap (iterM phi) fa)
```

There's an alternative formulation of the free monad called the Freer (or Prompt, or Operational) monad. The Freer monad doesn't require a Functor instance for its underlying instruction set, and it has a more recognisably list-like structure than the standard free monad.

The Freer monad represents programs as a sequence of atomic *instructions* belonging to the instruction set `i :: * -> *`

. Each instruction uses its parameter to declare its return type. For example, the set of base instructions for the `State`

monad are as follows:

```
data StateI s a where
Get :: StateI s s -- the Get instruction returns a value of type 's'
Put :: s -> StateI s () -- the Put instruction contains an 's' as an argument and returns ()
```

Sequencing these instructions takes place with the `:>>=`

constructor. `:>>=`

takes a single instruction returning an `a`

and prepends it to the rest of the program, piping its return value into the continuation. In other words, given an instruction returning an `a`

, and a function to turn an `a`

into a program returning a `b`

, `:>>=`

will produce a program returning a `b`

.

```
data Freer i a where
Return :: a -> Freer i a
(:>>=) :: i a -> (a -> Freer i b) -> Freer i b
```

Note that `a`

is existentially quantified in the `:>>=`

constructor. The only way for an interpreter to learn what `a`

is is by pattern matching on the GADT `i`

.

Aside: The co-Yoneda lemma tells us that`Freer`

is isomorphic to`Free`

. Recall the definition of the`CoYoneda`

functor:`data CoYoneda i b where CoYoneda :: i a -> (a -> b) -> CoYoneda i b`

`Freer i`

is equivalent to`Free (CoYoneda i)`

. If you take`Free`

's constructors and set`f ~ CoYoneda i`

, you get:`Pure :: a -> Free (CoYoneda i) a Free :: CoYoneda i (Free (CoYoneda i) b) -> Free (CoYonda i) b ~ i a -> (a -> Free (CoYoneda i) b) -> Free (CoYoneda i) b`

from which we can recover

`Freer i`

's constructors by just setting`Freer i ~ Free (CoYoneda i)`

.

Because `CoYoneda i`

is a `Functor`

for any `i`

, `Freer`

is a `Monad`

for any `i`

, even if `i`

isn't a `Functor`

.

```
instance Monad (Freer i) where
return = Return
Return x >>= f = f x
(i :>>= g) >>= f = i :>>= fmap (>>= f) g -- using `(->) r`'s instance of Functor, so fmap = (.)
```

Interpreters can be built for `Freer`

by mapping instructions to some handler monad.

```
foldFreer :: Monad m => (forall x. i x -> m x) -> Freer i a -> m a
foldFreer eta (Return x) = return x
foldFreer eta (i :>>= f) = eta i >>= (foldFreer eta . f)
```

For example, we can interpret the `Freer (StateI s)`

monad using the regular `State s`

monad as a handler:

```
runFreerState :: Freer (StateI s) a -> s -> (a, s)
runFreerState = State.runState . foldFreer toState
where toState :: StateI s a -> State s a
toState Get = State.get
toState (Put x) = State.put x
```

This modified text is an extract of the original Stack Overflow Documentation created by following contributors and released under CC BY-SA 3.0

This website is not affiliated with Stack Overflow

Email: [email protected]