【问题标题】:JsResult - Monad or Applicative?JsResult - Monad 还是 Applicative?
【发布时间】:2014-02-06 23:35:00
【问题描述】:

我对@9​​87654325@ 和Applicative 之间区别的一个的理解是flatMap 在Monad 上可用,但在Applicative 上不可用。

如果这是真的,我对这些 Scala Play JSON docs 感到困惑:

所以有趣的是 JsResult[A] 是一个单子结构 并且可以与此类结构的经典函数一起使用:

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

等

但是,文档接着说:

请注意,JsResult[A] 不仅是 Monadic,而且是 Applicative 因为它会累积错误。这种累积特性使得 JsResult[T] 使其不太适合用于理解,因为 你只会得到第一个错误,而不是全部。

因为,据我所知,for-comprehension 是 flatMap 的语法糖,JsResult 怎么可能同时是 Applicative 和 Monad?

【问题讨论】:

  • 看看 Scalaz Validation 看看这到底意味着什么。
  • @wheaties,啊,它包含在我从事的本书(Scala 中的函数式编程)练习中 - github.com/kman007us/side-work/blob/master/MonadsSbt/src/main/…。是一样的,是吗?因此,您可以通过Monad 或Applicative 执行验证并读取所有 错误?
  • 我实际上不会回答这个问题,因为我确定我会搞砸的。将Monad 和Applicative 添加到您的标签中,我敢打赌更多的眼球会回答。基本上,Applicative 所添加的只是另外两个方法pure 和<*>。后者是“解决”链接异常的问题(前提是它们保存在Semigroup中。)
  • 另见this recent conversation Scalaz 的\/(它是一元的并且不会累积错误)和Validation(它不是一元的并且可以)。简而言之,当你有一个 monad 时,你也有一个 applicative functor,并且有一些很好的理由避免 Play 采用的方法(对于同一类型具有不同的 monadic 和 applicative 行为)。

标签: scala monads applicative playframework-json


【解决方案1】:

Monad 是Applicative 的子类。 Applicative 的 apply 操作比 flatMap 弱。因此apply 可以根据flatMap 来实现。

但是,在JsResult(或实际上是Reads)的情况下,它具有利用Applicative 计算的静态形式的特殊实现。

例如下面的两个定义与正确的 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)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-04-22
    • 1970-01-01
    • 2016-04-28
    • 1970-01-01
    • 2012-11-12
    • 2014-06-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多