3 ms·
> Considering how much we hear about monads and macros compared to how much they are actually used That’s users. That’s not what I meant by the PL community. I
by WastingMyTime89 5y ago
> Considering how much we hear about monads and macros compared to how much they are actually used
That’s users. That’s not what I meant by the PL community. I was talking about people actually working on PL.
Monads and macros are both old news and not particularly exciting. I know they regularly crop up on HN. I find that a bit sad because actually exciting things happening in PL like effect systems rarely do.
- Zababa 5y agoThat's fair. I've seen a few mentions of Koka and OCaml 5.0 is going to have effects, though both are relatively niche. I was expecting to hear more about linear types too, I feel like one or two years ago (relatively) lots of people were talking about them, but I haven't seen much coming out of it.
- auggierose 5y agoI've been hearing about effect systems for a long time (decades ?) as well. I don't find them exciting at all. You kind of counter your own argument ...
- WastingMyTime89 5y agoResearch started more than twenty years ago but actual applications in programming languages you might use are relatively recent. If you find monads exciting but effect systems boring there is little I can do for you.
- zozbot234 5y agoLawvere theories have been around since the 1960s, so a lot older than 20 years.
- Ericson2314 5y agoAgreed I'm completely sick of effect systems too. It's entirely the wrong framing of the problem.
- WastingMyTime89 5y agoI would actually be glade if you could enlighten us about why effect systems are the wrong framing and what you would consider to be the right one.
- Ericson2314 5y agoSure. So I've spent a lot of time working with FRP things, e.g. with https://hackage.haskell.org/package/reflex https://hackage.haskell.org/package/reflex with the github.com/obsidiansystems/obelisk/ web framework. While FRP was sort of deemed to hard / a dead end in the early 2020s, it works well for me, and I still consider it viable. I dislike effects because superficially they are about similar problems ("My whole-program needs side effects") but no amount of effects system stuff is going to ever get you to anything like FRP. In particular, the eeffects mind seems to be pretty narrow, something like: "I have a bunch of regular-seeming code that does some 'extra stuff', and I need to manage those extra capabilities in a modular way that respects the principle of least authority." By contrast, the FRP approach rejects the premise that: - The programs basically look more or less "normal", but with (good) restrictions on what you can do - The effects are something "side" or "extra". It's hard to say exactly what it is about instead, but some guidelines might be: - Don't just decompose a program into terminating parts (like terminating callbacks + magic event look). Embrase non-termination (well, co-termination), and think of new ways to be modular that don't carry over from terminating whole programs. - Think in terms of "flows", be like a plumber. Try to directory program the steady state in terms of the large scale architecture, and not a regular functional--imperative program that "carries out" out the flows as a spec. - - Actor-model-type stuff is wrong for focusing on the "nodes not edges". We should have simple components but rich networks. - Try to find structure not in the effects themselves, but how you intended to use them. If the effects form sinks/sources, then have them be pipeline end pieces that compose just like the the pure middle pieces. - Calculus is good for programming, after all. Time derivatives / time integrals are at very least good metaphors. We should all go learn more Control Theory for more things than "memory pressure". I hope this helps.
- Ericson2314 5y ago
- Ericson2314 5y agoPeople continue to study metaprogramming / representations of syntax especially with binding, and category theory applications to programming. Yes, the blog post is bad and just rehashing old aphorisms, but that doesn't mean the broader research agenda stalled out.
- isaacimagine 5y agoI've done a lot of work with effect systems, continuations, and concurrency. I guess I'd like to rant about it a bit. An effect signals an interruption of the call stack to do some work. Like an exception, it 'unwinds' to the nearest handler (think catch block), and executes the effect; after this point, the effect can either resume, or continue from the catching handler. This ability to resume is exactly a continuation. In fact, a lot of effectful languages (Koka, Effekt) model it as exactly that. It's important that this continuation is only valid within the scope of the handler; this is equivalent to a delimited continuation. Full, as opposed to delimited continuations, on the other hand, can be invoked from any scope. At the least, this requires a copy of the stack, or that plus a subset of the heap. (Functional languages with immutable datatypes kinda get a free pass on this one, but only barely.) Because delimited continuations can only be invoked in nondestructive contexts, they do not require making a copy of the stack (in fact, we don't even need to unwind the stack at all.) Except in most cases, we only resume once, and this—a single-shot delimited continuation—is exactly a coroutine, a feature common in many languages. But there's more: remember that to execute an effect, a handler has to be located. This handler is found by searching backward through the stack. If this sounds familiar, it's because this type of name resolution is known as dynamic scoping (as opposed to lexical scoping). The ties here run deep. We all know that closures are a poor man's objects. That's easy too wrap your head around. But I think we'll soon realize that effects are just a poor man's coroutines are just a poor man's dynamic scoping are just a poor man's delimited continuations are just a poor man's resumable exceptions, and I'm not sure where the strange loop ends. But there's a light at the end of the tunnel. What do effect systems have to offer above these other approaches? I'd say there are 3 things: 1. Static typing. Unlike coroutines, resumable exceptions, etc. The type of effects used in a function can be automatically inferred. A lot of these other systems operate under a dynamic assumption, or require an explicit annotation of types at some point. With algebraic effects, the row of used effects can be statically determined with no additional annotations by the programmer. 2. Row-based composition. Building off our last point, effects build a sort of open enumeration over the possible effects raisable at a given point, a row. This row can be generic over further effects, which means that effectful higher-order functions can be composed. This full row can be known at compile time, so that the programmer can know the full set of potential effects in scope at each point in the program. Because these row-based constructions are usually built around a single monad (i.e. the free monad), different effects can be composed without running into traditional monadic composition issues. 3. System Injection. What happens when an effect does not have a handler in scope? This could just be an error at compile time, but this opens up another possibility. Instead of raising an error, unhandled effects are handed off to the host runtime for evaluation. Quite sensibly, effect systems are a really neat way not only to model concurrency, but actual honest-to-goodness side effects. An effect-based virtual machine is really just a glorified effect generator. The host runtime can also expose additional APIs, like an FFI, IO, or access to threads. Most importantly, because these 'syscalls,' so to speak, are just effects, they can be overridden. You could create a handler that rolls native threading requests into single threads, or redirects output to stdout to log files or the network. This has been quite the rambly rant. I've just been thinking about this a lot recently and need to get it all out of my system