Monads are everywhere... Maybe that's bad? by Till Schröder

preview_player
Показать описание
Till discusses the use of monads as a pattern for handling effects and chaining functions, with examples from various programming languages like JavaScript, Haskell, and C#. Monads, which can be thought of as a way to overload the semicolon, provide a more flexible way to handle errors and chain functions with effects. However, monads have challenges, such as the requirement for having the same error type for monadic computations and the complexity of implementing them in some languages.

Till also introduces the concept of algebraic effects as an alternative to monads, which can handle side effects and exceptions in a more user-friendly way but are more complex to implement. Despite the challenges, Till expresses his fascination with the history of programming languages and his enjoyment of experimenting with various languages.

Till Schröder

Links, about haskell and monads:

Algebraic Effects:

Mentioned languages with algebraic effects:

Chapters:
00:00 Welcome by Magnus Sedlacek
00:39 Thanks Ada Beat for sponsoring the video stream
02:29 Introduction of Till Schröder
02:38 Introduction
02:40 Let’s get practical: Checking an email address
08:46 Alternative: a result type
10:25 This is a pattern (a monad)
12:36 What does this mean? Monads are a way to overload the semicolon operator
15:08 Monads are everywhere (JavaScript, C#, Rust, C++)
17:48 Why are monads everywhere?
26:00 Maybe that’s bad?
30:54 A possible solution
33:40 Effect wish list
38:27 Algebraic effects
40:42 But how could algebraic effects be implemented?
44:44 That’s it – a broad overview of monads and algebraic effects
45:24 Questions

Video sponsor – Ada Beat

#funcprogsweden
Рекомендации по теме
Комментарии
Автор

Aside from all the kind words from others, which I support, in particular I want to compliment you on the sound quality. I wish everyone had their audio quality this good. I have a hearing problem so usually I have to rely somewhat on subtitles. Not here, so I'm very happy. Much thanks, and also for the high quality presentation.

Ancipital_
Автор

This is the most understandable explanation of Monads I ever heard.

danchatka
Автор

Good talk on explaining the fundamentals of monads. You're a good presenter!

KurtMueller
Автор

On the beginning of the second part: in Rust there are libs for that problem such as 'anyhow' and others.
I started using 'error-stack' recently, works pretty nice 😊

fullmaster
Автор

You did a great job motivating the idea behind algebraic effects. Thanks!

daniel-wificidr
Автор

BROTHER, YOU ARE THE BEST!!! You oooh really helped me!! THANK YOU VERY MUCH!

shamimunnaherrumi
Автор

best content around this topic! well exposed and very interesting, thank you!

rascio
Автор

What is the presentation software being used here? It's pretty nice and so easy to accompany

zellator
Автор

Awesome presentation! There's so much to learn in technology, I love it.

FourTetTrack
Автор

Surprised Lisp didn't come up. The central problem is that we really want a degree of control over how our code is compiled, so we sort of need a handle into the compiler. A monad is effectively a lightweight user defined language inside a prescribed language. While making these is pretty simple, making tooling that is able to combine them and manage them without any dedicated support from the underlying language will always be hell. Lisp is basically "write your own compiler", so will always be interesting for this sort of thing.
As a side note; A list parser that takes a function as it's last element, and regards a semicolon as a non-consuming closing bracket is already quite interesting. Basically when you meet a semicolon you treat it as a closing bracket, but also backtrack and add another opening bracket when you hit what would be its partner. ( a; (b) ; c) would be equivalent to (((a ) (b)) c), as both semicolons track back to the bracket before the 'a'. The idea is that your program starts with an opening description of state, and each line describes a function on that state. The semicolon is partially being used to make it so the programmer doesn't have to keep track of how deep it goes, but it also lets the parser treat it as imperative code despite being pure functional.
I have to say I fundamentally disagree with this on whether there should be a difference between 'map' and 'then'. When writing initial code I do not want to have to be thinking about corner cases, so I really don't want to be forced to think about whether a particular function can throw or not. Your solution later is better. I want to be able to query the functions and ask specific questions such as "do you throw", "do you allocate", "are you thread safe", "are you safe for user inputs". When I am looking over my code for thread safety, I don't want multiple keywords that only differ in terms of some other specific questions, as it is just noise. I want my language to support my IDE in telling me the details of what I have written, not test my memory of random details.

agsystems
Автор

Such a great and interesting talk. when talking about algebraic effects I remembered the Flix programming language, which does have some of that, but only limited to pure unpure, at least the last time I looked. But the idea Is really cool

racerand
Автор

Nice. Love the balance between what is and what could be.

I'm not a fan of exceptions, so in those cases where I'd want to return a value anyway, just return a different value? Or run a different function? Not sure about this use-case.

grawss
Автор

A mini comment about the audio. I feel the audio levels are not very consistent and go from quite soft to high to soft again. I'm not an audio expert, but I wonder if putting a compressor would help keeping a more balanced level.

FourTetTrack
Автор

26:36 Implicit generic sum types would probably help here.

Example:

fn domainFromEmailAddress(A) Result[B, DomainFromEmailAddressError]
fn tldFromDomain(B) Result[C, TldFromDomainError]

fn Result.then[Ok, Err](fn (Result.Ok) Result[Ok, Err] ) Result[Ok, Err | Result.Err]


So when calling the return type would be "Result[C, DomainFromEmailAddressError | TldFromDomainError]"

I wonder, if there already is a language, which allows that. Rust doesn't. Probably Haskell or OCaml.

porky
Автор

Very interesting talk, I'm glad I got to discover a few things with it!

What's this language you mentioned at the very end? It sounded like "qbml" or "gbml", but neither me nor the youtube captions could quite catch that

shadamethyst
Автор

35:00 effect wish list sounds a bit like what zig does with the explicit allocator passing, and try keyword.

minecraftermad
Автор

leave it to the guy who ~dislikes monads to give you the best description of what they are :D
- Everyone else explaining them just seem excited they understood it. You don't truly understand something, until you see it's flaws and better alternatives, and are willing to take the full context in.

Verrisin
Автор

Really not a fan of the idea of "try->throw->catch-> try again inside the function that threw" idea near the end, that sounds like itd be extremely hard to reason through. Maybe resumes that affect the control flow of the thrower should explicitly be passed in as an argument and if they dont apply they go back up as normal and if they do they try the passed in thing

KylerAce
Автор

hmm... algebraic effects. I've been designing a language as a hobby for years (unlikely I will ever make it) and this is pretty similar to ideas I had ... (among many other on my wish list)

Verrisin
Автор

Great talk, I really enjoyed it! I have one comment -

There is a caveat regarding the idea of "overloading semi-colons". In a strongly typed language, the "." operator on a type (or member functions, class functions... whatever really) requires a non-void type. To chain a statement, you're calling another "." operator on the returned type. The semi-colon delimiter does not necessarily have this constraint... for instance, you can follow up any semi-colon with a "goto" or "jump" statement in something like assembly or permitting languages. This is not a method called on a returned type.

I'd say that the sentiment is half-right. It does overload the semi-colon operator given that the next statement is operating on the returned type from the previous statement.

Anyhow, I'm nitpicking - this was a really good talk.

AndrewCodeDev