Working minimal example of ReaderT Capability design pattern

This is just lifted wholesale from Jordan’s reference website but it does git clone and compile and has an Aff example too so i hope that’s useful to someone else beside me.

Criticism, observations welcom. PRs or forks that do additional things would also be very welcome. I would love to know how you jam Except-ion handling into this mix too (and i will have to find out fairly soon!)

repo can be found here:

2 Likes

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
2 Likes

Thanks, both for the comment (Readme - :white_check_mark:) and the explanation of Except extension to the example.

It occurred to me in writing the readme how much like “virtualization” / containers the concept of these “application running monads” is.

I wonder if that would be a fruitful way to explain it to people coming from outside FP?

(TBC - not “monad == container” but rather “monad is many things, in this usage it’s like a container”)

Maybe?

Btw, found the library: https://github.com/reactormonk/purescript-rave

2 Likes