A Monad is something that "computes" when monadic context is collapsed by `join :: m (m a) -> m a` (recalling that `>>=` can be defined as `x >>= y = join (fmap y x))`. This is how Monads carry context through a sequential chain of computations: because at each point in the series, the context from the previous call is collapsed with the next.
A free monad satisfies all the Monad laws, but doesn't do any collapsing (that's the computation). It just builds up a nested series of contexts. The user who creates such a free monadic value is responsible for doing something with those nested contexts, so that the meaning of such a composition can be deferred until after the monadic value has been created.[^2]
[^2]: John Wiegley on [Stack Overflow](https://stackoverflow.com/a/13388966).
# Huh, what did that mean
- Define a monad in terms of `return`, `fmap` and `join`, rather than `return` and `(>>=)`.
```haskell
m >>= f = join (fmap f m)
```
- fmap is performing substitution and join is dealing with any re-normalization.
- Done this way, `(m >>= f)` on the `Maybe` monad would first `fmap` to obtain `Just (Just a)`, `Just Nothing` or `Nothing` before flattening.
- In the `Maybe a` case, the association of binds is largely immaterial, the normalization pass fixes things up to basically the same size.
- In Free monad, the monad is purely defined in terms of substitution.
```haskell
join :: Functor f => Free f (Free f a) -> Free f a
join (Pure a) = a
join (Free as) = Free (fmap join as)
```
# Free monads performance
- Vanilla free monads don't have great performance.
- Solutions like `Codensity` monad transformer and Church encoded free monad exist.[^3][^4]
```haskell
newtype FT f m a =
FT { runFT :: forall r. (a -> m r) -> (forall x. (x -> m r) -> f x -> m r) -> m r }
```
- Think of `Codensity` as a type level construction which ensures that you end up with a right associated bind.[^5]
[^3]: Asymptotic Improvement of Computations over Free Monads - Janis Voigtländer
[^4]: [The Free and The Furious: And by 'Furious' I mean Codensity. - raichoo](https://www.youtube.com/watch?v=EiIZlX_k89Y)
[^5]: [Free Monads for less - Edward Kmett](https://ekmett.github.io/reader/2011/free-monads-for-less-2/index.html)
# Reflection without remorse
- A left associated expression is asymptotically slower than the equivalent right associated expression. $O(n^2)$ vs $O(n)$ respectively.
- What's meant by reflection? Build and observe.
- Efficient data structures give asymptotic improvement for problematic occurrences of build and observe pattern like monads and monadic reflection.
# Extensible effects
- Defines only one effect `Eff`
- Type level list of effects
- What does it mean to be extensible?
# Freer monads
- Improves on extensible effects
- How?
* Relaxes the `Functor` constraint, becoming `Freer`!
* No need for `Functor` and `Typeable` on `Union`
-`freer` and `freer-simple` are based on `Freer` monads
- [Free monad considered harmful](https://markkarpov.com/post/free-monad-considered-harmful.html)
- [Building real-world Haskell applications using Tagless-Final and ReaderT](https://fpunfold.com/2023/01/30/final-tagless-readert.html)
- [Free monads from scratch](https://siraben.dev/2020/02/20/free-monads.html)
- [An earlier talk of my own on Free Monads](https://www.youtube.com/watch?v=fhu1UQel5eo)
- [Free Monads for less](https://ekmett.github.io/reader/2011/free-monads-for-less/index.html)
- [When to use CPS vs codensity vs reflection without remorse](https://stackoverflow.com/questions/45334985/when-to-use-cps-vs-codensity-vs-reflection-without-remorse-in-haskell)
- [ReaderT pattern is just extensible effects](https://xn--i2r.xn--rhqv96g/2022/02/03/readert-is-extensible-effects/)