7 ms·
Inventing Monads
- peteretep 7y ago> I'm fifteen years old with good knowledge of mostly high school level math, and may have missed some parts. Kabir, Great work on getting this done. I wonder if looking around for and mentioning the similar "You Could Have Invented Monads"[0] would be a good move [0] http://blog.sigfpe.com/2006/08/you-could-have-invented-monads-and.html http://blog.sigfpe.com/2006/08/you-could-have-invented-monad...
- celeritascelery 7y agoThey say the best teacher is a recent novice.
- westoncb 7y agoThat’s interesting—I’ve noticed my ability to explain programming concepts to newcomers seems to have degraded. I think you can maintain it by continually teaching, but in my case I had a gap of 5 years or so, and trying again afterward I feel less of an understanding of the mind of a newcomer, which is instrumental in teaching...
- mjlee 7y agohttps://en.wikipedia.org/wiki/Curse_of_knowledge https://en.wikipedia.org/wiki/Curse_of_knowledge has some good sources on studies done on this concept.
- charles_f 7y agoI know "20y of professional practice in the industry expert"s who would look at you with a blank stare for such mastery of non-trivial abstractions, and yet not get it. Good job is what I mean
- kreetx 7y agoI sometimes wonder if the "old" are just so set in their ways that they (unconsciously) don't want to learn anything new. Will has great power.
- charles_f 7y agoI don't know, but I have noticed two trends: for people who have worked x years, some have x years of experience, some have x times the same year.
- kbr 7y agoThanks haha, I had exposure to computers from a very early age, and I try to make functions/systems representing things I'm curious about. It's helped me grasp ideas and come up with new ones, and I should probably write about them more :P
- rhizome31 7y agoAs one of these guys (not yet 20 years experience but close), I concur. I don't accept defeat though as I'm actually trying to learn FP for the third time! I bookmarked this blog post for when I get to monads again. Actually I'm fine with "lightweight" FP like Scheme or Elixir (HOFs, recursion, immutable data, etc.) but still struggle with "real" FP like Haskell or functional Scala (algebraic data types, monads, lenses, etc.) By the way I couldn't help to notice that the blog also features a CSS centering article. The author really is into esoteric concepts!
- charles_f 7y agoHumility and self awareness is always inspiring. As well as starting to learn new concepts 20y in. Kudos!
- scns 7y agofor a good explanation what ADTs are useful for watch Effective ML by Yaron Minsky from 18:00 https://www.youtube.com/watch?v=-J8YyfrSwTk https://www.youtube.com/watch?v=-J8YyfrSwTk
- kbr 7y agoThank you! I'll mention "You Could Have Invented Monads" along with a couple of other great resources that helped me at the end of the post.
- rswail 7y agoGreat article and it started to grok for me by the end. Although that happens every time I read an article on Monads... getting it to stick in my head is the problem. I think I need a UnderstandInTheFuture Monad in my head that maintains the state of my understanding. :D
- Toutou 7y agoGreat article, now I feel stupid.
- leo89 7y agoGood attempt, it's good thing to popularize powerfull concepts in programming, which are not as hard as most programmers think they are. However I have one big problem with this article. Code snippets are so horrible. Seems so unpractical. Perhaps because I never used functional features of Javascript?
- kbr 7y agoHey! I attempted to make the code snippets use practical concepts, but they aren't very practical for use in actual JavaScript code — the reason being that JavaScript is not a functional language and doesn't have syntactic sugar for monads. However, I chose JavaScript because I believe it's more familiar and widespread, and it can be easier to explain a foreign concept when it's done in a language that more people feel comfortable with.
- garmaine 7y agoInterestingly for someone like me who has had the luxury of never having to read or write a line of JavaScript, it was all alien gobbledygook. Whatever that code was supposed to be doing was not clear to this C++ programmer.
- kbr 7y agoSorry about that haha, the style of programming in this guide is very different from C++, and it relies heavily on currying and lambda functions using next-generation JavaScript syntax. Nonetheless, I think it can offer a new perspective because JS is more comfortable than Haskell for most developers.
- garmaine 7y agoOh I'm fine with all those concepts. C++ has anonymous functions, and I'm a Haskell programmer too. But whatever syntax JavaScript uses is not standard across other imperative languages.
- widdershins 7y agoThat's a pretty good explanation, thanks. Along with the monads in Clojure [0] article I read recently, I feel I'm getting a decent grasp on monads finally. Now they're beginning to click, I don't feel they're too complicated. Simply a way to insert a converter function between each stage in a good-old-fashioned pipeline of function applications? The converter takes the output of each function, transforms it so that it can be piped into the next function, then takes that output and combines it with the previous one, etc. Please, someone enlighten me if I've got the wrong end of the stick. [0] https://github.com/khinsen/monads-in-clojure/blob/master/PART1.md https://github.com/khinsen/monads-in-clojure/blob/master/PAR...
- rusticpenn 7y agoYou are right. Its just a simple converter function to use in a pipeline.
- IceDane 7y agoNo, not even close.
- mikekchar 7y agoYou have it right. It is literally a container that allows you to pipeline functions on its contents. The only technical catch is that you aren't allowed to change the type of the contents in the function. That means if you start with something of type A in the container, you have to get a container containing something of type A at each stage of the pipeline. There are probably 3 popular uses for monads. First to defer error handling. You allow type A to include some kind of error state. The you run your entire pipeline of functions, but at every stage if the container contains an error, you just return a container with the same error as output. That way, none of your pipeline stages need to check for valid input -- they just assume there were no errors before their stage. The second main case is to defer processing until a later time. You have a pipeline of functions and a container. As long as you don't look at the result of running that pipeline, even if the container doesn't contain anything yet you can pretend that it represents your result. You can pass that along in your program, gradually appending more functions on your pipeline as you go. When you finally put something in the container, you can see what the result is. This is useful when you don't know what your result is right now, but you know what processing you want to do when you get the input (for example, if you are going to query some external system and when it returns you want to do some processing. You can go ahead and pretend to process that result and when the data finally arrives, then you can actually get the result of the computation). The third main case is when you have a big list and you want to narrow it. For instance, you might have a list of food. You want to narrow that to a list of fruit. Then you want to narrow that to a list of red fruit. Then you want to narrow that to a list of red fruits that are berries. Instead of writing a function to do your whole query, you can separate it: A query for fruit. A query for red. A query for berries. This can make your code a lot easier to read. There are other things you can do with monads, but that's the basics IMHO. They really are simple, but suprisingly enlightening. You might think, "This constraint that I return the same type each time is kind of annoying", but if you spend a fair amount of time with monads you will see that this allows you to make pretty amazing assumptions in your code -- which, in turn, let you do very powerful things.
- juped 7y agoWow, I haven't seen a monad tutorial in over a decade. Very nostalgic post.
- pka 7y agoIf you can implement flat_map [0] for something, it's (probably) a monad. You might as well call monads FlatMappables. That's the simplest, most understandable and most accurate explanation for an initial intuition I've come up with so far. [0] https://apidock.com/ruby/Enumerable/flat_map https://apidock.com/ruby/Enumerable/flat_map
- lmm 7y agoIt needs to be associative. More concretely, if you want to have something like "do notation" that makes sense, so that you can write code like: x <- f(a) y <- g(b) z <- h(c) for composition, then it needs to be the case that x.flatMap(a => f(a)).flatMap(b => g(b)) is equivalent to x.flatMap(a => f(a).flatMap(b => g(b))). Unfortunately people sometimes implement a flatMap where these are almost, but not quite, equivalent, which leads to very confusing behaviour and subtle bugs. You also need to be able to "point" a pure value and have the equivalences you'd expect - this often ends up being important as e.g. the base case of a recursive function.
- pka 7y agoSure! But note I said "initial intuition". return/pure and monad laws can be explained later, once one understands that there's really nothing magical about monads.
- lmm 7y agoOf course there's nothing magic. But I think it's important to grasp the definition as a whole rather than thinking monads are "just" some subset or superset - the full definition of a monad is quite short and every part of it is vital, even if it doesn't seem so to start with.
- zzo38computer 7y agoIf you have a macro then something like "do notation" could be done in a superset of JavaScript, such as something like this: const listMonad=(m,f)=>[].concat(...m.map(f)); const x=listMonad*>{ let a=yield [1,2,9]; let b=yield [3,4,5,7]; return a-b; }; Such a code can then be compiled into a ordinary JavaScript code.
- diegoperini 7y ago> Think of monads as a way to overload a semicolon. It might sound a little crazy at first, but imagine being able to override the semicolon to reduce boilerplate in specific code blocks. That's basically how monads are used in practice. Lol, this resonated well. It is both brilliant but also extremely confusing (talking with experience). In my previous company, when we collaborated while researching Monads, we ended up in this conclusion as well. Some even argued that Monads actually override the indentation before an expression to turn it into a statement which doesn't help at all either.
- Izkata 7y agoJust want to say, this guide has one massive advantage that's usually missing: multiple monads. Far too many tutorials I've seen in the past will pick only one to use as an example, then act as though that specific monad's functionality applies to monads in general, which just confuses the issue.
- proc0 7y agoMonads are not invented, they are discovered multiple times. You invent toilets and gadgets, but every time you come across a mathematical object, if it really is that object (with proofs), then it must be the same one (a.k.a. diagram commutes).