@@ -2,7 +2,7 @@
22
33[](https://github.com/arybczak/effective/actions?query=branch%3Amaster)
44
5−A simple, yet powerful extensible effects library.
5+A simple, yet powerful extensible effects library (in the making).
66
77Main features:
88
@@ -16,10 +16,85 @@ Main features:
16164. Seamless integration with existing Haskell ecosystem (`exceptions`,
1717 `monad-control`, `unliftio-core`, `resourcet`).
1818
19−5. Effects can be defined for either static (as fast as it gets, single
20− interpretation) or dynamic (slower, multiple interpretations) dispatch
19+5. Effects can be defined for either
20+
21+ - static dispatch (as fast as it gets, single interpretation) or
22+
23+ - dynamic dispatch (slower, multiple interpretations are possible),
24+
2125 depending on your needs.
2226
27+## Motivation
28+
29+Let's address the elephant in the room. Do we really need yet another library
30+for handling effects? There's
31+[freer-simple](https://hackage.haskell.org/package/freer-simple),
32+[fused-effects](https://hackage.haskell.org/package/fused-effects),
33+[polysemy](https://hackage.haskell.org/package/polysemy),
34+[eff](https://github.com/hasura/eff) and probably a few more.
35+
36+Unfortunately, of all of them only `eff` is a promising proposition because
37+of reasonable performance characteristics (see the talk "Effects for Less"
38+linked below for more information) and potential for good interoperability with
39+existing ecosystem.
40+
41+The second point is arguably the most important, because it allows focusing on
42+things that matter instead of reinventing all kinds of wheels and is crucial for
43+adoption of the library.
44+
45+However, `eff` uses delimited continuations underneath, which:
46+
47+- Are not yet supported by GHC (though [the
48+proposal](https://github.com/ghc-proposals/ghc-proposals/pull/313) for including
49+support for them has been accepted).
50+
51+- Are somewhat hard to understand.
52+
53+- Make the space of possible effects "too big", i.e. some of their interactions
54+ might no longer make sense. For example, there is no `MonadWriter` instance
55+ for the `ContT` transformer in the `mtl` library, because [it can't be
56+ properly
57+ implemented](https://www.reddit.com/r/haskell/comments/hai9kb/why_is_there_no_monadwriter_for_contt_in_mtl/). It's
58+ not clear how `eff` can detect and prevent such interactions.
59+
60+On the other hand, if support for continuations is excluded from the handler
61+monad, then the ability to define effects with non-linear control flow (such as
62+`NonDet`) is lost. I'll argue it's a small price to pay for predictability,
63+because such specialized effects are needed rarely and locally, at which point a
64+dedicated, well established solution such as
65+[conduit](https://hackage.haskell.org/package/conduit),
66+[list-t](https://hackage.haskell.org/package/list-t) or
67+[logict](https://hackage.haskell.org/package/logict) can be used.
68+
69+This is where `effective` comes in. The `Eff` monad it uses is essentially a
70+`ReaderT` over `IO` on steroids, allowing us to dynamically extend its
71+environment with data types that represent effects.
72+
73+Because this concept is so simple:
74+
75+- It's reasonably easy to understand what is going on under the hood.
76+
77+- The `Eff` monad being a reader allows for seamless interoperability with
78+ ubiquitous classes such as `MonadBaseControl` and `MonadUnliftIO` as well as
79+ support for handling runtime exceptions without worrying about lost or
80+ discarded state (see the talk "Monad Transformer State" linked below for more
81+ information).
82+
83+What is more:
84+
85+- The `Eff` monad is concrete, so GHC has many possibilities for optimization,
86+ which results in a very fast code at a default optimization level. There is no
87+ need to mark every function `INLINE` or enable additional optimization passes,
88+ it just works.
89+
90+- If an advanced effect with non-linear control flow is needed, you can always
91+ stick a transformer that implements it on top of `Eff` in a local context.
92+
93+In conclusion, `effective` aims to reduce duplication and bring back performance
94+to "boring" transformer stacks, most of which are a dozen of newtype'd `StateT`
95+or `ReaderT` transformers, each with a few associated operations (usually tied
96+to a type class), not to replace monad transformers altogether.
97+
2398## Example
2499
25100A `Filesystem` effect with two handlers, one that runs in `IO` and another that