Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Functors, Applicatives, and Monads in Pictures (adit.io)
25 points by Leftium on Feb 6, 2023 | hide | past | favorite | 4 comments


"Value in a box" remains a misleading and unmotivating visualization/example of functors. The train visualization for lists is particularly egregious[1].

Parsers and delimited continuations[0] are monads, and there is manifestly no value there in some terms.

Monads allow us to reason about a computational environment "from the outside", as opposed to "from the inside"; functors and applicatives are restricted forms of the same thing. Functors allows us to reason about values in the computational environment. Pointed functors allow us to reason about pure values embedded in the computational environment, which we are going to demand remain unaffected by other operations. Applicatives allow us to reason about partially applied functions, or suspended computations (as opposed to mere values). Monads allow us to reason about nested computations (or sequenced, precisely in the sense that `a(b(c))` is both nested and sequenced).

My favorite monad: classical logic is just a monad in constructive/intuitionistic logic. That exemplifies the concept of computational environment, not burritos. It also shows that "there is no value in the box, only an opaque box and our imagination" can literally be the defining characteristic of a monad!

[0] For certain systems of continuation primitives.

[1] The "list monad" used in Haskell and elsewhere is actually the nondeterminism monad plus a bit of ordering on the side; the train visualization captures the less important of those two aspects. The nondeterminism monad can be extended to the discrete probability monad; that seems far more interesting.


Can you elaborate on what you mean when you say "allow us to reason about"?


It means I don't need to know what a monad does before I can begin to characterize what it means to, say, traverse a data structure with that monad. Then once I do know what a monad does, the problem of figuring out what it means to traverse a data structure - or do any other operation generic over monads - becomes compositional: the combined knowledge is not more than the sum of its parts.

For example, let's take the Maybe monad and tree traversals. (a) Tree traversals take monadic actions at each node of a tree, nest/sequence them in a certain way, and apply the monad's rules for how to flatten that nesting, with the output being the whole tree with the same structure. (b) The maybe monad is the environment where we can give up on a computation. Now what does it mean to do a tree traversal in the Maybe monad? I don't need to do any additional reasoning, I can simply merge the definitios: "(a) it does some computation at each node and produces a same-shaped tree, (b) unless some computation gives up then the whole thing gives up". There is no novel or sui generis interaction possible between (a) and (b). So reasoning about the program is easier.

Or, for Applicatives: what does it mean to apply a (Nondeterminism (A -> B)) to a (Nondeterminism A)? Well, I don't need to worry about "function in Nondeterminism monad" being some spooky new entity I need to learn or memorize: because I can reason generally about applicatives, I know that the exact same sequencing effect must be used as when I apply a 2-ary pure function to two effectful values. And I know what that is for Nondeterminism: do each possible thing in parallel.

I hope that makes sense, although I think only experience can truly motivate monads. It seems like a bunch of abstract woo because the whole point of monads is to become blasé about monads. When confronted with some bizarre monad, one can shrug and say, "Whatever, it's just a monad, nothing new to see here."


This can be a tricky subject to get right.

What I found useful for this aspect of functional programming was having to implement a new monad as the result of a real engineering exercise.

https://sambernheim.com/blog/building-a-monad

This goes through a real problem with various solutions that evolve to support additional requirements and results in the design of a new Monad




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

Search: