【发布时间】: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 中的列表。那么列表不是单子吗?
【问题讨论】:
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 中的列表。那么列表不是单子吗?
【问题讨论】:
首先,单子定律假设f: A => M[A](这里是f: A => List[A])。 (x: Int) => Some[Int](x) 不是这样。
第二,List 的flatMap 是不是单子绑定。它比 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)
【讨论】:
我不是类别理论或 Haskell 专家,但我不明白你的问题,而且我的回答太大而无法评论,更不用说代码块在评论中看起来很糟糕。
Haskell 左边的恒等式是return a >>= f ≡ f a,对吧?
在 Scala 中:
return -> apply
>>= -> flatMap
因此,Scala 的左侧恒等式 List 将是 List(a).flatMap(f) = f(a)
在您的情况下,val a = 1 和 val 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]。
Some[Int](x) 转换为option2Iterable(Some[Int](x))。
List(1).flatMap(Some(_)) = List(1),没问题,但是val f = (x: Int) => Some(x); List(1).flatMap(f) 使用 2.12.2 提供 error: type mismatch。
List(1).flatMap(f(_))。谢谢。