I highly recommend Oleg Kiselyov's talk titled "Having an Effect"[0] in which he talks about<p>- purely functional model of computation and its pitfalls<p>- Actor model, effectful programming with requests and responses and an implementation in Haskell.<p>- denotational semantics and combining effects. Once you have a model of your language, what if you want to extend it by adding another effect? It forces you to rewrite the semantics (and thus any interpreter of your language) completely. Taking using the effects-as-requests viewpoint, only the request and handler for an effect needs to be added or changed, and the rest untouched. This is known as "stable denotations".<p>- really evaluating what it means for an expression to be pure or effectful. Even variable reference should be considered an effect.<p>- different scoping rules in lambda calculus can be expressed in terms of effects! Creating a dynamic closure is not effectful, though applying it usually is, OTOH, creating a lexical closure is effectful but using it is not.<p>I think Haskell provides a good example of how a purely functional language can still express effectful computation. through a monadic interface. Though monad transformers have their share of problems when heavily nested (n^2 instances, performance), various effect system libraries are gaining traction.[2] On the bleeding edge of research there's languages like Frank[1] where the effect system is pervasive throughout the language.<p>[0] <a href="https://www.youtube.com/watch?v=GhERMBT7u4w" rel="nofollow">https://www.youtube.com/watch?v=GhERMBT7u4w</a><p>[1] <a href="https://github.com/frank-lang/frank" rel="nofollow">https://github.com/frank-lang/frank</a><p>[2] Implementing free monads from scratch, <a href="https://siraben.github.io/2020/02/20/free-monads.html" rel="nofollow">https://siraben.github.io/2020/02/20/free-monads.html</a>
I expect that, as with any other type system extension, the more granular your effects are, the more likely you are to run into a “what color is my function” problem. If you have a public API that declares certain effects, you’re stuck with those unless you break backward compatibility.<p>In a practical system, when writing a library and especially an abstract interface, you’d want to be careful what you promise and declare effects that you might need (but currently don’t use), just in case you will need them later.<p>It’s not that easy even to distinguish functions that can fail from those that can’t, if you’re trying to anticipate how a system will evolve. Something that’s in-memory now might change to being done over the network later.
I've had this idea of "dynamic returns" (akin to dynamic scope) in my head for a while. Reading this, it feels like a dynamically typed companion to effect systems.<p>The idea of a dynamic return is just to give a formal way to accumulate things during a set of function calls, without having every function to be aware of what might be happening. In Python context managers are often used for this (e.g., contextlib.redirect_stdout to capture stdout), but thinking about it as another kind of return value instead of "capturing" would be an improvement IMHO. (You have to "capture" when hardcoded imperative code later needs to be retrofitted, but as it is retrofitting is all we have.)<p>But dynamic returns aren't quite like an effect system unless you also create something more-or-less like a transaction or a changeset. We usually think about transactions as simply a way to rollback in case of an error, but as a changeset there's all kinds of interesting auditing and logging and debugging possibilities. E.g., if your effect is writing to stdout, you could rewrite all those changes (e.g., apply a filter, or add a text prefix to each line).
> As far as I can tell no one uses this language [Koka] for anything, however it is downloadable and quite usable to explore these ideas.<p>I believe the typesetting tool Madoko[1] is implemented in Koka, though in fairness Daan Leijen developed both Koka and Madoko.<p>[1] <a href="https://github.com/koka-lang/madoko" rel="nofollow">https://github.com/koka-lang/madoko</a>
Ocaml (almost ?) has it.
<a href="https://www.janestreet.com/tech-talks/effective-programming/" rel="nofollow">https://www.janestreet.com/tech-talks/effective-programming/</a>
There's some interesting research and ideas here, but it does seem like monads "ate everything for lunch" back in the late 1990s and 2000s when it comes to encoding effects, probably because monads are a bit more ergonomic (which seems like a weird thing to say, given the reputation monads have for being abstract nonsense). So effect systems didn't get as much research as everyone was interested in monads, and now that monads have dried up a bit as a field of research for encoding effects, I'm interested to see what other systems people invent.
It's not just about marking regions and checking them, "effect systems are fundamentally about dynamic dispatch (separating effect from effect handler)" Alexis King
I was curious about this function:<p><pre><code> fun addRefs(
a : forall<h> ref<h,int>,
b : forall<h> ref<h,int>
) : total ()
{
a := 10;
b := 20;
return (!a + !b);
}
</code></pre>
Why is it total instead of st<h>? Won't this have a side effect of setting the references?
Arrow Fx implement this idea for Kotlin ->
<a href="https://arrow-kt.io/docs/fx/" rel="nofollow">https://arrow-kt.io/docs/fx/</a>