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
?
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With