3[](https://github.com/arybczak/effectful/actions?query=branch%3Amaster)
4[](https://hackage.haskell.org/package/effectful)
6*Note:* this is a pre-release.
8An easy to use, performant extensible effects library with seamless integration
9with the existing Haskell ecosystem.
131. Very fast (benchmark results with GHC 8.8.4:
14 [countdown](https://rybczak.net/files/effectful/countdown.html),
15 [filesize](https://rybczak.net/files/effectful/filesize.html), [comparison
16 with eff](https://rybczak.net/files/effectful/eff_comparison.html)).
182. Easy to use API (no boilerplate code and dealing with arcane types).
203. Correct semantics in presence of runtime exceptions (no more lost or
234. Seamless integration with the existing ecosystem (`exceptions`,
24 `monad-control`, `unliftio-core`, `resourcet` etc.).
265. Effects can be defined for either
28 - static dispatch (as fast as it gets, single interpretation) or
30 - dynamic dispatch (a bit slower, multiple interpretations),
32 depending on your needs.
36Do we really need yet another library for handling effects? There's
37[freer-simple](https://hackage.haskell.org/package/freer-simple),
38[fused-effects](https://hackage.haskell.org/package/fused-effects),
39[polysemy](https://hackage.haskell.org/package/polysemy),
40[eff](https://github.com/hasura/eff) and probably a few more.
42Unfortunately, of all of them only `eff` is a promising proposition because of
43reasonable performance characteristics (see the talk "Effects for Less" linked
44below for more information) and potential for good interoperability with the
47The second point is arguably the most important, because it allows focusing on
48things that matter instead of reinventing all kinds of wheels and is crucial for
49adoption of the library.
51However, `eff` uses delimited continuations underneath, which:
53- Are not yet supported by GHC (though [the
54proposal](https://github.com/ghc-proposals/ghc-proposals/pull/313) for including
55support for them has been accepted).
57- Are quite hard to understand.
59- Make the library "too powerful" in a sense as it faces
60 [a](https://github.com/hasura/eff/issues/13)
61 [few](https://github.com/hasura/eff/issues/7)
62 [issues](https://github.com/hasura/eff/issues/12) with no clear path towards
65On the other hand, if support for continuations is excluded from the handler
66monad, then the ability to define effects with non-linear control flow (such as
67`NonDet`) is lost. Arguably it's a small price to pay for predictability,
68because such specialized effects are needed rarely and locally, at which point a
69dedicated, well established solution such as
70[conduit](https://hackage.haskell.org/package/conduit),
71[list-t](https://hackage.haskell.org/package/list-t) or
72[logict](https://hackage.haskell.org/package/logict) can be used.
74This is where `effectful` comes in. The `Eff` monad it uses is essentially a
75`ReaderT` over `IO` on steroids, allowing us to dynamically extend its
76environment with data types that represent effects or their interpreters.
78Because this concept is so simple:
80- It's reasonably easy to understand what is going on under the hood.
82- The `Eff` monad being a reader allows for seamless interoperability with
83 ubiquitous classes such as `MonadBaseControl` and `MonadUnliftIO` as well as
84 support for handling runtime exceptions without worrying about lost or
85 discarded state (see the talk "Monad Transformer State" linked below for more
90- The `Eff` monad is concrete, so GHC has many possibilities for optimization,
91 which results in a very fast code at a default optimization level. There is no
92 need to mark every function `INLINE` or enable additional optimization passes,
95- If an advanced effect with non-linear control flow is needed, you can always
96 stick a transformer that implements it on top of `Eff` in a local context.
98In conclusion, `effectful` aims to reduce duplication and bring back performance
99to "boring" transformer stacks, most of which are a dozen of newtype'd `StateT`
100or `ReaderT` transformers, each with a few associated operations (usually tied
101to a type class), not to replace monad transformers altogether.
105A `Filesystem` effect with two handlers, one that runs in `IO` and another that
106uses an in-memory virtual file system can be found
107[here](https://github.com/arybczak/effectful/blob/master/examples/FileSystem.hs).
111Resources that inspired the rise of this library and had a lot of impact on its
116* [Effects for Less](https://www.youtube.com/watch?v=0jI-AlWEwYI) by Alexis King.
118* [Monad Transformer State](https://www.youtube.com/watch?v=KZIN9f9rI34) by Michael Snoyman.
122* [ReaderT design pattern](https://www.fpcomplete.com/blog/2017/06/readert-design-pattern/) by Michael Snoyman.
124* [Exceptions Best Practices](https://www.fpcomplete.com/blog/2016/11/exceptions-best-practices-haskell/) by Michael Snoyman.
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list