News for hackers. Stuff that matters.
Re:Monads are too powerful: The Expressiveness Spectrum by SchemaLoad on Wednesday October 15, 2025 @06:03PM (#45598856)
I tried learning Haskell for a decent chunk of time and could make some stuff, but despite trying to learn, I still could not tell you what a monad actually is. All the explanations for it seemed to make no sense.
Re:Monads are too powerful: The Expressiveness Spectrum by ilikebits on Wednesday October 15, 2025 @06:48PM (#45599265)
Monads are a generalization of Promises. Each type in Monad defines their own `.then` in a different way. For promises, `.then` is defined as "run this function once you have this deferred value from the last promise". For optionals (`Maybe`), `.then` is defined as "run this function if the last optional had an actual value". For Either, `.then` is defined as "run this function if the last Either returned Right, otherwise early-return with the value from Left" (this is functional early-return, basically).
Re:Monads are too powerful: The Expressiveness Spectrum by bhaney on Wednesday October 15, 2025 @07:24PM (#45599561)
This is the first explanation of monads I've heard that makes intuitive sense to me and feels like it sufficiently captures the point. Unless I come back in a few hours to see a bunch of replies from uber-haskellers saying "no that's not what a monad is at all," then I'll consider my search for a good monad explanation to finally be over.
Re:Monads are too powerful: The Expressiveness Spectrum by tickettotranai on Wednesday October 15, 2025 @07:58PM (#45599881)
No I believe he's basically formally correct.

You need to be able to "wrap" values and then also "wrap" functions in the way you expect. That's literally it.

Btw, the list monad example is stupid imo and borderline misleading. The promise/nullable/Either examples are better. you "wrap" a function by putting it as the only value in a list, and "map" pretty much acts as your function wrapper, but technically this you need to jump through a couple hoops to make it monadic, and I'm just not sure the metaphor is helpful here

Re:Monads are too powerful: The Expressiveness Spectrum by internet_points on Thursday October 16, 2025 @05:05AM (#45603087)
Agree about the list monad. I have never used it in actual code. I always felt it was so arbitrary, and "implicit", in the sense that if you haven't learnt beforehand that it makes "joins", then it's certainly not obvious that it should work that way

    λ> do { a <- [1,2]; pure a; }
    [1,2]
    -- oh so it returns the list unchanged
    λ> do { a <- [1,2]; b <- [3,4]; pure a; }
    [1,1,2,2]
    -- no what is this spooky action at a distance
    λ> do { a <- [1,2]; b <- [3,4]; pure [a]; }
    [[1],[1],[2],[2]]
    -- ...
    λ> do { a <- [1,2]; b <- [3,4]; c <- []; pure [a]; }
    []
    λ> do { a <- [1,2]; b <- [3,4]; c <- [5]; pure [a,b,c]; }
    [[1,3,5],[1,4,5],[2,3,5],[2,4,5]]
Re:Monads are too powerful: The Expressiveness Spectrum by dllthomas on Thursday October 16, 2025 @02:16PM (#45608834)
For some monads the "wrap" gets awfully metaphorical (for State it's a function that produces the value and updated state, for Const there is no value, etc) but I don't think that's actually a problem, just a thing to be aware of. There is certainly no expectation that you can actually get your hands on the thing.

A bigger issue is that you're missing a piece. If you can "wrap" values and "wrap" functions such that they operate on wrapped values, you (probably) have a functor. To be a monad you also need to have the ability to turn multiple layers of wrapping into one layer of wrapping. For lists, that's "flatten".

I said "probably" above because there are rules these pieces need to follow to behave well. They're pretty simple but I don't think we need to dig into them at this level of discussion.

Re:Monads are too powerful: The Expressiveness Spectrum by tasuki on Wednesday October 15, 2025 @07:19PM (#45599525)
Promises? Even more generally, Monads are a generalization of Chaining.

(I'm trying very hard not to fall into the trying-to-explain-monads trap!)

Re:Monads are too powerful: The Expressiveness Spectrum by binary132 on Thursday October 16, 2025 @10:19AM (#45605665)
This is misleading IMO because Promise is a particular kind of monad but in general monads don’t necessarily have anything to do with asynchrony. It is a useful example though because some people are more familiar with the API of promises.

I might have some inaccuracies in how I state this since I’m not from a functional programming background, but I think of monads as an abstraction of chaining functions over a value such that each returned value can specify what further transformations it supports, and particularly in such a way that generic transformations (like sequence reversal) can easily be applied, and errors or empty values can be accounted for within the control flow.

I think sometimes people call this a “fluent API”, but I would never call it “a generalization of callbacks” or of promises.

Anyway there’s a much more mathematically precise way of stating it but this is my intuitive caveman way of thinking about it.

Re:Monads are too powerful: The Expressiveness Spectrum by ww520 on Wednesday October 15, 2025 @07:28PM (#45599588)
Monad is a pattern for constructing container types so that their instances can be used in chain operations safely. Given a value type, you can build a monad type wrapping the value type with a set of prescribed monadic functions. Instances of the monad type are called monadic values.

Example is best for illustration. I'll use a made-up syntax.

  // 'Maybe' is a monad type wrapping any value type T.
  class Maybe<T> {
    // The value type wrapped by the monadic value
    value: T;

    // A constructor to make a Maybe monadic value from a plain value T.
    // This is called 'unit' or 'return' in Haskell, or 'lift' in other languages.
    // It's really a constructor.
    static wrap(v: T) Maybe<T> {
        return new Maybe { value = v } 
    }

    // then() applies fn on the unwrapped value. fn returns a Maybe<T>.
    // This is called 'bind' in Haskell, or 'flatMap' in other languages.
    then(fn: (T) => Maybe<T>) Maybe<T> {
        return this.value == null ? Maybe.wrap(null) : fn(this.value);
    }
  }
That's it! That's all to to monad. You can use the same pattern to build other monadic types, like List<T>, Promise<T>, IO<T>, as long as the wrap() and then() functions are built accordingly. Back to this example, to use it,

  let a = Maybe<int>.wrap(4)                   // construct a monadic value
  let b = a.then(x => Maybe<int>.wrap(x + 1))  // add 1 to it
  let c = Maybe<int>.wrap(null)                // construct a null monadic value
  let d = c.then(x => Maybe<int>.wrap(x + 1))  // safely handle null; d is null

  let e = Maybe<int>.wrap(5)
    .then(x => Maybe<int>.wrap(x + 1))
    .then(x => Maybe<int>.wrap(x * 2))    // chain the calls

  let f = Maybe<float>.wrap(5.0)          // The same Maybe on a different type
    .then(x => Maybe<float>.wrap(null))
    .then(x => Maybe<float>.wrap(x * 2))  // chain the calls; safely handle null
Re:Monads are too powerful: The Expressiveness Spectrum by 1718627440 on Wednesday October 15, 2025 @07:54PM (#45599844)
Why does it sound so complicated when it is just a wrapper type that conforms to an interface?
Re:Monads are too powerful: The Expressiveness Spectrum by ww520 on Wednesday October 15, 2025 @10:50PM (#45600938)
It is what you described at high level. The devils are in the detail. People keep using words to describe the detail when code shows everything.
Re:Monads are too powerful: The Expressiveness Spectrum by yobbo on Thursday October 16, 2025 @12:04AM (#45601343)
It's a generalised typeclass for wrappers. It's not called "then" but "bind" and spelled (>>=), which doesn't exactly evoke useful associations for newcomers.
Re:Monads are too powerful: The Expressiveness Spectrum by immibis on Thursday October 16, 2025 @09:15AM (#45604948)
Because the interface has a few complicated rules associated with it. If you break them, the compiler may accept your code but it won't work with a lot of libraries that are supposed to work with any monad.
Re:Monads are too powerful: The Expressiveness Spectrum by oncallthrow on Wednesday October 15, 2025 @06:36PM (#45599156)
A monad is just a monoid in the category of endofunctors
Re:Monads are too powerful: The Expressiveness Spectrum by kmstout on Wednesday October 15, 2025 @07:10PM (#45599439)
It's like an enchilada, right?
Re:Monads are too powerful: The Expressiveness Spectrum by astrange on Wednesday October 15, 2025 @06:52PM (#45599296)
It's an implementation of the typeclass Monad, which happens to come with a special "do" keyword.
Re:Monads are too powerful: The Expressiveness Spectrum by munk-a on Wednesday October 15, 2025 @06:46PM (#45599255)
Someone may correct me but - in three levels of conciseness...

A monad is a function that can be combined with other functions.

It's a closure (or functor to the cool kids) that can be bound and arranged into a more complex composite closure without a specification of any actual value to operate on.

It's a lazy operation declaration that can operate over a class of types rather than a specific type (though a type is a class of types with just a single type so this is more a note on potential rather than necessary utility) that can be composed and manipulated in languages like Haskell to easily create large declarative blocks of code that are very easy to understand and lend themselves easily to abstract proofs about execution.

You've probably used them or a pattern like them in your code without realizing it.

Re:Monads are too powerful: The Expressiveness Spectrum by 1718627440 on Wednesday October 15, 2025 @07:15PM (#45599492)
So it's a function pointer, right? /s
Re:Monads are too powerful: The Expressiveness Spectrum by the__alchemist on Wednesday October 15, 2025 @06:56PM (#45599329)
Nan-in received a university professor who came to inquire about Monads

Nan-in served tea. He poured his visitor’s cup full, and then kept on pouring.

The professor watched the overflow until he no longer could restrain himself. “It is overfull. No more will go in!”

“Like this cup,” Nan-in said, “you are full of your own opinions and speculations. How can I show you a Monad unless you first empty your cup?”

Re:Monads are too powerful: The Expressiveness Spectrum by tasuki on Wednesday October 15, 2025 @07:15PM (#45599484)
This is as good an explanation of monads as any. Which is to say, bad.
Re:Monads are too powerful: The Expressiveness Spectrum by kelipso on Thursday October 16, 2025 @08:33AM (#45604567)
So many people just turn their brain off when they read the GP post. Which I guess it’s fine, there are plenty of actual explanations, but it’s so widespread in the Haskell adjacent communities and annoying when programming is made into something mysterious like this.
Re:Monads are too powerful: The Expressiveness Spectrum by valiant55 on Wednesday October 15, 2025 @06:38PM (#45599175)
Forget all the academic definitions, at it's core a monad is a container or wrapper that adds additional functionality to a type.
Re:Monads are too powerful: The Expressiveness Spectrum by 1718627440 on Wednesday October 15, 2025 @07:17PM (#45599509)
Yes, this is the only definition I get, but then I don't get all the rage about monads, because containers and standardized interfaces are nothing new, so surely that definition must be wrong?
Re:Monads are too powerful: The Expressiveness Spectrum by tickettotranai on Wednesday October 15, 2025 @07:33PM (#45599639)
Like many things in life it is far easier to give examples than it is to describe the thing.

Examples of monads are Promises and Elvis operators (for values that can be nullptrs). In a sense exceptions as well. Having heard this I think if you do a second pass at the type definitions, I think you may be able to parse them out

It really is just "a wrapper for values that sticks around when you do something to the values".

Think of it as a coding pattern, and it's much easier to grok

It's handy for IO because, well, did you see the examples I gave? A monad lets you basically ignore the failure mode/weirdness (the async stuff in the context of promises, null type in the case of Elvis) and worry about the computation you actually want to be doing.

Other places you might apply these would be fileio (file not found? cool, don't care, deal with it later) or networking (as long as the connection's good, do this.)

Re:Monads are too powerful: The Expressiveness Spectrum by 1718627440 on Wednesday October 15, 2025 @07:47PM (#45599783)
Sorry I never understood the functional approach outside of LISP being cool, because code is data.

Promises are wrappers, I see that. How are exceptions wrappers? They stop the code at the point the exception occurs and unwind the stack. They don't allow you to continue doing stuff and deal with it later.

> A monad lets you basically ignore the failure mode/weirdness

I just don't see how this works out in practice?

Ok, I defer dealing with file not found. Does that mean I know perform heavy computation and parsing on something that does not even exist. Wouldn't it be way easier to just do an early return and encode that the file exists in the type? And how does it play out to let the user wait for you doing something and you at the end coming around, well actually the input file was already missing?

And then you have some intermediate layer that needs to store all the computation you are doing until you now whether something succeeded or not. All this to save a single return statement.

Re:Monads are too powerful: The Expressiveness Spectrum by tickettotranai on Wednesday October 15, 2025 @08:04PM (#45599924)
(rewrote this to be less insufferable)

It's not about saving a single return statement, even in the elvis case. How many times have you written code along the lines of "if this isn't null do this, otherwise return. If the result of that isn't null, do this, otherwise return" etc etc.

Elvis ops are a small QoL change, Promises are essential to async Exceptions (much of the time) are kind of a "catch it pass it on" logic for me, and man do I wish I didn't need to write it every time.

With networking this really shines, or really just anything async etc

Re:Monads are too powerful: The Expressiveness Spectrum by 1718627440 on Wednesday October 15, 2025 @08:19PM (#45600058)
> How many times have you written code along the lines of "if this isn't null do this, otherwise return. If the result of that isn't null, do this, otherwise return" etc etc.

Yeah that sucks, but why would you write it that way. I thought it is common to write "if this is null return, anyways: do this, do that."

> Promises are essential to async Exceptions

I don't see that either. If errors are specific to functions then there is only one case where I handle them, so it doesn't save something to put these checks elsewhere. If they can be accumulated over many calls, then they should be just part of the object state (like feof), so I can query them in the end.

Re:Monads are too powerful: The Expressiveness Spectrum by tasuki on Wednesday October 15, 2025 @07:21PM (#45599533)
It is!
Re:Monads are too powerful: The Expressiveness Spectrum by binary132 on Thursday October 16, 2025 @10:22AM (#45605710)
People have a perverse incentive to make it seem fancier and more esoteric than it really is
Re:Monads are too powerful: The Expressiveness Spectrum by hinkley on Wednesday October 15, 2025 @06:28PM (#45599079)
Unfortunately no one can tell you what a monad is. You have to experience it for yourself. - Haskell Morpheus
Re:Monads are too powerful: The Expressiveness Spectrum by binary132 on Thursday October 16, 2025 @10:21AM (#45605706)
I’m convinced that this kind of talk is cope dreamed up by people who don’t understand monads but are expected to in their professional or student setting.
Re:Monads are too powerful: The Expressiveness Spectrum by bananaflag on Wednesday October 15, 2025 @06:31PM (#45599113)
You should first understand what a typeclass and a Functor is.
Re:Monads are too powerful: The Expressiveness Spectrum by tickettotranai on Wednesday October 15, 2025 @07:38PM (#45599688)
no, you do not.
Re:Monads are too powerful: The Expressiveness Spectrum by gowld on Wednesday October 15, 2025 @06:27PM (#45599064)
The important thing to know first is that a monad is not a single thing like "Optional". "monad" is a pattern or "interface" (called a "typeclass" in Haskell), that has many implementations, (Optional, Either, List, State Transormer, IO (Input/Output), Logger, Continuation, etc). Sort of how "Visitor" pattern in C++/Java is not a single thing.

https://hackage.haskell.org/package/base-4.21.0.0/docs/Contr...

https://book.realworldhaskell.org/read/monads.html

A common metaphor for monad is "executable semicolons". They are effectively a way to add (structured) hook computations (that always returns a specific type of value) to run every time a "main" computation (akin to a "statement" in other languages) occurs "in" the monad.

It's sort of like a decorator in Python, but more structured. It lets you write a series of simple computational steps (transforming values), and then "dress them up" / "clean them up" by adding a specific computation to run after each step.

Re:Monads are too powerful: The Expressiveness Spectrum by tickettotranai on Wednesday October 15, 2025 @07:42PM (#45599733)
Somehow I hear this all the time, but the haskell people have to realize that code patterns are absolutely a thing in all languages, ever? A lack of syntactic sugar doesn't mean monads don't exist in other languages.

Typeclasses are a distraction, the point is computation ignoring annoying contexty stuff (file not found errors, null on failure, etc) and there's dozens of examples in literally every language ever.

Not all problems are solved with a technical definition.

Re:Monads are too powerful: The Expressiveness Spectrum by tome on Thursday October 16, 2025 @02:52AM (#45602181)
> the haskell people have to realize that code patterns are absolutely a thing in all languages, ever? A lack of syntactic sugar doesn't mean monads don't exist in other languages.

Where did you get the impression that Haskell people don't realize that code patterns are a thing in other languages, or that monads don't exist in other languages?

Besides the syntactic sugar of "do notation", what Haskell has that most other languages don't have is the ability to abstract over monads, since it has higher kinded types. That is, you can write a generic operation like

    mapM :: (Traversable t, Monad m) => (a -> m b) -> t a -> m (t b)
that works for all monads. Most other type languages force you to write mapM separately for each monad you want it to work with.
Re:Monads are too powerful: The Expressiveness Spectrum by Ryder123 on Wednesday October 15, 2025 @06:31PM (#45599111)
This makes SchemaLoad's comment perfectly clear.

(but do I appreciate the effort you put into your reply - reading that monad's are more like interfaces is new information to me, and might help down the road)

Re:Monads are too powerful: The Expressiveness Spectrum by bitwize on Wednesday October 15, 2025 @06:43PM (#45599219)
Just think of it as a design pattern, but a bit more strict than the Gang of Four patterns. Fundamentally it's a relationship between types and other types such that certain operations make sense and follow well-understood rules (the monadic laws). Study the monadic laws, and try playing with the State, IO, and List monads to get a better sense of what those operations are and why they're useful for sequencing in a pure-functional context.
Re:Monads are too powerful: The Expressiveness Spectrum by b0sk on Wednesday October 15, 2025 @06:36PM (#45599149)
Re:Monads are too powerful: The Expressiveness Spectrum by runeblaze on Thursday October 16, 2025 @04:01AM (#45602662)
beats me. I spent so much time learning what a fundamental group is and I still cannot tell ppl what a fundamental group is convincingly.

I can’t even make stuff with fundamental groups.

Re:Monads are too powerful: The Expressiveness Spectrum by jghn on Thursday October 16, 2025 @09:00AM (#45604795)
The largest problem I found when I was going through the same thing was that every explanation that's trying to provide a non-abstract answer will always suffer the flaw of not being universally true. Because they're an abstract concept.