6 ms·
I'd say Monads shouldn't require the use of Haskell to be understood. I personally don't understand them.Some people told me it's a bit like "reversed" generic
by aikah 12y ago
I'd say Monads shouldn't require the use of Haskell to be understood.
I personally don't understand them.Some people told me it's a bit like "reversed" generics,some others pointed me at promises in Javascript which are "monadic".
I guess I don't understand them because I work with languages that make them either hard to implement or totally unnecessary.
- olavk 12y agoF# also has monads. However both Haskell and F# has syntactic sugar which makes the use of monads convenient. Without some syntactic sugar, using mondas requires chains of nested lambdas which quickly becomes convoluted and unreadable. E.g. you could use monads in JavaScript, but it would probably be simpler to solve the same problem without monads.
- eru 12y agoYou can use the chain of nested lambdas for monads in Haskell easily. That's bearable mostly thanks to the way lambda syntax works.
- thinkpad20 12y agoI'm not an expert on promises, but they certainly seem like monads. A promise, if I recall correctly, looks something like this: doThing1().then(function (thing1Result) { doThing2(thing1Result).then(function (thing2Result) { doThing3().then(function() { doThing4(thing2Result + thing1Result).then(function (res) { console.log("I did a lot of things. The answer is: " + res); } } } } Basically, at each stage we're calling a function which may or may not return immediately, and saying "whenever you're done calculating, pass your result into this function I'm giving you here." Similarly, in monadic computation, you sequence a series of "actions" together by passing each a function that determines what to do based on the output of the previous one. In Haskell, the above fake code would be written like this: doThing1 >>= \thing1Result -> doThing2 thing1Result >>= \thing2Result -> doThing3 >>= \() -> doThing4 (thing2Result + thing1Result) >>= \res -> putStrLn ("I did a lot of things. The answer is: " ++ res) So you can see the `>>=` acts like the `then` function we saw before, and each time we're passing in a new function (indicated with a backslash, which resembles a lambda). And since this kind of thing is so common, there's a syntactic sugar for all of this: thing1Result <- doThing1 thing2Result <- doThing2 thing1Result doThing3 res <- doThing4 (thing2Result + thing1Result) putStrLn ("I did a lot of things. The answer is: " ++ res) Hopefully it's simple enough to see the correspondence between the above snippet and the one before it; the two are essentially identical. Now the really cool trick is that the same concept holds up for any monadic computation; that is, any situation in which we have a series of steps, executing in a well-defined order, and at each step we have the ability to "examine" what the previous step did in some way. Thus, for example, we can model a series of fail-able computations, where the failure of any one in the chain should cause the chain to stop at that point; or a series of actions that affect a background state in some way, or a chain of effectful computations like IO, or any number of other things -- the abstract idea tends to pop up all over the place, which is one of the great powers of type classes in general: they give you tools that you can use all over the place, even in vastly different arenas.