5 ms·
Monads are too powerful: The expressiveness spectrum
- z3ratul163071 1y ago[flagged]
- dang 1y agoPlease don't do this here.
- PaulHoule 1y agoI'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 1y agoI 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 1y agoWhat 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 1y agoTotally 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 1y agoCoroutines 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 1y agoBut 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?
- bvrmn 1y agoThe issue with state you should handle it. Compare for example some iterator implementation in Java and Python. Latter needs only one method with coroutine and no state to store on object level. > the state is already enough to explain a state machine. I did not talk about explaining state machines but implementing state machines as coroutines. Progression: give an idea of state machines, show how hard is to handle state, present coroutines as way to handle states.
- instig007 1y ago> 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 1y ago> 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 1y agoBut lisp programs are compilers. That's the whole point of lisp and macros. Your functions can happily emit assembly direction.
- whycombinetor 1y agoYes. 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 1y agoInteresting, 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 1y agoI 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.
- deleted 1y ago[deleted]
- internet_points 1y agotook a bit less than five years :) https://chrispenner.ca/posts/arrow-effects https://chrispenner.ca/posts/arrow-effects
- bionhoward 1y agoAnd here I thought it was a pedantic word for “data box”
- jcmontx 1y agoHaskell looks a heck lot like F#, even more than Ocaml if you ask me
- gowld 1y agoPaging John Harrop... https://news.ycombinator.com/item?id=1396763 https://news.ycombinator.com/item?id=1396763
- retrac 1y agoI'd say the family resemblance is the other way around. F# was influenced by Haskell, both in syntax and semantics. Just as Haskell was influenced by early ML. Haskell and ML make up one of the major language families. They are more like each other than they are like other languages. Inspired by the lambda calculus. Strong static typing with type inference. A succinct math-like syntax that emphasizes pattern matching. Haskell goes further with syntactic sugar and tries to be almost equation-like: a = 5 f = \x -> x + 1 g x = x + 2 f $ g a SML: val a = 5 val f = fn x => x + 1 fun g x = x + 2 f (g a) But F# like Haskell makes no distinction between values and functions: let a = 5 let f = fun x -> x + 1 let g x = x + 2 f (g a) The use of indent-based blocks is another Haskell-ish influence on F#. But now we're awfully close to bikeshedding.
- SchemaLoad 1y agoI 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.
- deleted 1y ago[deleted]
- gowld 1y agoThe 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/Control-Monad-Instances.html https://hackage.haskell.org/package/base-4.21.0.0/docs/Contr... https://book.realworldhaskell.org/read/monads.html 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 1y agoThis 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)
- tickettotranai 1y agoSomehow I hear this all the time, but the haskell people have to realize that code patterns are absolutely a thing in all languages, ever? A lack of syntactic sugar doesn't mean monads don't exist in other languages. Typeclasses are a distraction, the point is computation ignoring annoying contexty stuff (file not found errors, null on failure, etc) and there's dozens of examples in literally every language ever. Not all problems are solved with a technical definition.
- jancsika 1y agoIt'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.
- tickettotranai 1y agoIf someone paired this with a code-lite GUI designer, the world would be a brighter place indeed
- spewffs 1y agoYes 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).