我对Monad
和Applicative
之间区别的一个的理解是flatMap
上Monad
可用,但Applicative
不可用for-comprehension
}}
如果这是真的,我对这些Scala Play JSON docs感到困惑:
有趣的是,JsResult [A]是一个monadic结构 并且可以与这种结构的经典功能一起使用:
flatMap [X](f:A => JsResult [X]):JsResult [X]
等
但是,然后文档继续说:
请注意,JsResult [A]不仅仅是Monadic而且是Applicative 因为它累积了错误。这个累积特征使得JsResult [T] 因为理解而使用它并不是一件好事 你只会得到第一个错误而不是全部。
据我所知,flatMap
是JsResult
的语法糖,Applicative
如何同时为Monad
和{{1}}?
答案 0 :(得分:4)
Monad
是Applicative
的子类。 Applicative
的{{3}}操作比flatMap
弱。因此,apply
可以flatMap
实现。
但,在JsResult
(或实际Reads
)情况下,它具有利用Applicative
计算的静态形式的特殊实现。
E.g。下面的两个定义与正确的JSON等效,但Applicative
(使用and
)在错误的情况下有更好的错误消息(例如,如果bar
和quux
都无效,则会提及):
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)