# 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.