Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Haskell is a pure language. Purity is a concept that is absolutely bizarre to the real world, where adding two numbers together results in tons of side effects (load into registers, oops, have to load cache lines, alter memory, raise the ambient temperature, etc. etc.). However, the idea of pure functions is useful. So we make our basic program blocks from pure functions that don't "do" stuff, but just transform values.

However, we must chain these into useful programs somehow. Monad is the type name chosen in Haskell for the construct that does this. It's kind of simple if you work it backwards from the syntax. You want to be able to say

    do
      a <- readInt
      b <- readInt
      add a b
      print
The first two can fail, rely on side effects and the last one is purely a side effect. The only pure function is add, which can't work if a or b aren't there. Monads serve as a way to represent the real-world-ness without it seeping into the add function. You can think of each line as a closure getting the next value from the previous line. So readInt returns a Maybe Int. If it returns a Nothing, the next closure is simply skipped. You can insert a check after the add, if you want to, to see if you got Nothing and alert the user, etc. However, the basic idea is that the program does not crash with a NullPointerException. We know what to do if we get Nothing. The add function doesn't need to concern itself with that.

Hence, the Monad. It wraps a real world concern around a type (it has a type constructor). You must be able to make one from a concrete value that is unburdened with exceptional state (it has the unit function). You must be able to call pure functions on these monadic values without the side state seeping into the function (it has the bind function).

Edit: the reason you don't see Monads in other languages is because they're not essential to them. You can do stuff in C without Monads. To Haskell, Monads are like the Higgs boson. It's how you bind stuff together.




A few quibbles:

* Purity is not at all bizarre to the real world. If I have two apples in one pile and three in the other, then merely regarding them as the same pile is (2 + 3) very, very purely. Computers are the bizarre ones!

* "The first two can fail, rely on side effects and the last one is purely a side effect." It'd be much nicer to say that the first two are "side effecting computations with interesting return values" and the third one it the same... except we are not interested in the return.

* "The only pure function is add". I highly doubt that `add` is pure in your example! (1) this wouldn't typecheck in Haskell now if it were and (2) it'd imply that we are just throwing away the result of the addition.

* "the reason you don't see Monads in other languages is because they're not essential to them" I would challenge you to turn this exactly on it's head. The reason you don't see monads in other languages it that they are so essential to them that you cannot perceive parts without the monad.


"You must be able to call pure functions on these monadic values without the side state seeping into the function (it has the bind function)."

That sounds more like fmap.


First three lines could just be written using applicatives only:

(+) <$> readLn <> readLn

The monadic part only comes into play in the last line:

(+) <$> readLn <> readLn >>= print

It's part of what makes it monadic that the action takes an argument.


It's really the add function, strangely, which is monadic here.

Or the whole thing is an applicative if you take at face value his claim that add is pure.


Your explanation makes sense, but I don't see how are Monads different from Rust's Option Type (or Java's Optional Type?), or any other nullable type?


Option and Optional are indeed monads, and Java's Optional.flatMap() function is the monadic /bind/ function. But not all monads are Optional -- List is also a monad, and they go on to get a lot more complex than that.

I found that reading about Haskell really helpful for my Java development, and that looking at really simple monads like Optional, and using them in my code, was really helpful for understanding how more complicated monads work. Jumping straight into Haskell's IO monad is really unhelpful.


The maybe monad is just being used as an example here, but Haskell allows you to implement the same interface for any applicable type. for example; IO, mutable state, parsers, etc.


"Monad" is more like an adjective. "Option" is a monad, but, interestingly, the union type (A | null) is not.


As I understand it, this is because nullability (typically?) doesn't nest and so can't be a functor (with the whole of the types of the language as domain). If you can't wind up with m (m a), then there is no place for join.


Yeah, exactly. The other way to see it is to note that `Nothing(null)` is a perfectly reasonable Javascript expression which ought to mean something different from `null` alone. If that cannot be true then you don't actually have parametricity.




Consider applying for YC's Fall 2025 batch! Applications are open till Aug 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: