9 ms·
Monads explained by Eric Lippert
- ufo 14y agoNote that this is a series of posts. The first post that is being linked to doesn't have much IMO. http://ericlippert.com/2013/02/21/monads-part-one/ http://ericlippert.com/2013/02/21/monads-part-one/ http://ericlippert.com/2013/02/25/monads-part-two/ http://ericlippert.com/2013/02/25/monads-part-two/ http://ericlippert.com/2013/02/28/monads-part-three/ http://ericlippert.com/2013/02/28/monads-part-three/ I wasn't clear for me but in the last post he mentioned that there would be more posts to come.
- interconnector 14y agoThere's a part four as well: http://ericlippert.com/2013/03/04/monads-part-four/ http://ericlippert.com/2013/03/04/monads-part-four/
- dons 14y agoHe sure takes his time.. Episode 4: Conclusion: But we are so close! Next time on FAIC we'll make a small but vital modification to the signature pattern ApplyFunction to arrive at the actual second requirement of the monad pattern.
- Locke1689 14y agoEric is attempting to explain it to a wide class of C# developer -- most of whom are pretty unfamiliar with lambdas and higher-order functions, much less eclectic type polymorphism and computation.
- raverbashing 14y agoDo you know what I miss about these explanations? Technical people can't go straight to the point. They go around, around, around, going into corners, etc (not only on explanations, mind you) For example, math has some very high-level/generic explanations, and curiously, I find them more understandable. So, I've given up on understanding Monads (or at least Haskell ones), I'll probably understand them when I come up with a similar problem and think about how to solve them.
- gngeal 14y ago"For example, math has some very high-level/generic explanations, and curiously, I find them more understandable." That's because math always "goes straight to the point". There's nothing but the raw substance in it.
- kryptiskt 14y agoWhen I read math, I really like some motivating examples before digging into the definitions and theorems. For me, concrete examples makes it way easier to grasp abstract concepts.
- raverbashing 14y agoOh, I agree, sometimes it's too generic =) Especially if you don't know the names used in the description. The problem is that I can't stand explanations that would go like this if it was explaining Math: "So, we have a natural number, that is 2, 7, or 34232345 and by the way they're all integer numbers as well, also they are rational numbers as well, oh and there's equation you can do with them, but ok, so you can sum those numbers, etc" I'd rather go with "This turns the natural numbers (N, +) into a commutative monoid with identity element 0,"
- unconed 14y agoI find the best analogy is with optimized code. It's not like you're deliberately obfuscating it, but still, in trying to write it as succinctly as possible, some of the information has gotten lost.
- marco-fiset 14y agoIn this case, going around and around really helped me grasp the concept. Every other monad tutorial out there always go straight to the point and that is what made it difficult for me to understand them. I really like this series so far and I think this is the perfect way to explain something that complex. "You need to know where you came from to understand where you're going".
- 14y ago
- serpi 14y agoThe monad is the clitoris of programming.
- marco-fiset 14y agoWhat is that supposed to mean ?
- friendly_chap 14y agoI think he is high, all those recent drug related posts ya know...
- treerex 14y agoI took it as a reference to the clitoris being "Nature's Rubik's Cube" --- the most difficult puzzle in the world. Pretty funny, actually.
- charlieflowers 14y agoI need On-Star ...
- pekk 14y agoOne of these things is routinely found by most humans, and the finding can be taught to an idiot in one or two sentences. If you are going to make an improper analogy for monads, it should probably be the prostate or the g-spot.
- DannoHung 14y agoMonads are complicated because the word "monad" bears too much weight in any discussion about them. 1) There is a category theoretical concept of a monad. This is largely irrelevant in a practical explanation of monads since Monads are usually talked about in terms of another category theoretical concept called the Kleisli Category or Kleisli Triple. However, if someone starts talking about "monad laws", they're probably referring to the theoretical sense of this. 2) There is, in Haskell at any rate, a typeclass called the Monad (note the capital "M"). This is mostly important because when a type is an instance of this category, the Haskell do-notation is useful. Aside from that, you can only use the handful of operations that the Monad typeclass implements that you don't have to implement yourself for it to be an instance of Monad. 3) There are Monad type constructors, such as Maybe, IO, and State. This is where things actually start getting interesting for the practitioner, because each provides a specific abstraction of a concept, such as input/output or partial functions (IO and Maybe, respectively). 4) There are Monad types, both abstract and concrete, like Maybe a, IO a, Maybe Int, State MyType and so on. These are the types you actually will program with. 5) There are Monad values, which are instances of the Monad types, which are, themselves, instances of the Monad type constructors, which are instances of the Monad typeclass. 6) Then just to add a slightly extra confusing layer on top of it all, you have the values inside the Monad you'll actually be doing computations with. 7) And finally, it doesn't help when in code examples, type variables and function variables are conflated by name, such as in: get :: State s s get s = (s,s) Unfortunately, that's much more clear for an expert than a beginner in regards to what's going on there, so if you're reading code samples, likely written by people with expertise, they're going to be confusing. So, yeah. Simple concept of explicit effects. Seriously semantically overloaded stack of terms to actual reason with them about.
- Peaker 14y agoMinor nitpicks: "Monadic types" and "Monadic values" would be better for 4 and 5, because "Monad types" are the type constructors (which are also sometimes named types). And "monad values" is not a term I've ever heard used. Also, values have-type, they're not instance-of. So it would be slightly more accurate to say monadic values are values of a monadic type, whose type constructor is an instance of the Monad type-class. I agree better and more accurate use of accepted terminology for all these concepts could be useful. As for the namespacing issue in the examples, it might be confusing for a complete beginner, but one of the first things you learn in Haskell (ideally before Monads) is how scoping works.
- kinofcain 14y agoI'm beginning to think that all the people who have ever understood monads have written an article trying to explain them.
- p3d4nt 14y agoThis guy has managed four so far...
- DigitalJack 14y agoAnd that somehow in understanding monads, the lose the capability of explaining them.
- simonh 14y agoOnly three kinds of people have ever understood Monads - some of them died, others went mad trying to formulate explanations and the rest have forgotten all about them.
- DanWaterworth 14y agoI understand monads and use them everyday, but I've never written an article about them. I did once try to explain to someone what a monad is... that could be the reason I've never tried.
- paulrademacher 14y agoYou should write an article!
- DanWaterworth 14y agoI'll start with the continuation monad, explaining that via the Curry-Howard correspondence it is related to a double negative. I'll go on to show that the continuation monad is more general than any other monad by showing how to implement some common ones (state, list, IO, coroutines) using it. I'll finish with a half-baked analogy.
- 14y ago
- arianvanp 14y agoMonads should be a familiar concept for the seasoned C# programmer. LINQ's 'from in' syntax and the haskell monad 'do' syntax are almost the same! Heck, the type signature of SelectMany and (>>=) are even the same! (>>=) :: m a -> (a -> m b) -> m b and public static IEnumerable<TResult> SelectMany<TSource, TResult>( this IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> selector ) m = IEnumerable b = TResult a = TSource => m<a> SelectMany<a,b>(this m<a> source, Func<a,m<b>> selector) The type signatures are _EXACTLY_ the same. This isn't a coincidence. LINQ is actually a monad :) So I think taking this approach to explain the Monad voodoo to a C# programmer is the way to go. He actually uses them already :)
- daknok 14y agoLINQ is very similar to the List monad, specifically.
- chadzawistowski 14y agoFurther proof for my personal conviction that C# is a very interesting, progressive language which masquerades as a Java clone. I once copied the style of a maybe monad using LINQ - the WinRT apis lack a "FileExists?" method, so I used LINQ to search a directory's contents for a filename. An IEnumerable of size of zero represented None, and size one represented Some. Unfortunately, a simple try/catch around an attempt to open the desired file was more efficient and clearer to understand.
- daknok 14y agoYou should use try/catch; branching would imply a race condition in a multithreaded environment (what if another process deletes the file between the check and the use of the file?).
- krallja 14y agoLINQ has an .Empty() extension method, and you should use that instead of .Count()==0 when determining if an expression is empty.
- 14y ago
- daniel-levin 14y agoMonads are actually a very simple concept. They're really hard to understand at first because of how much knowledge is prerequisite. I found that by teaching myself Haskell incrementally, in small steps, I was able to understand monads just as easily as anything else. For me, it was simply resolving the following dependency graph: Algebraic data types -> type classes -> functors -> applicative functors -> monoids -> monads. I need to emphasise that understanding of each stage is predicated on understanding of the previous stage. Trying to learn monads without understanding these other concepts is like trying to learn Maxwell's equations without an understanding of calculus and physics. Lippert states: "Plenty of developers have used the monad pattern entirely by accident, not realizing that they're re-inventing something that already has a name.". This is completely true. For instance, watch this video on refactoring by Ben Orenstein [1]. He 'destroy[s] conditionals with a NullObject'. This is exactly how the maybe monad works. [1] http://www.youtube.com/watch?v=DC-pQPq0acs http://www.youtube.com/watch?v=DC-pQPq0acs
- lucian1900 14y agoLearn You A Haskell teaches precisely in that order and I've found it worked great for me. I was never confused and at every step it was obvious why the concepts were useful.
- qznc 14y agoWhy do you need to understand monads? Nobody explains groups to people using integers, either.
- Scriptor 14y agoYou've never been curious about something you don't know about, but don't immediately need?
- mokus 14y agoWhether any particular tutorial is good or not, it's almost automatic that people (especially in the Haskell community) question whether we needed /yet another/, because there are already so many and most of them are not that great. IMO there's nothing wrong with more, but the fact that there are so many out there seems to perpetuate the incorrect belief that it's something you need to learn to actually use Haskell. I suspect that the GP was addressing this belief, not saying "nobody should bother learning this stuff".
- qznc 14y agoIn general the Haskell community seems way too obsessed about monads. I just checked the "official" tutorials [0]. I was happy to see they all introduce IO without talking about monads. However, the linked wiki page has a whole section about monads. In contrast, there nothing about concurrency or transactional memory, despite that fact that this is one of the strong parts of Haskell. http://www.haskell.org/haskellwiki/Tutorials http://www.haskell.org/haskellwiki/Tutorials
- papsosouid 14y ago>In general the Haskell community seems way too obsessed about monads You need to understand monads to do anything beyond trivial exercises. It is something that virtually every single person coming to haskell from another language is unfamiliar with. I don't see how a focus on such a fundamental aspect of the language is a bad thing.
- mokus 14y ago
- charlieflowers 14y agoAs a C# developer, here's the explanation that made it all crystal clear to me: http://stackoverflow.com/a/2484101/80112 http://stackoverflow.com/a/2484101/80112
- Surio 14y ago@DigitalJack's comment [http://news.ycombinator.com/item?id=5325542 http://news.ycombinator.com/item?id=5325542] reminded me of another talk on monads viewed by me recently, by none other than dear ol' Dougie! http://www.yuiblog.com/blog/2012/12/13/yuiconf-2012-talk-douglas-crockford-on-monads-and-gonads-evening-keynote/ http://www.yuiblog.com/blog/2012/12/13/yuiconf-2012-talk-dou...
- KirinDave 14y agoI tried to like this series. I really did. And it starts out so strong... The thing is, you can't escape talking about the specific implementation details of monads while talking about monads, otherwise you lose the plot of what we're doing and why. Saying, "Monads are just code patterns" is like saying, "All matter in the universe is just energy patterns," strictly correct but unhelpful for any true insight. Its okay to skip the monad laws at first, but what's not okay is to talk about why there are so many Monads or what actually constitutes a monad. The best writing I've ever seen on this subject is from Learn You A Haskell for Great Good, where they walk you through a piece of code and then show how using a monad makes it cleaner and less tedious. By the end of those 2 chapters from LYAH, you end up with the sense that monads are obvious and natural. And they are once you understand the sorts of problems they solve. I wish we had more of that.
- pmk 14y agoIf you understand function composition, you already understand monads; you just may not realize it yet. Monads are a wonderful thing, spoiled by being packaged in truly awful terminology.
- lhnz 14y agoThe simplest explanation of Monads I've ever read (as a Python developer) was actually one in a comment by a Hacker News user 'frio': http://news.ycombinator.com/item?id=4960701 http://news.ycombinator.com/item?id=4960701
- runT1ME 14y agoThat is an incorrect explanation fyi...
- lhnz 14y agoDammit, how wrong?
- lobster_johnson 14y agoThat's a decent explanation that covers part of what monads are, although since it uses Python, it cannot express the type goodness that comes with monads in languages such as Haskell and, more recently, Rust. Both Haskell and Rust exploit compile-time typing to avoid having null (or nil, or None, or whatever) pointers in the language -- something which eliminates an entire class of errors that plague most of today's languages, including Python. The reason they can do this is that with Maybe, the wrapped value is either something (Just a) or nothing (Nothing). Since Nothing is a type (more technically a type constructor), not a value -- unlike something like Python's None, or C++'s null -- it cannot be passed as the value to a function which expects a valid pointer to a different type: -- This won't work setUserName(user, Nothing) Another thing about Haskell is that the IO system relies on monads for a very specific reason, or maybe two reasons. Since Haskell is lazy and pure, it needs a mechanism to express the fact that a function has actually done some work, even though -- from the compiler's point of view -- it hasn't. For example, consider a function call such as: putStrLn "Hello world" Well, this function has nothing particular to return; in most languages it would be a "void" function or return a null value. But this would not work in Haskell, which is designed to (1) optimizes function calls that return the same value (so if you call this more than once, Haskell would normally just evaluate it once), and (2) completely eliminate function calls whose values are not used. For this reason, Haskell's putStrLn has to return a unique value every time it's run, just to convince the compiler that it should not be optimized away. And so it does -- this is the IO monad. putStrLn returns a new IO value for every call. Since it always returns a new value, this ensures that Haskell won't optimize it away. There is another aspect to the IO monad: Haskell being lazy and pure, it's allowed to evaluate everything out of order. The way the IO monad is passed, baton-style, between each operation ensures that the compiler is forced to evaluate I/O operations in the sequence they appear in the code. Well, mostly. You still have to be careful; you can easily end up in a situation where a read is only evaluated after you closed a file, for example. (I'm not a Haskell expert, so I would be happy to be corrected on any point. Note I have glossed over some technical details in my explanation that would just complicate things.)
- kybernetikos 14y agoI've also (sorry!) written a blog about understanding monads as a design pattern http://kybernetikos.com/2012/07/10/design-pattern-wrapper-with-composable-actions/ http://kybernetikos.com/2012/07/10/design-pattern-wrapper-wi... It was motivated after I'd written a simple promises library and suddenly realised that promises are monads too.