Monad 的左单位法则似乎不适用于 Scala 中的列表。那么 scala 列表不是 monad 吗?

Monad's left unit law does not seem to hold for Lists in scala. Are scala Lists not monads then?

Monads' "left unit law":

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 中的列表。那么列表不是单子吗?

我不是范畴论专家,也不是 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.

return Option

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

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

LHS = RHS,左标识满意。

我是不是漏掉了什么?

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

其次,ListflatMap 而不是 单子绑定。它比 bind 更通用,因为它采用隐式 CanBuildFrom,允许它根据您的需要将其 return 类型更改为 return。你可以限制它像这样绑定

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)