this post was submitted on 27 Mar 2025
452 points (94.8% liked)

Programmer Humor

22133 readers
1898 users here now

Welcome to Programmer Humor!

This is a place where you can post jokes, memes, humor, etc. related to programming!

For sharing awful code theres also Programming Horror.

Rules

founded 2 years ago
MODERATORS
 
you are viewing a single comment's thread
view the rest of the comments
[–] Kache@lemm.ee 3 points 3 days ago* (last edited 3 days ago)

It's a container with certain behaviors and guarantees making them easy and reliable to manipulate and compose. A practical example is a generic List, that behaves like:

  • List[1, 2, 3], i.e. ("new", "unit", "wrap") to create, containing obj(s)
  • map(func) to transform objs inside, List[A] -> List[B]
  • first(), i.e. ("unwrap", "value") to get back the obj
  • flat_map(func), i.e. ("bind") to un-nest one level when func(a) itself produces another List, e.g. [3, 4].flat_map(get_divisors) == flatten_once([[1, 3], [1, 2, 4]]) == [1, 3, 1, 2, 4]

Consider the code to do these things using for loops -- the "business logic" func() would be embedded and interlaced with flow control.

The same is true of Maybe, a monad to represent something or nothing, i.e. a "list" of at most one, i.e. a way to avoid "null".

Consider how quickly things get messy when there are multiple functions and multiple edge cases like empty lists or "null"s to deal with. In those cases, monads like List and Maybe really help clean things up.

IMO the composability really can't be understated. "Composing" ten for loops via interlacing and if checks and nesting sounds like a nightmare, whereas a few LazyList and Maybe monads will be much cleaner.

Also, the distinction monads make with what's "inside" and what's "outside" make it useful to represent and compartmentalize scope and lifetimes, which makes it useful for monads like IO and Async.