代码之家  ›  专栏  ›  技术社区  ›  kiritsuku

为什么Scalas不是monad?

  •  5
  • kiritsuku  · 技术社区  · 14 年前

    我有兴趣了解设计决策的原因 scala.Either 不是作为monad完成的。关于如何纠正偏见,已经有一些讨论 Either ,例如:

    但这里提到的细节太多了,我无法全面了解为什么要这样做。有人能概述一下有权利偏见的好处吗 任何一个 ,关于这样做的问题,以及不偏袒权利的好处 任何一个 (如果它们存在的话)?

    2 回复  |  直到 14 年前
        1
  •  8
  •   dyross    14 年前

    我认为归根结底 Principle of Least Astonishment .使用 Either 对成功或失败进行编码显然是人们所做的事情,但这并不是 任何一个 事实上,没有太多理由 Right 取得成功 Left 是传统之外的失败。正如adelbertc在上面的评论中提到的,scalaz Validation 其专门对此进行编码。

    为了进一步证明上述POLA声明的合理性,请使用以下代码:

    def foo(): Either[Int, Int] = Right(1)
    def bar(j: Int): Either[Int, Int] = Left(1)
    def baz(z: Int): Either[Int, Int] = Right(3)
    
    // Result is Left(1) 
    for (a <- foo().right; b <- bar(a).right; c <- baz(b).right) yield c
    

    这是因为我正在使用 .right 投影 for 表示这是有道理的 Left(1) 在里面 bar 是失败的情况,所以这就是结果,但想象一下如果 任何一个 正确的 -有偏见。上面的代码将在没有 正确的 表达式中的投影类似于:

    for (a <- foo(); b <- bar(a); c <- baz(b)) yield c
    

    如果您使用 任何一个 在您的代码中,如果只是“一个或另一个”类型,您会惊讶于(1)它会编译,(2)它会返回 左侧(1) 似乎从不执行 baz

    总之,使用 验证 如果你想使用 任何一个 对成功或失败进行编码。

        2
  •  5
  •   Rex Kerr    14 年前

    我不知道这是否是最初的原因,但至少有一个很好的原因。在Scala中, for 为了获得完整的功能,理解对参数的要求比它是monad更高。特别是,有这样的构造

    for (a <- ma if a > 7; /*...*/) yield /*...*/
    

    这要求monad是一个零的monad(因此,如果条件失败,您可以清空它)。

    Either 不能理智地成为零的monad(除了 Either[Unit,B] 哪里 Left(()) 可以是零)。

    一种方法是说:好吧,好吧,只是不要用你的方式来理解。另一种方法是说:好吧,好吧,根本不用麻烦做《非此即彼》。当然,这是个人喜好的问题,但我可以看出 任何一个 (在Scala中提供的常见monad中是独一无二的)一旦你尝试使用全部功能,它就会失败 对于 给你。

    推荐文章