←back to thread

A list is a monad

(alexyorke.github.io)
153 points polygot | 1 comments | | HN request time: 0.266s | source
Show context
kerblang ◴[] No.44447914[source]
The way I think of it, monads are a solution to Callback Hell, where you've fallen in love with lambdas, but now you have a nightmarish mess of lambdas in lambdas and lambdas calling lambdas. The monadic functions allow you to create "for comprehensions" aka "do comprehensions" but really, they look like a classic for-each loop. They secretly call the monadic map/flatMap/filter functions.

    for x in list
        doThings(x)
These comprehensions have a strange bonus feature, that you can do nested "loops" all at once, and even add "guards" (little if statements)

    newlist=
        for x in list1
            y in list2 if y > 3
            z in list3
            doThings(x, y, z)
But again, the comprehension, when "de-sugared", is secretly calling the map/flatMap/filter functions of list1, list2, list3 to get our result. You as the author of a given monad can implement those functions however you want, and they're all 3 lambda based. But notice how the comprehension is flattening those lambdas out! Our callbacks in callbacks are much more readable like this.

Without comprehensions, you can still implement monadic functions in any old language (probably in C...?), and they're handy in their own right, but you don't get the flattening-of-callback-hell magic.

replies(1): >>44447956 #
stronglikedan ◴[] No.44447956[source]
After reading your comment, I've made it my mission to understand it. Although I have no idea what you're talking about, you make it sound intriguing.
replies(6): >>44448147 #>>44448192 #>>44448734 #>>44449291 #>>44450891 #>>44452126 #
1. still_grokking ◴[] No.44452126[source]
What parent describes is pretty simple: That's just how the compiler transforms some code.

Do-notation in Haskell, or for-comprehensions in Scala are just syntax sugar for nested calls to `flatMap`, `filter`, and `map`.

I think this here shows it nicely:

https://www.baeldung.com/scala/for-comprehension#for-compreh...

In Scala you can add the needed methods to any type and than they will "magically" work in for-comprehensions. In Haskell you need to implement a Monad instance which than does the same trick.

The concrete implementations of these methods need to obey to some algebraic laws for the data structure which defines them to be called a monad. But that's pretty much it.

In my opinion all that Haskell in most "monad tutorials" just blurs an in principle very simple concept.

The in practice relevant part is that a monad can be seen as an interface for a wrapper type with a constructor that wraps some value (whether a flat value, some collection, or even functions, makes no difference), does not expose an accessor to this wrapped value, and has a `flatMap` method defined. It also inherits a `map` method, coming from an interface called "Functor". The thing is also an instance of an "Applicative", which is an interface coming with a `combine` method which takes another object of the same type as itself and returns a combination of again the same type (classical example: string concatenation can be a `combine` implementation if we'd say that `String` implements the `Applicative` interface).