When to use monads from scalaz?

265 views Asked by At

I'd like to create a simple wrapper for computations. The built-in scala monads (TraversableLike) seems sufficient for me. And they have already syntax sugar. From some point of view scala collection traits are accidental monads. And there intended monads provided by the scalaz library.

What uses cases benefit from complex type classed monads of scalaz? What functionality is unfeasible for built-in monads and indicate need for scalaz?


Some clarification.

This question is not a holy war inheritance vs type classes. My question is about infrastructure that provides scalaz. Not any library with type classes approach, but this mentioned library. It slightly complicates things. But also it have bunch of utility classes that have no matches in scala collection library. Because it is a collection library, not a monadic. So the question is about the additional functionality provided by scalaz. In which cases does it matter?

1

There are 1 answers

10
Travis Brown On

First for a point about terminology: it's sometimes useful shorthand to say things like "Option is a monad", but "Option has a monad instance" or "Option is monadic" is clearer. It's potentially a little confusing to say that Scalaz provides a bunch of monads—what it provides is a Monad type class and instances of that type class for a number of types, including some of its own (e.g. \/, Task, etc.) and some from the standard library (List, Option, etc.).

So I'm going to answer a question which is similar to your question: what's the value of an explicit Monad type class over the monadic syntactic sugar provided by the standard library?

One place where having an explicit Monad representation is useful is when you want to define your own generic combinators or operations. Suppose I want to write a method addM that takes two monadic M[Int] values and adds them in the monad. It's easy to write for Option:

def addM(oa: Option[Int], ob: Option[Int]): Option[Int] = for {
  a <- oa
  b <- ob
} yield a + b

Or for lists:

def addM(oa: List[Int], ob: List[Int]): List[Int] = for {
  a <- oa
  b <- ob
} yield a + b

These two implementations obviously have a lot in common, and it'd be nice to be able to write a single generic implementation that would work in both cases—and for any other monadic type as well. This is really hard if we only have the standard library's hand-wavy monadic syntax, and really easy if we have a Monad type class.