This is a sample project to compare how side-effects can be managed and tested in Haskell using different techniques.
Each alternative has it's own app<N> and test<N> project, and they all share common library code from src.
There are some docs describing each alternative
- Part 1, Introduction
- Part 2, Console Handler
- Part 3, Task
- Part 4, Type Classes
- Part 5, ReaderT design pattern
- app1 uses
IOfunctions direcly. The tests replace & capture the STDIN/STDOUT. - app2 uses the handler pattern to be able to replace the functions to interact with the console in tests.
- app3 similar to
app2but restricts which other side-effects can happen by introducing aTaskto replaceIO. - app4 uses custom type classes to restrict other side-effects from happening.
- app5 similar to
app4but usingReaderTto keep the application state
- app-bluefin similar to
app2andapp3but usesbluefinpackage as a type level alternative of the handler pattern. - 🚧 app-effectful uses
effectful- TBD tests
- app-heftia uses
heftia - 🚧 app-polysemy
- ❌
app-capabilities similar to.app5but usesCapabilitiespackage- ❌
Capabilitiespackages only works forbase >= 4.5 && 4.6. We are using 4.17. I wanted to try it out based on its blog post
- ❌
The code was developed with ghc 9.4.8 and cabal 3.10.3.0 as they were the recommended version at time.
% ghcup run --ghc 9.4.8 --cabal 3.10.3.0 -- zsh
# or % ghcup run --ghc recommended --cabal recommended -- zsh
% ghc --version
The Glorious Glasgow Haskell Compilation System, version 9.4.8
% cabal --version
cabal-install version 3.10.3.0
compiled using version 3.10.3.0 of the Cabal library
Each app and test can be run with cabal directly.
% cabal run app1
% cabal test app1-test