Capability

Further expanding upon why we chose capability

Usage of the Capability Library

  • Historically Haskell has been written with the mtl library. This library allows Monads 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 below

    • Downsides with MTL

      • ReaderT design pattern.

        • 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 single Reader 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's MTL 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 library

    • Fundamental 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 as deriving 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 way

        • Currently 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.