Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JsResult - Monad or Applicative?

My understanding of one of the distinctions between Monad and Applicative is that flatMap is available on Monad, but not Applicative.

If that's true, I'm confused by these Scala Play JSON docs:

So what’s interesting there is that JsResult[A] is a monadic structure and can be used with classic functions of such structures:

flatMap[X](f: A => JsResult[X]): JsResult[X]

etc

But, then the docs go on to say:

Please note that JsResult[A] is not just Monadic but Applicative because it cumulates errors. This cumulative feature makes JsResult[T] makes it not very good to be used with for comprehension because you’ll get only the first error and not all.

Since, as I understand, a for-comprehension is syntactic sugar for flatMap, how can JsResult be both a Applicative and Monad?

like image 720
Kevin Meredith Avatar asked Jan 17 '14 15:01

Kevin Meredith


1 Answers

Monad is a subclass of an Applicative. Applicative's apply is weaker operation than flatMap. Thus apply could be implemented in terms of flatMap.

But, in the JsResult (or actually Reads) case, it has special implementation which exploits Applicative computation's static form.

E.g. the two definitions below behave equivalently with correct JSON, yet Applicative (which uses and) have better error messages in erroneous cases (e.g. mentions if both bar and quux are invalid):

val applicativeReads: Reads[Foo] = (
  (__ \ "bar").read[Int] and
  (__ \ "quux").read[String]
)(Foo.apply _)

val monadicReads: Reads[Foo] = for {
  bar <- (__ \ "bar").read[Int]
  quux <- (__ \ "quux").read[String]
} yield Foo(bar, quux)
like image 154
phadej Avatar answered Nov 16 '22 06:11

phadej