4 ms·
Haskell's IO monad is decidedly not useful outside the context of Haskell and pure functional programming, both of which I do not find fun. Are monads in genera
by vertex-four 12y ago
Haskell's IO monad is decidedly not useful outside the context of Haskell and pure functional programming, both of which I do not find fun. Are monads in general useful outside that context - for example, in mostly-imperative languages like Rust?
- olavk 12y agoThe IO and State monads is specifically to solve the problem of side effects in a purely functional language, so they are not really relevant in other languages. But other uses of monads, like say monadic parsers could be useful in other languages. And list comprehensions is also based on a monad in Haskell - this functionality is clearly useful in many other languages. But without some kind of syntactic sugar (like do-notation in Haskell) the use of monads becomes far to cumbersome, and it ends up being easier to solve the same problem in an ad-hoc manner.
- fubarred 12y agoCheck out https://youtu.be/xKRndVoo2ms https://youtu.be/xKRndVoo2ms, it explains how monads can refactor messy things like call chaining if you're building SQL-like result interfaces.
- noelwelsh 12y agoApparently the authors of Rust believe monads are useful, as they come in the standard library. Rust's Option and Result types are monads, for instance. Rust lacks a feature, called higher-kinded types, that allow you to abstract over type constructors such as Option and Result and give a name to the monad concept. Thus in Rust you can create monads by convention but cannot create a type that actually embodies that concept.
- phamilton 12y agoIn Scala they are heavily used. Future, Try, Option and List are all monadic. I find Options to be fairly easy to understand and pretty useful. An example: Suppose we want a function that returns C = A + B, but only if A and B both exist. Otherwise C cannot be set with a meaningful value. In an imperative language (python-esque?)I might do something like: if A != NULL && B != NULL: C = A + B else: C = NULL in Scala: val C = for { a <- A b <- B } yield a + b What's the difference? In this example it is largely syntax, but let's do something with C. D = [1,2,3,4,5] E = [] if C != NULL: E = [x*C for x in D] else: E = D So now we've got some complex logic. If C is set, then we want to multiply every element in D by C and assign the result to E. Without monads, I have to explicitly check for C == NULL before doing anything with it. The compiler isn't going to enforce that so it's possible I forgot to check and I segfault or NPE. Here's the monadic version: val D = List(1,2,3,4,5) val E = (for { c <- C x <- D } yield c*x).getOrElse(D) With an Option monad, I must use C inside the for comprehension. This is enforced by the compiler. If C is None, then cx won't execute and the for comprehension will return None. `getOrElse` on None just returns whatever was passed in, which in this case is D. So what did we gain? Again, it might just look like syntax. We swapped an `if C != NULL` and and `else` for a `c <- C` and a `getOrElse`. We actually gained some strong compiler guarantees. Sort of a basic example and it might not be completely straightforward at first, but in my opinion once I understood how to effectively use monads (like Option and Try in Scala) my ability to simplify complex logic and be confident that it was correct increased. EDIT: Haha... I botched my final scala example. That doesn't compile... something like: val E = C.map{c => D.map(_*c)}.getOrElse(D) would do the job.
- dllthomas 12y ago"Haskell's IO monad is decidedly not useful outside the context of Haskell and pure functional programming" That's not true. It could still be useful to build up descriptions of IO that should be executed later, and an IO monad would be a fine way to do that in a language that provided the necessary capabilities to make that convenient.