[HN Gopher] Monads are too powerful: The expressiveness spectrum
___________________________________________________________________
Monads are too powerful: The expressiveness spectrum
Author : hackandthink
Score : 39 points
Date : 2025-10-12 05:11 UTC (3 days ago)
(HTM) web link (chrispenner.ca)
(TXT) w3m dump (chrispenner.ca)
| PaulHoule wrote:
| I'd argue the exact opposite. Compared to what you can do if you
| can _write compilers_ anything that involves _composing
| functions_ is weak beer and most monad examples cover
| computational pipelines as opposed to computational graphs. It 's
| like that Graham book _On Lisp_ , it's a really fun book but then
| you realize that screwing around with functions and macros
| doesn't hold a candle to what you learn from the Dragon Book.
| taeric wrote:
| I maintain that the big advantage of the On Lisp approach is
| that all of that is available without having to write a new
| compiler.
|
| Granted, I also don't have as heavy an attachment to pure
| functional as most people seem to build. Don't get me wrong,
| wanton nonsense is nonsensical. But that is just as true in
| immutable contexts.
| PaulHoule wrote:
| What I found remarkable about that book is that 80% of what
| is in it can be done with functions and no macros, mostly you
| can rewrite the examples in Python except for the coroutines
| but Python already has coroutines. It also irks me that the I
| don't think the explanation of coroutines in Scheme is very
| clear but it's become the dominant one you find in the net
| and I can't find a better one.
|
| As for 'compiler' you also don't need to go all the way to
| bare metal, some runtime like WASM or the JVM which is more
| civilized is a good target these days.
| taeric wrote:
| Totally fair. I think a lot of the things we used to do in
| the name of efficiency has been completely lost in the
| progress of time. Largely from the emergence and refinement
| of JIT compilers, I think?
|
| That is, a lot of why you would go with macros in the past
| was to avoid the expense of function calls. Right? We have
| so far left the world of caring about function call
| overhead for most projects, that it is hard to really
| comprehend.
|
| Coroutines still strike me as a hard one to really grok. I
| remember reading them in Knuth's work and originally
| thinking it was a fancy way of saying what we came to call
| functions and methods. I think without defining threads
| first, defining a coroutine is really hard to nail down.
| And too many of us take understanding of threads as a
| given. Despite many of us (myself not immune) having a bad
| understanding of threads.
| bvrmn wrote:
| Coroutines as a technique to implement state machines is
| the first things which comes to my mind. It's a more
| abstract and requires a way less fundamentals to know
| comparing to concurrency.
| taeric wrote:
| But coroutines really only work any better than "objects"
| if you understand the implication to the stack pointer?
| Which requires understanding exactly what a thread is.
| Right?
|
| That is, a basic class that has defined state and methods
| to modify the state is already enough to explain a state
| machine. What makes coroutines better for it?
| andersmurphy wrote:
| Yeah, I've had fun using macros to create optimised
| functions at runtime (inline caching effectively) and/or
| generate code that is more friendly to the JVM JIT.
|
| Also, there's always plenty of use for doing work at
| compile time.
|
| In some sense they can also be seen as a better code
| generation.
| instig007 wrote:
| > if you can write compilers anything that involves composing
| functions is weak beer
|
| > screwing around with functions and macros doesn't hold a
| candle to what you learn from the Dragon Book.
|
| ---
|
| So, what is it that you learn from that book that's a
| revelation for you compared to the weak beer of composable
| effect systems?
| fn-mote wrote:
| > screwing around with functions and macros doesn't hold a
| candle to what you learn from the Dragon Book
|
| This depends a lot on what you mean. My first take is that the
| more you know about macros the more you realize what they can
| do.
|
| I don't know what your takeaway from the Dragon Book was, but
| writing DSLs using macros feels very usefully powerful to me.
|
| I think you are undervaluing modern macros.
| veqq wrote:
| But lisp programs are compilers. That's the whole point of lisp
| and macros. Your functions can happily emit assembly direction.
| whycombinetor wrote:
| Yes. For the same reason that the Yoneda lemma and the Cayley
| theorem are almost meaningless tautologies once you fully
| understand what they're saying. "Every small thing (of a certain
| type) is able to be expressed as a subcase of a bigger thing that
| contains every single possible subcase in existence." Well no
| shit.
| IshKebab wrote:
| Interesting, but it seems like he kind of proved himself wrong?
| Monads are the only option he presented that _are_ sufficiently
| powerful for normal programs.
| bokumo wrote:
| I don't think you're being fair to Chris Penner. He ends his
| blog post with: "It may take me another 5 years to finally
| finish it, but at some point we'll continue this journey and
| explore how we _can_ sequence effects using the hierarchy of
| Category classes instead. " Emphasis by me.
|
| So while it is true, that what he has described so far is not
| sufficiently powerful for normal programs, he has clearly
| stated that there are more abstractions between Applicative and
| Monad to explore than what he has presented so far.
| bionhoward wrote:
| And here I thought it was a pedantic word for "data box"
| jcmontx wrote:
| Haskell looks a heck lot like F#, even more than Ocaml if you ask
| me
| gowld wrote:
| Paging John Harrop...
|
| https://news.ycombinator.com/item?id=1396763
| SchemaLoad wrote:
| I tried learning Haskell for a decent chunk of time and could
| make some stuff, but despite trying to learn, I still could not
| tell you what a monad actually is. All the explanations for it
| seemed to make no sense.
| gowld wrote:
| The important thing to know first is that a monad is not a
| single thing like "Optional". "monad" is a pattern or
| "interface" (called a "typeclass" in Haskell), that has many
| implementations, (Optional, Either, List, State Transormer, IO
| (Input/Output), Logger, Continuation, etc). Sort of how
| "Visitor" pattern in C++/Java is not a single thing.
|
| https://hackage.haskell.org/package/base-4.21.0.0/docs/Contr...
|
| https://book.realworldhaskell.org/read/monads.html
|
| A common metaphor for monad is "executable semicolons". They
| are effectively a way to add (structured) hook computations
| (that always returns a specific type of value) to run every
| time a "main" computation (akin to a "statement" in other
| languages) occurs "in" the monad.
|
| It's sort of like a decorator in Python, but more structured.
| It lets you write a series of simple computational steps
| (transforming values), and then "dress them up" / "clean them
| up" by adding a specific computation to run after each step.
| Ryder123 wrote:
| This makes SchemaLoad's comment perfectly clear.
|
| (but do I appreciate the effort you put into your reply -
| reading that monad's are more like interfaces is new
| information to me, and might help down the road)
| hinkley wrote:
| Unfortunately no one can tell you what a monad is. You have to
| experience it for yourself. - Haskell Morpheus
| bananaflag wrote:
| You should first understand what a typeclass and a Functor is.
| b0sk wrote:
| This is great imo --
| https://www.adit.io/posts/2013-04-17-functors,_applicatives,...
| oncallthrow wrote:
| A monad is just a monoid in the category of endofunctors
| valiant55 wrote:
| Forget all the academic definitions, at it's core a monad is a
| container or wrapper that adds additional functionality to a
| type.
| bitwize wrote:
| Just think of it as a design pattern, but a bit more strict
| than the Gang of Four patterns. Fundamentally it's a
| relationship between types and other types such that certain
| operations make sense and follow well-understood rules (the
| monadic laws). Study the monadic laws, and try playing with the
| State, IO, and List monads to get a better sense of what those
| operations are and why they're useful for sequencing in a pure-
| functional context.
| munk-a wrote:
| Someone may correct me but - in three levels of conciseness...
|
| A monad is a function that can be combined with other
| functions.
|
| It's a closure (or functor to the cool kids) that can be bound
| and arranged into a more complex composite closure without a
| specification of any actual value to operate on.
|
| It's a lazy operation declaration that can operate over a class
| of types rather than a specific type (though a type is a class
| of types with just a single type so this is more a note on
| potential rather than necessary utility) that can be composed
| and manipulated in languages like Haskell to easily create
| large declarative blocks of code that are very easy to
| understand and lend themselves easily to abstract proofs about
| execution.
|
| You've probably used them or a pattern like them in your code
| without realizing it.
| ilikebits wrote:
| Monads are a generalization of Promises. Each type in Monad
| defines their own `.then` in a different way. For promises,
| `.then` is defined as "run this function once you have this
| deferred value from the last promise". For optionals (`Maybe`),
| `.then` is defined as "run this function if the last optional
| had an actual value". For Either, `.then` is defined as "run
| this function if the last Either returned Right, otherwise
| early-return with the value from Left" (this is functional
| early-return, basically).
| astrange wrote:
| It's an implementation of the typeclass Monad, which happens to
| come with a special "do" keyword.
| the__alchemist wrote:
| Nan-in received a university professor who came to inquire
| about Monads
|
| Nan-in served tea. He poured his visitor's cup full, and then
| kept on pouring.
|
| The professor watched the overflow until he no longer could
| restrain himself. "It is overfull. No more will go in!"
|
| "Like this cup," Nan-in said, "you are full of your own
| opinions and speculations. How can I show you a Monad unless
| you first empty your cup?"
| jancsika wrote:
| It'd be nice to have a process like the following:
|
| 1. I free solo a bunch of junk in vanilla javascript with state
| flowing hither and thither until I'm out of coffee
|
| 2. I test the _exact_ behaviors(s) I wanted to make possible in
| the GUI I just wrote.
|
| 3. The framework whitelists only the event chains from my test.
|
| 4. For any blacklisted event chains, the user gets a Youtube
| video screencast of the whitelisted test so they can learn the
| correct usage of my GUI.
| spewffs wrote:
| Yes monads in general are too expressive but the answer isn't to
| limit the typeclass to something between applicative and monad
| but rather to limit what monads are allowed. The problem is that
| there should only be one monad: an effect monad loaded with
| various effects depending on the side effect needed. Instead of
| defining this or that monad, there should only be the capability
| to define the effect you need.
|
| In that case, everything runs within the effect monad and then no
| one would ever really need to learn what a monad is, just that
| some calls are effectful (like reading a file or throwing an
| exception).
___________________________________________________________________
(page generated 2025-10-15 23:00 UTC)