←back to thread

A list is a monad

(alexyorke.github.io)
153 points polygot | 3 comments | | HN request time: 0.009s | source
Show context
brooke2k ◴[] No.44445948[source]
As far as monad tutorials go, this one seems quite good. I like the categorization of monads between "containers" and "recipes".

However, I personally think that monad tutorials tend to give people the wrong impression and leave them more confused than they were before, because they focus on the wrong thing.

A monad is not a complex concept, at all. IMO a more useful way to present the topic would be with one separate lesson for every common monad instance. Start with Maybe, then IO, then maybe State and List, and so on... because ultimately, every instance of a Monad works very differently. That's why the pattern is so useful in the first place, because it applies to so many places. (Note: this is a criticism of monad tutorials in general, not this one in particular, which seems to do a decent job on this front).

In my experience, people new to Haskell focus way too much on getting the "a-ha" moment for monads in general, when really you want a bunch of separate "a-ha" moments as you realize how each instance of a monad takes advantage of the pattern differently.

I also tend to think that monads are best demonstrated in Haskell rather than in other languages, if only because the notation is so much less clunky. That may just be me though. (EDIT: well, also because almost no other languages have typeclasses, so you have to approximate it with interfaces/traits/etc)

Also FYI: in part 2, the code examples have extra newlines in between every line, which makes it hard to read (I'm on firefox, if that matters).

replies(15): >>44446327 #>>44446377 #>>44446564 #>>44446988 #>>44447713 #>>44448118 #>>44448413 #>>44449093 #>>44449627 #>>44449895 #>>44450873 #>>44450887 #>>44451012 #>>44451851 #>>44458827 #
pdhborges ◴[] No.44446327[source]
If all monad instances work differently what is the value of the Monad interface? What kind of usefull generic code can one write against the Monad interface.

Related: https://buttondown.com/j2kun/archive/weak-and-strong-algebra...

replies(11): >>44446453 #>>44446472 #>>44446556 #>>44446586 #>>44446781 #>>44446882 #>>44447360 #>>44448151 #>>44448170 #>>44450818 #>>44462125 #
tel ◴[] No.44447360[source]
The more constrained your theory is, the fewer models you have of it and also the more structure you can exploit.

Monads, I think, offer enough structure in that we can exploit things like monad composition (as fraught as it is), monadic do/for syntax, and abstracting out "traversals" (over data structures most concretely, but also other sorts of traversals) with monadic accumulators.

There's at least one other practical advantage as well, that of "chunking".

A chess master is more capable of quickly memorizing realistic board states than an amateur (and equally good at memorizing randomized board states). When we have a grasp of relevant, powerful structures underlying our world, we can "chunk" along them to reason more quickly. People familiar with monads often can hand-wave a set of unknowns in a problem by recognizing it to be a monad-shaped problem that can be independently solved later.

replies(1): >>44447577 #
ryandv ◴[] No.44447577[source]
> There's at least one other practical advantage as well, that of "chunking".

> When we have a grasp of relevant, powerful structures underlying our world, we can "chunk" along them to reason more quickly.

This is one thing I've observed about Haskell vs. other languages: it more readily gives names and abstractions to even the minutest and most trivial patterns in software, so that seemingly novel problems can be quickly pattern matched and catalogued against a structure that has almost certainly been seen before.

One example: I want to run two (monadic) computations, and then somehow combine together their results (with some binary operation). Such a trivial and fundamental mode of composition, that seems to lack a name in almost every other programming language. Haskell has a name for this mode of composition, and it's called liftM2.

Never again will you have to re-write this pattern for yourself, leaving yourself open to error, now that you have this new concept in your vocabulary. Other languages will happily let you reinvent the wheel for the umpteenth time, or invent idiosyncratic patterns and structures without realizing that they are just particular applications of an already well-studied and well-worn concept.

replies(1): >>44448925 #
maleldil ◴[] No.44448925[source]
Note that this is general enough that you don't need a Monad for this. Applicative is enough (liftA2).
replies(1): >>44449959 #
solomonb ◴[] No.44449959[source]
Not if you need to perform two /Monadic/ operations as the commenter stated explicitly.
replies(1): >>44450039 #
tel ◴[] No.44450039[source]
Every monad is also an applicative and liftA2 does/is the same thing as liftM2. The only reason they both exist was due to Monad being popularized in Haskell earlier than Applicative and thus not having it as a superclass until the Functor-Applicative-Monad Proposal in Haskell 2014. It was obviously correct, but a major breaking change that also got pork barreled a bit and so took a while to land.
replies(1): >>44450664 #
1. solomonb ◴[] No.44450664[source]
Yes you're absolutely right. I had a bit of a brain fart moment here. If they were Applicative operations then you would not be able to use `liftM2`, not the other way around.
replies(1): >>44452347 #
2. mnsc ◴[] No.44452347[source]
This is my fear when I think about doing actual in a team using a functional language. That there's an imbalance in understanding between participants in a team making all discussions about problem x into the pattern matchning problem y. Like "is this liftM2 or liftA2?"

I've only had a couple of months of experience working with scala before the team switched to Java. The reasons were many but one of them was that the external consultant that was most knowledgeable in "thinking with functions" was kind of a dick. Making onboarding into a horror show of "go look up yt video x before I can talk about this functionality" with a condescending tone. So within a month he was let go and then no one in the remaining team really had the courage to keep debe it further. Some thought that they maybe could maintain the current functionality but the solution was only like half complete. (in the consultant mind it was complete because it was so generic you only needed to add a couple of lines in the right place to implement each coming feature)

That said, I would love to work in a hardcore Haskell project with a real team, one with a couple of other "regular" coders that just help each other out when solving the actual problems at hand.

replies(1): >>44456654 #
3. solomonb ◴[] No.44456654[source]
Well, I can't speak to your experience but in the case of liftM2 vs liftA2 I have never even seen liftM2 get used. Its more of a historical oddity that it is available.