7 ms·
The Lazy Monad
- xupybd 4y agoWhy is it that as an abstract concept a monad is so hard to explain in simple English. I didn't understand it for years then realized I had seen it all over the place. Now that I think I know what it is I can explain to someone that doesn't already know what it is.
- tiddles 4y agoIt is, after all, just a monoid in the category of endofunctors.
- Arrrlex 4y agoI think this is the mistake a lot of people make: they form an intuition of monads after seeing lots of examples of them, and then they try to communicate that intuition without just saying "here are lots of examples of monads".
- xupybd 4y agoThat could be it. Perhaps my lack of understanding of category theory means I've only developed the pattern recognition for monads but not a deep understanding. So I can only explain it as the abstract thing all of these things have.
- schwurb 4y agoI am gonna be heavily opinionated, take my words with a bit of salt ;) Here it goes: 1. One understood monads when one is able to write a monadic interface that behaves like any intermediate haskell would expect it to behave. This is not a hard task. 2. Screw the abstract stuff. While fascinating, really few people understand concepts going from abstract to concrete rather than the other way around. And don't get me wrong, I don't think these kind of people are better theorists or problem solvers, they just have to seem a special relationship with symbols. If you are one of those people, you would likely know - in any case, I would encourage to write 3-5 examples of monads in Haskell or Java or JavaScript or whatever language suits you and go from there.
- strictfp 4y agoI think it's because it's a concept that constrains how multiple instances of a type interact, and we're used to thinking of types as putting restrictions on single instances.
- karmakurtisaani 4y agoI think one problem is that there is the mathematical concept of monad and the programming pattern monad. On abstract level they are the same, but in practice and for illustrative purposes they are not.
- krembanan 4y agoCould you explain it to me?
- xupybd 4y agoNot really. Here is one of the articles that helped me click. https://swlaschin.gitbooks.io/fsharpforfunandprofit/content/posts/elevated-world-7.html https://swlaschin.gitbooks.io/fsharpforfunandprofit/content/... After trying to understand it at a more fundamental level I have a suspicion that that piggy wiggies are involved.https://www.google.com/amp/s/bartoszmilewski.com/2014/10/28/category-theory-for-programmers-the-preface/amp/ https://www.google.com/amp/s/bartoszmilewski.com/2014/10/28/...
- schwurb 4y agoI offer a simple explanation elsewhere in this thread: https://news.ycombinator.com/item?id=31652379 https://news.ycombinator.com/item?id=31652379
- schwartzworld 4y agoThere's a great FP podcast, the lambdacast. They aren't making new episodes, but if you listen in order, by the time you get to the monad episode it all makes sense n
- luftibus 4y agoI recently wrote an explanation aimed at Scala developers, so if the syntax is not an obstacle this may help: https://upsolver.engineering/posts/monads-are-not-that-complicated/ https://upsolver.engineering/posts/monads-are-not-that-compl... In short: Functors (a tightly related concept) are about types that have ‘.map()’, and Monads are Functors that in addition have ‘.flatMap()’.
- chombier 4y agoA monad is for composing effectful computations. Effects are encoded using a polymorphic type with a `map` operation (called a functor), and effectful computations are functions `a -> E b` for some types `a, b` and effect `E`. A monad is exactly the plumbing you need for composing effectful computations: it turns a computation `b -> E c` into a `E b -> E c` so that you can compose `a -> E b` with `E b -> E c` to get a composed computation `a -> E c`. It does so in a way that makes effectful composition associative (i.e. the way you'd expect)
- larschdk 4y agoTo me, it is because the term 'a monad' refers to a thing that doesn't even exist as its own thing in programming. Of course your can realize a monad, but the monad is not the type, nor the function, but the abstract, mathematical "thing" that defines a type and the two operations (value wrapping, and the compose function). Programmers without a mathematical background will naturally struggle with such concepts. You can't point to where in the the code "the monad" is, as it's just the pattern, or the abstract mathematical combination of the type and the operations. Sure you could pack them into a class or a module, but it's still hard to point to where "the monad" is. When we describe other patterns, like a Singleton, Factory, an Adapter, etc., it's is much more clear what and where the thing is. It's just a word to describe a function, a class, or a module. Perhaps 'function composition with metainformation' would be a better title for the pattern. You take composable functions that act on certain types, and extend them to support metainformation attached to the values, while defining how the metainformation combines.
- IshKebab 4y agoYeah, I haven't done any Haskell but from what I understand "a monad" is just a type that lets you call `.map()` on it and do the normal thing that `map()` does. Would it be wrong to call it `mappable`? That would be a much clearer name.
- tel 4y agoIt's not that. The thing you're describing is often called a "functor". It could be called a "mappable" but generally once you've heard a functor is a thing that has a .map() function that works the way you expect it to then you don't really need to call it a mappable anymore. So the name sticks. Even to just be able to rapidly identify why having a thing that .map()s is a meaningful object represents the sort of experience with and abstraction of these concepts that'll put you ahead of the game for understanding monads.
- IshKebab 4y agoOh yeah I mixed them up. I still think `Mappable` is a much better name than `Functor`, and names matter. Especially for difficult to understand concepts. Functor isn't really even the right type of word. It should be Functable or something. Monad should be `FlatMappable`. I found this great article where they use exactly these terms to explain it: https://dev.to/joelnet/functional-javascript---functors-monads-and-promises-1pol https://dev.to/joelnet/functional-javascript---functors-mona... If people are using different terms to explain your confusing terminology then... maybe the confusing terminology is not very good.
- BerislavLopac 4y agoA monad is just an object.
- tedeh 4y agoI'm pretty sure a monad is just an endoid in the category of monofunctors?
- deleted 4y ago[deleted]
- kqr 4y agoWhy is it that I can't play musical instruments after someone has explained to me in simple English what musical instruments are? https://two-wrongs.com/the-what-are-monads-fallacy https://two-wrongs.com/the-what-are-monads-fallacy
- goto11 4y agoImagine if functions were explained the same way: A function is just a mapping from a domain to a codomain. This would also be pretty useless and confusing for someone trying to lean how to write print("hello world")
- schwurb 4y agoFor 99% of people, monads are best understood by a) using and writing many monadic interfaces and b) forgetting about the whole mathematical background. What a monad offers is: "1: Do A. After A is done, you can inspect the result of A and do either B or C. 2: You can chain monads of the same type together.". Sounds easy? It is because it is! The big fuzz about Monads is mainly because prior to monads, doing IO was akward in Haskell. Monads offered a convenient way to do IO (and other interactions with the outside worlds, such as databases, networking, ...) and turn up basically everywhere. There is nothing stopping one from introducing a monadic interface in OO-World, and it is partly done (i.e. "orElse" or "then") in some domains. However, bigger gain is to be expected in Haskell, since the type checking system forces the developer to deal with monads in a disciplined way. ----- I admit being guilty of having only the title prior to writing the comment. But even with only having read just the word 'monad' in the title together with 'lazy', I knew the author would describe 1) some way of lazily evaluating one thing after another and 2) some way of combining multiple lazily evaluated things with each other. After skimming, this is what the article is about. As always, the interesting stuff is not about the concept of a monad (which is pretty easy), but about how to model/code 1) and 2) in a specific context (in this instance, being lazy evaluation).
- omginternets 4y agohttps://www.youtube.com/watch?v=ZhuHCtR3xq8 https://www.youtube.com/watch?v=ZhuHCtR3xq8 I found Brian Beckman's video Don't Fear the Monad was extremely helpful for understanding monads as a practical user. I now use them everywhere. I don't know the first thing about category theory.
- WJW 4y agoMonads in OO-world often fall flat because monads usually add something to a computation (ability to store state, ability to throw exceptions, ability to do I/O, ability to return `null`, etc) and in Haskell the basic building block is the pure function which can do none of those things. But in (say) Ruby, every method I write has already been given rights to return nil, write to the logging system, delete the database or launch the missiles no matter from where it is called in the program. The ErrorT monad transformer is much less useful when exceptions are a key part of the language and intended to be used everywhere.
- mdm12 4y agoAs I like to say, design patterns for strongly-typed functional programming languages is essentially category theory. What matters, from a practical point of view, is that you know how to effectively use such patterns when decomposing systems to smaller parts (aka, functions) and composing them (monads et. al.).
- substation13 4y agoMonads as a concept in category theory are hard to understand without a bit of background. However, monads as a design pattern are not much more difficult than singletons, strategy pattern, visitors etc. I think the reason many monad tutorials fail is that the authors have an interest in category theory, so they find it hard to target the level of their audience. Here's my attempt for Java programmers. Suppose that: - Values (like `String` and `int`) can be put into "boxes" (like `Async<String>`) - We can call the box a "monad" when we have a few static methods for operating on the boxes that are well behaved: 1. A method for constructing a box from a value: Async<String> myAsync = Async.from("Hello, world. "); 2. A method for transforming a box into a new one with a possibly different value: Async<int> anotherAsync = Async.flatMap(myAsync, myString -> Async.from(myString.length())); The implementation of these two methods depends on the box we are talking about. You may see these under different names, which makes things extra confusing: 1. "just", "from", "pure", "return" 2. "flatMap", "bind" OK, but why would you want to do this? Well, if you are doing a complex procedure that manipulates these boxes, then having these methods allows us to build that complex procedure out of simpler parts. It's highly compositional. Additionally, the monad structure allows languages (not Java sadly) to give you really powerful syntactic sugar that avoids nesting. In Haskell this is called do-notation; F# has Computation Expressions. Many more traditional languages have a less general version in the form of async / await.
- chopin 4y agoWhere this can directly been seen in Java is the Optional class which has the methods you describe as instance methods. Though Java has no syntactic sugar for monads this allows chaining expressions (which I think in Haskell would be bind() chains). Java streams behave similarly (and form a kind of monad around Collections). Having monad (or functor) functions (flatMap, map,...) as static functions has the disadvantage that you can't chain them well.
- tremon 4y agoBut for such a monad to be valuable, wouldn't you also need 3a. A method for extracting the value from the box String myValue = Async.val(myAsync); Or, alternatively, to be able to re-use the entire standard library for your boxed values (which is not possible in Java, FAFAIK): 3b. Take a plain-valued function and lift it to accept boxed values: Func<Async<String>> asyncJoin = Func.lift<Async>(String.join);
- goto11 4y agoSince everyone is just writing their own explanation of monads, here is mine: Monads are a pattern for function chaining. It can be compared with fluent interfaces in OOP, which is also a pattern for chaining operations. A fluent interface does not imply any particular semantics - the semantics of a fluent chain will depend on the specific object it is used on. Same with monads, where each type which support the monad pattern provide its own unique semantic for how the operations are performed. The name "monad" is misleading since it is a noun. Perhaps "Chainable" would be a better name? The pattern can be used in any language which support higher-order functions, but without any syntax sugar support it tend to be rather verbose compared to say fluent interfaces. But with built-in syntax sugar support like in Haskell, monads becomes viable for many purposes. Since JavaScript is the lingua franca of today, here is an example of a method chain in JavaScript: [1,2,3].map(a => a + 1).filter(b => b != 3) The same result using the monad pattern: [1,2,3].flatMap(a => [a + 1]).flatMap(b => b != 3 ? [b] : []) The strength of the monad pattern is that it is more composable. For example the same result can be achieved by nesting rather then chaining: [1,2,3].flatMap(a => [a + 1].flatMap(b => b != 3 ? [b] : [])) Although in both cases it is clearly more verbose than the first non-monad method chain. But with some syntactic sugar with hide the repeated flatMap boilerplate, it can be made pretty concise.
- avgcorrection 4y ago> The name "monad" is misleading since it is a noun. Perhaps "Chainable" would be a better name? Other type classes can be chained. Like Applicative. Applicative is a chain where you cannot inspect the per-step state or whatever. But you can with Monad.