Hey, nice! You might want to add a Readme that clarifies the order in which to read the files. I thought Layer 4 was the last file to read, not the first one.

I would love to know how you jam `Except`

-ion handling into this mix too

`ReaderT env monad output`

is isomorphic to `env -> monad output`

, which is read as “if you give me an environment value, I will give you (but not yet run) a monadic computation that produces an `output`

value.” You then run that computation via `launchAff`

/`runAff`

.

If you want to change that sentence to, “If you give me an environment value, I will give you a monadic computation that produces either a successful output (i.e. `Right output`

) or an error (i.e. `Left error`

),” then you would want a type signature like `env -> monad (Either error output)`

.

When we translate complex monads to monad transformers, we start with the inside part first. `monad (Either error output)`

is synonymous with `ExceptT error monad output`

. If we update our function type signature to use this new “monadic type,” we get `env -> ExceptT error monad output`

. We now want to replace the `env ->`

part with `ReaderT`

, so we get `ReaderT env (ExceptT error monad) output`

.

Now that we have `ExceptT`

in our stack, we can use `MonadCatch`

and `MonadError`

throughout our code base.

However, the `ExceptT`

transformer constrains us to use only one error type throughout the entire code base. If we want to use `Variant`

instead, we can use checked-exceptions, which exists for this very purpose.

I believe someone packaged up a library that defines the below type, but I can’t recall where and what the library was called:

```
-- isomorphic to:
-- env -> monad (Either (Variant errorRows) monad output
newtype REvT env errorRows monad output =
ReaderT env (ExceptV errorRows monad) output
```