【问题标题】:Monad's left unit law does not seem to hold for Lists in scala. Are scala Lists not monads then?Monad 的左单位定律似乎不适用于 scala 中的列表。那么scala Lists不是monad吗?
【发布时间】:2017-07-10 02:09:53
【问题描述】:

Monads 的“左单位法则”:

unit(x) flatMap f == f(x)

但是:

(List(1) flatMap ((x: Int) => Some[Int](x))) == List(1) // true
((x: Int) => Some[Int](x))(1) == Some(1) // also true

所以左单位定律不适用于 scala 中的列表。那么列表不是单子吗?

【问题讨论】:

    标签: scala monads


    【解决方案1】:

    首先,单子定律假设f: A => M[A](这里是f: A => List[A])。 (x: Int) => Some[Int](x) 不是这样。

    第二,ListflatMap不是单子绑定。它比 bind 更通用,因为它需要一个隐式的CanBuildFrom,它允许它根据您希望它返回的内容来更改其返回类型。你可以限制它像这样绑定

    def bind[A](xs: List[A])(f: A => List[A]) = xs.flatMap(f) // implicit (List.canBuildFrom)
    

    现在您可以看到满足法律要求:

    bind(List(1))(x => List(x, x)) == List(1, 1)
    

    【讨论】:

      【解决方案2】:

      我不是类别理论或 Haskell 专家,但我不明白你的问题,而且我的回答太大而无法评论,更不用说代码块在评论中看起来很糟糕。

      Haskell 左边的恒等式是return a >>= f ≡ f a,对吧?

      在 Scala 中:

      return -> apply
      >>=    -> flatMap
      

      因此,Scala 的左侧恒等式 List 将是 List(a).flatMap(f) = f(a)

      在您的情况下,val a = 1val f = (x: Int) => Some[Int](x)。但这甚至不会编译,因为Option 不是GenTraversableOnce;你不能从List.flatMap返回Option

      相反,如果我们定义val f = (x: Int) => List(x * 2),则为双重函数

      LHS: List(a).flatMap(f) = List(2)
      RHS: f(a) = List(2)
      

      LHS = RHS,左身份满足。

      我错过了什么吗?

      【讨论】:

      • 你忽略了implicit Option.option2Iterable: Option[A] => Iterable[A]
      • @HTNW 如何将其纳入范围?
      • 你不应该这样做。隐式解析规则将自动用于将Some[Int](x) 转换为option2Iterable(Some[Int](x))
      • @HTNW 有趣的是,它并不总是有效。 List(1).flatMap(Some(_)) = List(1),没问题,但是val f = (x: Int) => Some(x)List(1).flatMap(f) 使用 2.12.2 提供 error: type mismatch
      • NVM,我需要List(1).flatMap(f(_))。谢谢。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-02
      • 1970-01-01
      • 2019-05-19
      • 1970-01-01
      • 2014-05-03
      • 2018-05-05
      相关资源
      最近更新 更多