---
title:
- Effect Systems in Haskell - Part II
author:
- Sanchayan Maity
theme:
- default
classoption:
- aspectratio=169
---

# Agenda

- Cover two papers on Effect Systems.
    * Generalized Evidence Passing for Effect Handlers[^1]
    * Effect Handlers in Haskell, Evidently[^2]
- Some sections today's discussion isn't going to cover
    * Efficiency/Performance of the library or effect system itself
    * How to use effect systems
    * Comparison of effect system libraries or how to choose one


[^1]: [Generalized Evidence Passing for Effect Handlers](https://dl.acm.org/doi/pdf/10.1145/3473576)
[^2]: [Effect Handlers in Haskell, evidently](https://xnning.github.io/papers/haskell-evidently.pdf)

# Recap, what's it all about

- **Separate syntax from semantics**
- **Interpret your abstract syntax tree in various ways**
- **Not losing performance while having both**

# Recap, why effect systems

- Monads to model effects but monads don't compose[^3]
- transformers/mtl has limitations
    * Monad transformer stacks are rigid
    * Doesn't allow handling something like `Reader Int (Reader String)` due to functional dependencies
    ```haskell
    class Monad m => MonadReader r m | m -> r
    ```

    * More than a few effects in stack become unwieldy
    * n-square instances problem

[^3]: [Composing Monads by Mark Jones and Luc Duponcheel](https://web.cecs.pdx.edu/~mpj/pubs/RR-1004.pdf)

# Evidence passing based effect system libraries

- `EvEff`
- `MpEff`
- `speff`
- `cleff` based on `ReaderT IO`
- `effectful` based on `ReaderT IO`
- others?

# Some myths[^4]

- Many extensible effects libraries are implemented with free(r) monads (True)
- Therefore extensible effects = free(r) monads (False)
- Free(r) monads require certain mathematical concepts to grasp (True)
- Free(r) monads don't have very good performance (True, to some extent)
- Therefore extensible effects are slow, ivory-towerish toys (False)

[^4]: [ReaderT pattern is just extensible effects](https://喵.世界/2022/02/03/readert-is-extensible-effects/)

# Effects can be implemented in various way

- `free` monads
- `ReaderT IO`
- `CPS`
- `delimited continuations`

# What's the gist

- How do you pass the `handler` for the `effect`?

# Generalized control flow

- Languages that expose a yield primitive actually have a way to access delimited continuations! Central result of the paper by James-Sabry [^5][^6].

[^5]: [Yield: Mainstream Delimited Continuations](https://legacy.cs.indiana.edu/~sabry/papers/yield.pdf)
[^6]: [Delimited Continuations are all you need](https://www.youtube.com/watch?v=uRbqLGj_6mI)

# WTH are delimited continuations

- Delimited Continuations for Everyone[^7]

[^7]: [Delimited Continuations for Everyone](https://github.com/papers-we-love/pwlconf-info/tree/master/2017/kenichi-asai)

# How does one define an effect

```haskell
data Reader a e ans = Reader { ask :: !(Op () a e ans)
                             }

data State a e ans = State { get :: !(Op () a e ans)
                           , put :: !(Op a () e ans)
                           }
```

# Multi-prompt delimited control

```haskell
data Ctl e a = Pure { result :: !a }
             | forall h b e' ans.
               Control {
      -- prompt marker to yield to (in type context `::ans`)
                  marker :: Marker h e' ans,
      -- the final action, just needs the resumption (:: b -> Eff e' ans) to be evaluated.
                op     :: !((b -> Eff e' ans) -> Eff e' ans),
      -- the (partially) build up resumption;
      -- (b -> Eff e a) :~: (b -> Eff e' ans)` by the time
      -- we reach the prompt
                  cont   :: !(b -> Eff e a) }

data Context e where
  CCons :: !(Marker h e' ans) -> !(h e' ans) -> !(ContextT e e')
          -> !(Context e) -> Context (h :* e)
  CNil  :: Context ()

newtype Eff e a = Eff { unEff :: Context e -> Ctl e a }
```

# Key ideas

- Multi Prompt
- Evidence Passing
- Tail Resumptive Operations
- Bubbling Yields
- Short cut resumptions
- Monadic Translation
- Bind-inlining and Join-Point Sharing

# Dig in

- Dig in to the paper!

# Resources

- [Alexis King on "Delimited Continuations, Demystified" @ZuriHac2023](https://www.youtube.com/watch?v=DRFsodbxHQo)
- [GHC Proposal: Delimited continuation primops](https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0313-delimited-continuation-primops.rst)
- [Delimited Continuations](https://calwoo.github.io/posts/2020-02-03-delimited.html)
- [Efficient Compilation of Algebraic Effect Handlers - Ningning Xie](https://www.youtube.com/watch?v=tWLPrPfb4_U)
- [From Folklore to Fact: Comparing Implementations of Stacks and Continuations](https://kavon.farvard.in/papers/pldi20-stacks.pdf)
- [Compiler and Runtime Support for Continuation Marks](https://www-old.cs.utah.edu/plt/publications/pldi20-fd.pdf)
- [Capturing the Future by Replaying the Past Functional Pearl](https://arxiv.org/pdf/1710.10385.pdf)
- [From Delimited Continuations to Algebraic Effects in Haskell](https://blog.poisson.chat/posts/2023-01-02-del-cont-examples.html)
- [Concurrent System Programming with Effect Handlers](https://kcsrk.info/papers/system_effects_feb_18.pdf)
- [Eff Directly in OCaml](https://arxiv.org/pdf/1812.11664.pdf)
- [Retrofitting Effect Handlers onto OCaml](https://kcsrk.info/papers/drafts/retro-concurrency.pdf)

# Questions?

- Reach out on
  * Email: sanchayan@sanchayanmaity.net
  * Mastodon: https://sanchayanmaity.com/@sanchayan
  * Blog: https://sanchayanmaity.net
  * Telegram:
    - t.me/fpncr
    - t.me/SanchayanMaity
