Revise effect handling in Morley.Nettest
Clarification and motivation
Morley.Nettest.Abstract
defines a method dictionary (NettestImpl
) with all methods that a test can use. This approach is commonly used in Haskell and I think it's fine that we are doing it this way. Test writers have two options:
- Explicitly pass
NettestImpl
as an argument to every function that needs it. - Put it into a
ReaderT
(or anything similar toReaderT
) and get from the reader environment.
I find the latter more convenient (at least for test scenario writing) and that's what most our tests do. We have Morley.Nettest.Caps
module that provides ReaderT
-based interface. However, it does so using the caps library. Note that CapsT
is a synonym for ReaderT
. The primary feature of caps
is so-called "late binding". If there are multiple effects (or capabilities), caps
lets you change one capability so that it affects all other capabilities. Which is totally useless if you have only one capability. Or if you don't want to change any capability in runtime.
AFAIU, currently we are using caps
as nothing but ReaderT
, we don't use its killer features. It was me who initially added it. The addition of caps
was somewhat experimental and the whole morley-nettest
library was somewhat experimental back then. I didn't know whether we would have more effects and would want to modify them in runtime. Since then we have added one new effect: logging. When I was adding it, I was trying to figure out whether caps
can be more useful now. It seemed to be useful, but I still couldn't prove its usefulness. Anyway, currently we are still using it as a simple ReaderT
.
Using ReaderT
directly has some obvious advantages: it's well-known and well-tested, it doesn't add an extra dependency that's not even on Hackage. However, there still can be some reason to use caps
:
- Maybe it makes sense to make logging another capability inside
CapsT
. - In https://github.com/tqtezos/stablecoin/pull/79/files there is
CapsT
with 2 capabilities. But apparently they are independent, so the killer feature ofcaps
can't be used there. So it seems that instead ofCapsT
we could put something like(NettestImpl m, StablecoinImpl m)
intoReaderT
context there. Ifcaps
is actually useful there, it makes sense to export some caps-related things fromcleveland
.
I need someone else to look at this and give fresh opinion whether caps
gives any advantage here or we can replace it with ReaderT
.
Acceptance criteria
- Figure out whether there are any good arguments to keep using
caps
. - If there are no good arguments or we decide they don't outweigh the drawbacks of using
caps
, we stop usingcaps
and use standardReaderT
.