4 ms·
There are so many attempts at describing what monads are, but so few attempts at teaching why you would want to use a monad, and where it would be beneficial ov
by white-flame 11y ago
There are so many attempts at describing what monads are, but so few attempts at teaching why you would want to use a monad, and where it would be beneficial over other coding styles.
- kccqzy 11y agoMonads basically capture computation itself: it gives you a way to describe a computation in terms of smaller computations arranged in a tree. I would recommend you to take a look at the history of monad in Haskell: why Haskell's initial approach of `main :: [Request] -> IO [Response]` doesn't work, and then perhaps you will appreciate why you want them at all.
- imh 11y agoAt risk of adding to the pile of half baked pedagogy, here's my take at why they're useful. The operation to chain things together (denoted >>= and pronounced bind) in the Maybe monad has type Maybe a -> (a -> Maybe b) -> Maybe b In a more a java-like notation, this is like Maybe<B> bind(Maybe<A>, Function<A, Maybe<B>>) The Haskell notation says that it's a function that takes two arguments (separated by ->). The first argument (Maybe a) is either something of type a or Nothing. Nothing is like null. The second argument (a -> Maybe b) is a function of one argument that takes a thing of type a and returns either a thing of type b or Nothing. The Maybe monad defines this chaining function for you. It uses a function you provide to turn a Maybe a into a Maybe b. It's useful, because a popular alternative is to turn Maybe a into Maybe b by writing functions of type Maybe a -> Maybe b To write a function like that, you have to handle both cases, a normal value and a null value. This is a pain in the ass and I don't enjoy it. Wouldn't it be easier to only have to write a function that handles the non-null value? If the value is null, then it should always return null anyways! Why should I have to repeat that for each step of my code? Let's let the language detect our context (the fact that we're doing a bunch of Maybe operations) handle that for us. More generally, for monad m, >>= has type m a -> (a -> m b) -> m b You can make new monads if you define this function for it (and another function that's easier but I won't talk about). The reason it's worth doing is because it's easy to write code that handles simple values and returns complicated things (a -> m b), but hard to write code that takes complicated things and returns complicated things (m a -> m b). With monads, you write the complicated version once and then write simple code every time you use it. It's no silver bullet, but it turns out to be a common pattern worth abstracting when you have structured data that you have to unpack and deal with in the same way over and over again. It's flexible too, but I won't go into that.
- txru 11y agoI really have to thank you for this comment. I had serious trouble understanding Haskell's type notation, and translating it to Java-ish was immensely helpful.
- Dateki 11y agoThese are some tangible explanations of Maybe monad in C#. Was helpful for me to understand, and now using some the concepts in my projects. http://www.codeproject.com/Articles/109026/Chained-null-checks-and-the-Maybe-monad http://www.codeproject.com/Articles/109026/Chained-null-chec...
- reddytowns 11y agoFor the "maybe a" case, you then need to take all of your code and place it in some machinery that knows what "maybe" means, and how to extract "a" from it. And then you need to write or convert all your functions to return maybe values rather than just plain values. All of this could be easily done with exceptions. Why do all that when something simple like an exception will do, is easily understood, and easily coded? If there are other common usage patterns where monads are great fit, I'd love to hear it. But, given the examples of usage I've heard about, they seem to be a somewhat painful mechanism which are useful only in a few obscure cases. Admittedly, I do not understand category theory, so I can accept that I might not be able to see the benefit unless I do.
- kccqzy 11y agoYou don't need to "place it in some machinery that knows what 'maybe' means, and how to extract 'a' from it". Because all these are defined in the standard library. If you don't like relying on the standard library you can easily implement this "machinery" with five lines of code (the Maybe definition and its Monad instance). It's all about being explicit. In many languages, even statically typed ones, like C++ and Haskell, exceptions aren't reflected in the type system. This makes it easy to forget to handle an exception. If you are not convinced about the utility of Maybe monads, maybe you can find other monads that aren't as easily mapped to other concepts in imperative languages, like the various parser monads, or just the List monad (which can be used to implement a simple parser). You don't need to understand category theory. Learning category theory is only just something nice-to-have; it can help you devise new and novel abstractions, but hey, perhaps 99% of the code don't really need new abstractions.
- aninhumer 11y agoThe benefit is that, by recognising a common pattern of composition among many different types, you can develop a whole suite of functions that work with anything that follows that composition pattern. This means you can encounter an unfamiliar monadic type, and form a decent intuition for what it does based on its purpose (although obviously you should probably check). Then you can encounter a weird new data structure, and immediately start mapping monadic functions over it without learning anything about its internals. Also, a lot of monads make it more convenient to deal with certain things more strictly (IO, checking Maybes, avoiding mutable state etc.) such that you actually do them, instead of thinking they're too much faff.