I strongly recommend to check all other papers and articles on https://okmij.org/ftp/, every single one of them is brilliant and insightful. I love the pedagogy, the writing style and clarity. Oleg Kiselyov is one of the best technical writers I've discovered recently.
If you are looking for real-world code for an effect system, not just a PDF paper, you should probably look at the eff library: https://github.com/hasura/eff
The acknowledgement section on that GitHub README mentions this paper.
eff has never been released to Hackage and as far as I know never used in production. I wouldn't call it "real-world code". For effect systems that people do actually use in production I suggest
`eff` is a research project that is no longer in active development and never made it to production in any sense. It would be AMAZING if `eff` were completed but I dont think that will happen at this point.
`eff` is based on delimited continuations (which Alexis had to build into GHC), it is not using `Freer`. If you want to look at an effect system in Haskell that actually has been used in production AND is based on this paper then look at `freer-simple`: https://hackage.haskell.org/package/freer-simple
No it is not high performance, but neither are any other Haskell effect systems and performance is relative to your problem domain. It also has the benefit of being implemented very similarly to Oleg's paper making it a lot easier to learn from then most other options.
> No it is not high performance, but neither are any other Haskell effect systems
This is not true. IO-wrapper effect systems (in practice, effectful or Bluefin) have as good performance as Haskell's IO monad, that is to say as good as you can get in Haskell.
No, no loss of safety. Was there something in particular you were thinking of? With IO-wrapper effect systems you give up native multishot continuations (but you can always get them back by wrapping in LogicT).
You can look at my table of "A Comparison of Effect Systems at a Glance" to see all the tradeoffs:
As far as I know the shiniest implementations in the effect typing world at the moment are Koka and Effekt, which are both languages in their own right. They each have their own ideas about implementation to make effects (mostly) zero-cost.
Also effect-ts in TypeScript world, which is by far the most popular effect system around (quite sure it has overtaken Scala's ZIO from which it is inspired).
The ecosystem is massive.
Cons: TypeScript is a great type system but requires some investment to get the best out of it, it's also very verbose.
Pros: you have access to the entirety of the TypeScript ecosystem.
This paper is up to Oleg's usual high standard, and is a very important step to read if you're catching up on the history of effect systems in Haskell.
As a user, I think effect libraries in Haskell trade off between five main constraints:
* Typelevel wizardry
* Boilerplate
* Performance
* Ability to handle "higher-order" effects (e.g., `bracket`)
* Safety (e.g., not accidentally leaking effects beyond their scope)
The most compelling libraries I've seen from the industrial perspective are the "IO-wrapper" libraries like `cleff`, `effectful`, and `bluefin`. These libraries tend to give good performance, can handle higher-order effects, but trade off a little safety to get the typelevel stuff down a bit. Of these, I currently favour `effectful` but am keeping an eye on `bluefin` (which is very close to `effectful` but with explicit handle-passing). The explicit handle-passing in `bluefin` seems to get the typelevel down a bit more in exchange for asking the user to write a little more boilerplate to explicitly pass handles around.
Effect systems are a trend that will go away. You can't statically guarantee that only, for example, the DB has side effects in a function. So what's the point? Haskell got it right in the first instance: IO or pure.
The point of effect systems isn't to stratify the behaviour of the operating system (it's the Wild West out there). It's to stratify the behaviour of your program. A function that has a DB effect isn't telling you that it will make Postgres queries (which can do anything!), it's telling you that it wants to make DB queries so you need to pass it a handler of a certain form to let it do that, hexagonal architecture style.
But you can also stratify in the other direction. ‘Pure’ functions aren't real outside of mathematics: every function can have side effects like allocating memory, possibly not terminating, internal (‘benevolent’) mutation, et cetera. When we talk about ‘pure’ functions we usually mean that they have only a particular set of effects that the language designer considered ‘safe enough’, where ‘enough’ is usually defined with reference to the ergonomic impact of making that effect explicit. Algebraic effects make effects (and importantly effect composition — we got here in the first place because we were fed up of monad transformers) more ergonomic to use, which means you can make more effects explicit without annoying your users.
I'm willing to bet the contrary: that IO-wrapper effect systems are the future of Haskell (particularly Bluefin, but then that's my library, so I would say that).
> You can't statically guarantee that only, for example, the DB has side effects in a function
I've always loved this paper. Great reading if you're interested in implementing an effect system from scratch. Though rather overkill if you're just interested in using one.
It was given to a Haskell audience, but not everyone knew Haskell, so I hope it's generally accessible. It describes how Oleg's work fits into the overall history of Haskell effect systems.
Wow, this is so cool that you did this and this showed up right now. There was an online book (soon to be published) by Xavier Leroy on the history of control mechanisms in programming languages with the last few chapters on Effect systems.
The acknowledgement section on that GitHub README mentions this paper.
* Polysemy: https://hackage.haskell.org/package/polysemy
* effectful: https://hackage.haskell.org/package/effectful
* Bluefin: https://hackage-content.haskell.org/package/bluefin/docs/Blu...
[Disclosure: Bluefin in my effect system]
`eff` is based on delimited continuations (which Alexis had to build into GHC), it is not using `Freer`. If you want to look at an effect system in Haskell that actually has been used in production AND is based on this paper then look at `freer-simple`: https://hackage.haskell.org/package/freer-simple
No it is not high performance, but neither are any other Haskell effect systems and performance is relative to your problem domain. It also has the benefit of being implemented very similarly to Oleg's paper making it a lot easier to learn from then most other options.
This is not true. IO-wrapper effect systems (in practice, effectful or Bluefin) have as good performance as Haskell's IO monad, that is to say as good as you can get in Haskell.
that said, your library is really cool. : )
You can look at my table of "A Comparison of Effect Systems at a Glance" to see all the tradeoffs:
https://hackage-content.haskell.org/package/bluefin-0.2.0.0/...
And thanks! Glad you like it. Feel free to reach out to me at any time if you'd like any help with it or have any questions or comments.
https://koka-lang.github.io/ https://effekt-lang.org/
Frank is pretty old now but perhaps a simpler implementation: https://github.com/frank-lang/frank
The ecosystem is massive.
Cons: TypeScript is a great type system but requires some investment to get the best out of it, it's also very verbose.
Pros: you have access to the entirety of the TypeScript ecosystem.
https://effect.website/
Crazy claim to make without providing any evidence
As a user, I think effect libraries in Haskell trade off between five main constraints:
* Typelevel wizardry
* Boilerplate
* Performance
* Ability to handle "higher-order" effects (e.g., `bracket`)
* Safety (e.g., not accidentally leaking effects beyond their scope)
The most compelling libraries I've seen from the industrial perspective are the "IO-wrapper" libraries like `cleff`, `effectful`, and `bluefin`. These libraries tend to give good performance, can handle higher-order effects, but trade off a little safety to get the typelevel stuff down a bit. Of these, I currently favour `effectful` but am keeping an eye on `bluefin` (which is very close to `effectful` but with explicit handle-passing). The explicit handle-passing in `bluefin` seems to get the typelevel down a bit more in exchange for asking the user to write a little more boilerplate to explicitly pass handles around.
But you can also stratify in the other direction. ‘Pure’ functions aren't real outside of mathematics: every function can have side effects like allocating memory, possibly not terminating, internal (‘benevolent’) mutation, et cetera. When we talk about ‘pure’ functions we usually mean that they have only a particular set of effects that the language designer considered ‘safe enough’, where ‘enough’ is usually defined with reference to the ergonomic impact of making that effect explicit. Algebraic effects make effects (and importantly effect composition — we got here in the first place because we were fed up of monad transformers) more ergonomic to use, which means you can make more effects explicit without annoying your users.
I'm willing to bet the contrary: that IO-wrapper effect systems are the future of Haskell (particularly Bluefin, but then that's my library, so I would say that).
> You can't statically guarantee that only, for example, the DB has side effects in a function
Yes, you absolutely can.
Particularly (2014): https://scholar.google.com/citations?view_op=view_citation&h...
It was given to a Haskell audience, but not everyone knew Haskell, so I hope it's generally accessible. It describes how Oleg's work fits into the overall history of Haskell effect systems.
Yes, Xavier's book was really interesting. It's here: https://xavierleroy.org/control-structures/
It's missing some subtleties of capability-based effect systems (which Bluefin is). Maybe I should write to him.