Capability
Usage of the Capability Library
Historically Haskell has been written with the
mtl
library. This library allowsMonads
to stack on top of each other in a linear fashion. This is very nice, as it allows the pluming of how each layer interacts to be abstracted away. However these advancements do not come without costs which are outlined belowDownsides with MTL
This means that as our monad stacks grow and our state monad fails to deal with concurrent programming, we will have to rewrite the backend to use
IO
over a singleReader Monad
.
Explicit heavy use of lenses
Due to every state being forced into a single reader monad, and not wanting to couple every function with everything in the reader environment, lenses with views into the struct itself must be used instead.
Inefficiencies in execution
Due to
MTL
Working as a list of effects rather than a set of effects, the more layers one adds to one'sMTL
stack, the slower the execution speed is.Even worse, is that the writer monad always leaks space and thus should be avoided
Solving These Issues with the
Capability
libraryFundamental ideas
Instead of having a list of monads one linearly stacks, we instead have a `set` of effects. This set may contain that a database connection is read-only or that this shared thread resource is readable and writable.
The set of effects is in reality, a single monad, with a view into the structure itself. So, a read-only view mimics the reader monad, while a write-only view mimics the writer monad.
This allusion is achieved by using a new feature in
GHC
8.6 known asderiving via
, which allows us to derive the proper interface and `effect` for each field in our environment.
ReaderT design pattern
This issue goes away, as the "State" effect could be implemented as either a proper state monad (we currently do this in the source code) or as a reader monad. This choice of how some computation gets computed is separated from the function logic itself.
Explicit heavy use of lenses
This issue goes away, as the
deriving via
extension derives the correct interfaces for us in a straightforward wayCurrently it is a bit tedious, but it's obvious in how tedious it is, thankfully.
Inefficiencies in execution
GHC thankfully knows how to optimize a single layer monad like Reader or State very well, so performance should be great.
Further Improvements
Currently the capability library only displays each field of a record as an effect. Ideally we'd have effects explain certain kinds of computation instead, and logically bundle these fields into some kind of greater effect.
Tomas has brought to my attention of the eff library which may some day replace or aid our usage of capability.