The Death of Monads? Direct Style Algebraic Effects

  Рет қаралды 19,368

Impure Pics

Impure Pics

Күн бұрын

Пікірлер: 77
@impurepics
@impurepics 6 ай бұрын
In a blog post form: www.unison-lang.org/docs/fundamentals/abilities/for-monadically-inclined/
@Slate245Ivanovo
@Slate245Ivanovo 6 ай бұрын
Was I just tricked into watching a Haskell vid by a funny thumbnail?
@mtaur4113
@mtaur4113 6 ай бұрын
A monad is a monoid in the category of endofunctors.
@Slate245Ivanovo
@Slate245Ivanovo 6 ай бұрын
@@mtaur4113 I always thought it to be a burrito though
@JoeTaber
@JoeTaber 6 ай бұрын
@@Slate245Ivanovo The channel's profile photo agrees with you.
@jean-michelgilbert8136
@jean-michelgilbert8136 6 ай бұрын
Yep. I have the same feeling of being tricked too. I usually avoid Haskell and FP. There's already enough new things happening in the C++ world.
@8panthermodern2
@8panthermodern2 6 ай бұрын
Just the KZbin algorithm pushing another extremist ideology. Sure, it starts with the memes. "Monads, lol", you say to yourself. Next thing you know you are holding your scrum meetings hostage with long tirades about type theory.
@JanilGarciaJr
@JanilGarciaJr 6 ай бұрын
Just found out about ocaml's effect handlers yesterday, the timing of this video is just amazing lol Unison looks really cool, I might check it out. I think algebraic effects are here to stay from the little I saw. I honestly can see mainstream languages implementing this 10/20 years from now.
@NostraDavid2
@NostraDavid2 6 ай бұрын
All I know about Monads (other than that they are a Monoid in the Category of Endofunctors) is that they are basically a black box that holds state (of your game, a file, anything, really). You pass that black box into a function. The function unwraps the black box and does something based on the input state, constructs a new black box to hold the new state and passes that black box to the next function. I have no idea if this explanation is even correct, but it's what my peabrain has come up with after watching 451 videos, and reading 2501 Wikipedia articles, about Monads and what REALLY TRULY FINALLY are.
@cgibbard
@cgibbard 6 ай бұрын
That's really only a description of the state monad in particular, where you implement stateful computations by using pure mathematical functions (i.e. the sort you learned about in math where there's only one possible output for any given input) by taking an initial state and transforming it into a final state along with some result. The monad abstraction also captures a broader pattern of defining some sort of "computations" having a result, where you have certain primitive operations that allow us to build a common library of "control flow" operations in terms of that. So you can, for instance, define how a for-each loop ought to work in any monad, as an ordinary library function. Then upon finding out that your parsing library defines a monad of parsers (which might in addition to implementing state, also implement backtracking), you get to make use of the for-each loop that was already defined in the library to concatenate together a bunch of parsers (and a lot of other useful control-flow-like things besides). The monad abstraction only really makes sense as an abstraction once you look at a bunch of examples. On top of that, the code for it in languages that aren't similar to Haskell (in particular, it kind of demands static typing + something like type classes that let you pick implementations of things based on the type of result they need to produce, not just the type of the input) is usually going to be ugly and/or crippled in some way which reduces the usefulness. They're super useful and good in Haskell, and I feel like this video strawmanned the monad code a good bit (look how ugly this is if I write it in a way that nobody does), but I wouldn't blame, say, a Ruby or Java programmer for not using monads, because you just don't have the right sort of polymorphism in those languages to get the benefit from it conveniently.
@samuraijosh1595
@samuraijosh1595 4 ай бұрын
@@cgibbard Monads in Haskell seemed to be designed in such a way that you're punished for even using by them even though they exist as a potential option. The fact that all of your stateful computations have to always exist in the ST monad is just so not easy to deal with. Yes, sometimes you can extract the value from ST but if only it's a simple immutable type which doesnt have the state s token embedded in its kind signature. Very very annoying abstraction in my opinion. after trying to integrate some mutable types in complex type at the type level, I just gave up and opted for immutable alternatives.
@cgibbard
@cgibbard 4 ай бұрын
@@samuraijosh1595 If the type of thing you're returning from ST has an 's' in it, that means it contains references to mutable variables. There are ways to smuggle such values out, but they are useless, because if you were to do another runST to get back into the ST monad to access them again, the 's' would be treated as distinct by the typechecker, and it wouldn't let you access them. This is what makes runST safe and doesn't cause it to just break the entire evaluation model of the language. If you want to return the contents of those mutable variables instead, you just want to use readSTRef at the end to get the values out. (If it's an array, you might instead use runSTArray.) But that said, ST is pretty niche indeed, and yeah, most of the time, you're better off just writing a functional program to compute what you were trying to compute, I super agree about that part. That says very little about whether monads in general are a good abstraction though. I think the first example of a monad which really convinced me that it's a good idea was parsing monads. You can have a type (Parser t) of parsers which consume some portion of an input string in order to produce results of type t, and combine those together using the monad operations, and stuff like forA which was ordinarily a for-each loop in stuff like IO or ST, turns into a way to concatenate a bunch of parsers together and collect the results. Other really nice examples often have to do with contexts where you want some effects, but can't or don't want to allow all of them. A monad for doing database or memory transactions that might need to be rolled back and retried later might want to prevent various other sorts of effects from occurring because you can't un-fire the missiles. I do a lot of work with functional reactive programming stuff using Reflex (building web and mobile apps mostly, some desktop on occasion). In that context, we have some monads where the actions are implicitly a function of the present time (but what that time actually is, is never mentioned or specified because the system as a whole at a low level is implementing things with IORefs and carefully providing the illusion that updates happen in lockstep globally and dealing with all the simultaneity). There, the monad operations serve as a way of sticking together things which vary over time in various senses to make more complicated things which vary over time. The simplest of those is probably (Behavior a) which is the type of things which vary over time, and have a value of type a whenever you'd care to look, but can't notify you of when they change: it's consistent with the laws of the system that they may even change continuously. Another is (Dynamic a) which is like a step function that only changes at discrete moments in time and you can tell when. Those are both monads. The real point of it all is that this idea of having a type of computations of some sort that will later be run to produce values is a fairly common functional programming abstraction. By recognizing it, we get to reuse things like all the control flow stuff in Control.Monad and gadgets like monad transformers, without needing to rebuild that stuff for each new monad, so it's quicker to get these sorts of domain-specific libraries fleshed out.
@georgH
@georgH 6 ай бұрын
The thumbnail cracked me 🤣🤣🤣
@capability-snob
@capability-snob 6 ай бұрын
My goodness. A video on algebraic effects 😮 Nicely done.
@OhsoLosoo
@OhsoLosoo 6 ай бұрын
No please guys don’t change anything. I’m just starting to get the hang of functional programming, I recently have began to study category theory & its implementation in computer science 😭😭😭
@impurepics
@impurepics 6 ай бұрын
You don't need to study category theory to write/understand functional programming. I would only recommend category theory if you think it's fun.
@nanman_chief
@nanman_chief 4 ай бұрын
I'm not sure if this comment is a joke (sorry, I often misunderstand humor on the internet, so I need to check). If it's not a joke, I have some good news for you: Effect handlers are essentially based on category theory. They are just so well-packaged that you don't need to know what Yoneda lemma is to happily use them for programming. If you're deeply interested in the theory, you can read Gordon Plotkin papers "Algebraic Operations and Generic Effects" and "Handling Algebraic Effects".
@justinhj1
@justinhj1 3 ай бұрын
Beautifully produced and content rich, thanks!
@woobilicious.
@woobilicious. 6 ай бұрын
Your assessment that Haskell is non-strict and Monads "help" is wrong, The point of a Monad is to handle side effects/passing the "world" around on the side in a pure language, they allow you to turn a function "(World, a) → World" in to a "a → (World → World)", monads allow you to write functions that return functions with the world as the only argument, the IO Monad is not strict and only some calls force evaluation, the best way to think about it is that IO is a output based promise system, `a ← readLine` doesn't run *until* you use the `a` in some sort of output, they do a poor job of sequencing effects. And you will get intermittently familiar with forcing evaluation in the correct order using bang patterns (using !), unboxed types and `seq` and `deepseq` all have varying effects on thunk evaluation ordering. It's probably the biggest pain point of Haskell.
@apteropith
@apteropith 6 ай бұрын
well, it's true for side-effects that are internal to haskell, where it knows all the dependencies, but that's a fair point that the language would need still extra help with IO side-effects, since there's little way for it to tell if one IO action is meant to be _externally_ "dependent" on another i wonder what the best way to handle that is! haskell is very neat and demonstrates some very good ideas, but i find it deeply imperfect in some spots (so i very quickly lost most of my interest in it, oops)
@samuraijosh1595
@samuraijosh1595 4 ай бұрын
@@apteropith the monad abstractions Haskellers came up with to handle mutable types are fine in theory/concept but they're executed so badly in my opinion.
@nythrox3047
@nythrox3047 6 ай бұрын
Thank you for bringing up the important stuff
@apteropith
@apteropith 6 ай бұрын
i learned about monads in haskell a few years ago; while i did appreciate the power of the very fancy wrapping & unwrapping of values which monads can provide, my biggest takeaway was actually that the do-blocks with the bind operators are just a form of continuation-passing style, and should never have been confined to monads the bind operator really should default to simpler function-composition when a monad is not present; there is little reason for it not to, and not doing so damages the flexibility and utility of the do-block's syntax - i might go so far as saying it damages the elegance of the language
@locker47
@locker47 6 ай бұрын
Could you show an example of converting a piece of code that uses monadic effects into algebraic effects and show the pros/cons of each? I'm trying to wrap my head around the ergonomics of tagless final and algebraic effects (e.g., Cats vs. Kyo), and when should we prefer one over the other. If there is a blog post on this I would love to read it!
@generalyoutubewatching5286
@generalyoutubewatching5286 Ай бұрын
This one video made me subscribe!!! Love how u pointed out that Haskell was lazy and hence needs monad for io
@impurepics
@impurepics Ай бұрын
@@generalyoutubewatching5286 Thanks, I’m glad you enjoyed it; bunch of people hated that part 😀
@DrewryPope
@DrewryPope 6 ай бұрын
Laziness in Haskell on the Tweag channel is very good
@impurepics
@impurepics 6 ай бұрын
Agree
@ywenp
@ywenp 6 ай бұрын
5:00 That is a bit of a strawman and you know it :) That's what the syntactic sugar of Haskell's do-notation is for, and it's very straightforward. Don't get me wrong: the rest of your points remain valid, but the drawbacks of using monads don't lie in the syntactic department. You could say though that's is a bit of a bummer to have two different syntaxes for pure code and monadic code, but this gives the advantage of making it immediately clear when some part of the code is not using a standard control flow (which is kind of an important thing to know when you look at code). 15:34 If by "static control flow" you mean "being able to see the whole graph of computations before actually running it" (given you use build systems as an example, I have a sense this is what you mean), then you cannot do that with Monads either. Monadic computations are opaque by essence, they produce a dynamic computation graph just like direct style. You need other control flow structures for that (namely Applicative functors or Arrows).
@impurepics
@impurepics 6 ай бұрын
Any extra syntax (or even sugar) is a cognitive overhead. And some people think that do-notation is even worse. We emulate strict languages and the idea of execution during the evaluation (one more thing to think about) to build programs as values, which will then be executed. Another syntax - another level overhead. You're right. In the video, I said monads "and friends" because I didn't want to bring another player all of a sudden. I realized it wasn't a good idea, in the blog post I explicitly bring up Applicatives.
@ywenp
@ywenp 6 ай бұрын
> Any extra syntax (or even sugar) is a cognitive overhead. Yes, it's true. But it's just one criterion out of many over which to evaluate such a design choice. In any case, my point was that it does the job of tidying up monadic code so you don't have to do the heavy lambda-juggling you were showing.
@isodoubIet
@isodoubIet 6 ай бұрын
If it were a strawman, there wouldn't be as many monad tutorials as there are, nor would there be tens as many people commenting some variation of "I still don't get it" underneath every single one. One of the most fun things to do is to ask what are Monads in a Haskell forum and watch the magic happen as people start fighting over one another's misconceptions.
@zackyezek3760
@zackyezek3760 6 ай бұрын
What modern programming languages really need is explicit syntax for defining tasks- atomic chunks of work with explicit inputs and outputs, the dependencies between them, plus any other specific runtime or state machine conditions the actual machine running the code should honor (e.g. error handling). Basically, doing for the state machine of a program- the control flow, async logic, parallel processing- what the introduction of objects (“classes” or “object oriented programming”) did for the data. Manually writing threads or low level async handoffs like semaphores and locks is really the state machine equivalent of directly writing assembly. Monads are like the structs in the original K&R C; they’re a significant and powerful improvement upon straight assembly and primitive types, but far from the massively more powerful (and complex) full blown objects of C++ or Python classes. It’s why their rampant (ab)use is everywhere, why so much custom boilerplate is piled atop them, and why a lot of that code is reminiscent of the old school C boilerplate you write to obtain de facto vtables and ‘member functions for C structs. Because it’s the equivalent of full classes that we need for the state machine, and we don’t have those yet.
@i-am-the-slime
@i-am-the-slime 6 ай бұрын
Very good effects. I handled them like a champ.
@jenreiss3107
@jenreiss3107 6 ай бұрын
I really like the fused-effects library, as fusion laws allow the effect handler to fuse effect types so that evaluation only requires a single AST traversal, rather than the O(n) for more standard free monads. granted, it is built on a giant tower of abstractions that is very tough to grok, but once you do, it is incredibly powerful
@poklet
@poklet 6 ай бұрын
Do these methods compose well? For example if an existing codebase was written in a monadic style, is it possible to add code with Abilities or Direct-Style? If they do compose, what’s the mental overhead like in juggling all these styles in one code base?
@impurepics
@impurepics 6 ай бұрын
Depends on the language/implementation. Shouldn't be a big problem, as long as there are functions to convert from one to another. For example, in Unison, you can convert the "monadic" Either to the Exception ability and vice versa. So, if you have a function that returns an Either and another that has Exception, and want to use/compose them together, you might need to convert one of them first (e.g., using Either.toException). But, yeah, mixing styles always comes with overhead. share.unison-lang.org/@unison/base/code/releases/2.20.0/latest/terms/@5mqjoauctm02dlqdc10cc66relu40997d6o1u8fj7vv7g0i2mtacjc83afqhuekll1gkqr9vv4lq7aenanq4kf53kcce4l1srr6ip08
@Heater-v1.0.0
@Heater-v1.0.0 6 ай бұрын
Wow! I have been programming for 40 years. On all kinds of projects from time embedded systems to desktop CAD systems. In all kind of languages from assembler up. Ten years ago I first heard the word "monad". Despite multiple efforts at understanding it I still don't get it. Now this, I have no clue what the words even mean or why one would want such a thing. Luckily such cognitive overhead is not required to actually get useful things done.
@hath995
@hath995 6 ай бұрын
Monads are the minimal structure needed to do function composition of wrapped/decorated data types. You can compose easily a function from integer to string and a function string to boolean to get a function from integer to boolean for example. Now if you had functions from integer to Boxed and one from string to Boxed, where Boxed is some container type like Array or Optional then you can't compose these functions naturally. Roughly a monad is just an interface on your objects that provides a method called chain or flatMap that can take a Boxed and a function from T to Box to produce a Boxed.
@diribigal
@diribigal 6 ай бұрын
This reminds me of "Hold" in Wolfram Language where delaying evaluation (really substitution) is not weird, but the syntax overhead is a lot compared to the parentheses and ticks shown in this video. I have to check out Unison now!
@federicoagustinsawadyoconn2716
@federicoagustinsawadyoconn2716 5 ай бұрын
Some things I read in the comments or see in the video make me realize that some poeple analyze Haskell as if its computing model were the same as other traditional languages, when it is not. Referential transparency, in the computing model that Haskell chooses to have, is extremely important, so it is not that optional. That is the main reason why the language is lazy. And it is the main reason why one also chooses to program in Haskell. Algebraic structures like monads or applicative functors are excellent in terms of maintaining equational reasoning more than other options, so they are not criticizable in the same way as a feature in a imperative language. They are not just a feature that solves something from a utilitarian point of view neither, because they are a mathematical solution for mantaining clear reasoning about pure code, which in Haskell is more important than in other languages. I know that many want features in Haskell that are also utilitarian, which is not bad, but please understand that the language was not designed for that, so you have to be aware of what I mentioned before when analyzing some of the pain points of the language.
@hantuchblau
@hantuchblau 6 ай бұрын
Great video! I still find it funny that java has almost everything you need. Checked exceptions for effect tracking, thread local state for handlers, the new virtual thread stuff for control flow manipulation. Pity java surface syntax cannot write down type unions in most places, though. One point I didn't understand is why 'user-defined effects' were rated better for Abilities than for Monads. In my experience multishot delimited continuations are hard to make efficient, so you gotta work much harder to build good nondeterministic effects. Many implementations just give up and forbid multishot effects entirely. With mtl-style final embeddings CPS nondeterminism just works.
@ZeroG
@ZeroG 6 ай бұрын
I do not understand what is meant by "effect handlerl
@impurepics
@impurepics 6 ай бұрын
Sorry, didn't have time to go into it. Here are a few good pointers: * www.unison-lang.org/docs/fundamentals/abilities/using-abilities-pt2/ * v2.ocaml.org/manual/effects.html * koka-lang.github.io/koka/doc/book.html#sec-handlers * effekt-lang.org/docs/concepts/effect-handlers
@ZeroG
@ZeroG 6 ай бұрын
How is this different than what I can do in Swift already, using closures?
@capability-snob
@capability-snob 6 ай бұрын
Effect handlers may or may not choose to return back to the caller, hence the comparison to exception handling and call/cc.
@JanilGarciaJr
@JanilGarciaJr 6 ай бұрын
How is it similar to closures?
@u9vata
@u9vata 6 ай бұрын
Good content - but for solving the same things, I would any day take somthing like zig comptime instead or metaprogramming in general... Too taxing on the programmer to do it these ways still.
@estebanmarin002
@estebanmarin002 6 ай бұрын
wow, loved the explaination
@hansisbrucker813
@hansisbrucker813 6 ай бұрын
I wonder if it can be implemented in Common Lisp using macros 🤔
@mskiptr
@mskiptr 6 ай бұрын
I'm at 7:00 and I have to say it's a really nice overview, but I absolutely cannot agree with the conclusions so far
@wildwestrom
@wildwestrom 6 ай бұрын
I gotta figure out how I could translate this concept into Rust code. Maybe it'll result in better code?
@dansheppard2965
@dansheppard2965 6 ай бұрын
Mercury's "modes" always seemed a neat middle ground for side-effects. I'm not sure why they haven't caught on.
@Nikolas_Davis
@Nikolas_Davis 6 ай бұрын
2:05 shouldn't these be "\_" instead of "\\_" ? (Absolute noob in haskell; still, I think that's a typo)
@luvincste
@luvincste 6 ай бұрын
i didn't really understand much of this
@herrbonk3635
@herrbonk3635 2 ай бұрын
You are not supposed to.
@hindigente
@hindigente 6 ай бұрын
Went in thinking this was about category theory. :D
@mattmmilli8287
@mattmmilli8287 6 ай бұрын
This is just a methodology that applies to any language ?
@maxmustermann5590
@maxmustermann5590 3 ай бұрын
I was told you were the burrito made me spit out my coffee my guy
@8panthermodern2
@8panthermodern2 6 ай бұрын
Just the KZbin algorithm radicalizing another generation
@angeloceccato
@angeloceccato 6 ай бұрын
Figoooooo, great video¡¡¡
@MikkoRantalainen
@MikkoRantalainen 5 ай бұрын
15:52 I would argue that neither monads for "abilities" are teachable. Definitely not easy to teach as direct style procedural programming.
@BenHutchison
@BenHutchison 6 ай бұрын
I'm sceptical of the claim that writing effect handlers is easier than monads. Better leave such claims for a future video where you have time to go into the topic and hopefully show some evidence for your claims. Which I personally think will in the long arc of history end up being recognised as "about equivalent" to monads.
@impurepics
@impurepics 6 ай бұрын
Yeah, I'd like to go deeper into the topic. For now, I assumed that an average viewer/reader either has no experience writing production/real-world monads or already knows that it's not that easy (I'm not talking about monad-tutorials-like monads). So, the bar for the effect handlers is relatively low. Unison docs already has a good section on writing handlers: www.unison-lang.org/docs/fundamentals/abilities/writing-abilities/
@asdfghyter
@asdfghyter 6 ай бұрын
in my experience they are way easier to write. it’s generally straightforward, while monad transformer implementations are finicky and easy to get wrong (c.f. the many “ListT done right”) but the most important advantage in my opinion was missing: unlike monad transformers, effect systems generally aren’t order dependent, so you don’t need to be careful about stacking the transformers in the right order
@Taylor-rx4yb
@Taylor-rx4yb 6 ай бұрын
I love monads! But I am also a mathematician and I'm realizing this video isn't actually for me lol
@TaranovskiAlex
@TaranovskiAlex 6 ай бұрын
"a guy in a lab coat with a shank"...
@mojeimja
@mojeimja 6 ай бұрын
this all looks horrible :)
@herrbonk3635
@herrbonk3635 2 ай бұрын
Indeed. As complex as possible, instead of the opposite.
@vpatryshev
@vpatryshev Ай бұрын
This talk is really confusing, since it does not give an impression that the speaker knows what monads are. Weird.
@impurepics
@impurepics Ай бұрын
@@vpatryshev knowing what monads are and knowing why monads are used are two different things. I assumed people watching are familiar with the former, and the later is important for talking about a bigger picture
@JorgetePanete
@JorgetePanete 6 ай бұрын
I'm having a really hard time understanding your words and the automatic subtitles aren't helping
@impurepics
@impurepics 6 ай бұрын
I'm working on the blog post version. I'll share in a few days.
@impurepics
@impurepics 6 ай бұрын
You can read it here: www.unison-lang.org/docs/fundamentals/abilities/for-monadically-inclined/
[Haskell'23] The Evolution of Effects
1:06:11
ACM SIGPLAN
Рет қаралды 6 М.
New Gleam Just Dropped
25:33
ThePrimeTime
Рет қаралды 85 М.
World’s strongest WOMAN vs regular GIRLS
00:56
A4
Рет қаралды 22 МЛН
Perfect Pitch Challenge? Easy! 🎤😎| Free Fire Official
00:13
Garena Free Fire Global
Рет қаралды 65 МЛН
1, 2, 3, 4, 5, 6, 7, 8, 9 🙈⚽️
00:46
Celine Dept
Рет қаралды 66 МЛН
😜 #aminkavitaminka #aminokka #аминкавитаминка
00:14
Аминка Витаминка
Рет қаралды 2,8 МЛН
The Vim Experience
45:19
Bog
Рет қаралды 140 М.
What is a Monad? - The Last Monad Intro You'll Ever Need
15:48
走歪的工程師James
Рет қаралды 23 М.
What is a Monad? - Computerphile
21:50
Computerphile
Рет қаралды 607 М.
Okay but WTF is a MONAD?????? #SoME2
18:18
TheSTEMGamer
Рет қаралды 68 М.
A Simpler Way to See Results
19:17
Logan Smith
Рет қаралды 113 М.
What the Heck Are Monads?!
21:08
ArjanCodes
Рет қаралды 74 М.
[Advanced] On error handling in Functional Programming
15:14
Impure Pics
Рет қаралды 2 М.
Brief History of the Monad
21:18
Alchemy of Consciousness - Dennis W. Hauck
Рет қаралды 4,8 М.
Dynamic Programming isn't too hard. You just don't know what it is.
22:31
DecodingIntuition
Рет қаралды 191 М.
World’s strongest WOMAN vs regular GIRLS
00:56
A4
Рет қаралды 22 МЛН