# Pipes define a free monad

The core type of the *pipes*
library is a free monad.
Indeed,
`Pipes.Proxy`

is equivalent to `Free (ProxyF _ _ _ _ _)`

, where

```
data Free f a
= Free (f (Free f a))
| Pure a
data ProxyF a' a b' b m x
= Request a' (a -> x)
| Respond b (b' -> x)
| M (m x)
```

That’s nothing ground-breaking if you’re familiar with free monads. In fact, it
used to be the literal definition of
pipes,
using *free* before I even knew
Haskell was a thing.

Nevertheless, my previous understanding of *pipes* was mostly based on the
interface (which is very nice by the way; the diagrams in
`Pipes.Core`

are a pleasure to contemplate), while I needed all my focus to follow the
implementation. Hence, in spite of now extensive experience with free monads,
it took one more wander in front of the source code of *pipes* for me to have
that epiphany.

A much deeper understanding of the whole business followed immediately.
With free monads as a common starting point^{1},
it became much easier to compare
*pipes*,
*conduit*,
and
*quiver*:
basically, they’re all using free monads for differing I/O-like functors^{2}.

Now it may be just another occasionally useful fun fact, but that one somehow felt like a personal achievement. That realization gave me a strong impression of the power of abstraction.