具有 flatMap 的集合是 monad 吗?

2024-03-10

Scala有一个特点Iterable[A]定义了

def flatMap[B](f: (A) ⇒ GenTraversableOnce[B]): Iterable[B] 

那当然looks就像 monad 上的 bind 函数一样,文档暗示它是一个 monad,但有两个反对意见,一是次要的,一是主要的:

  • 小一点:传入函数的返回类型是 thisGenTraversableOnce。我认为这只是判断单子性时可以忽略的一种便利。
  • 主要的一个:monad 的“值”是它包含的所有值的列表,但函数一次给出一个值。

这些问题是否破坏了集合的单一性?


“主要”问题更容易回答:不,不是,因为那不是它的意思。 monad 不需要具有任何特定的“值”或没有,只需以特定的方式与函数组合即可。

对于“次要”的,您担心类型是正确的。正确地说,单子是一个幺半群(有一些额外的约束),这意味着它是一个具有某些操作的集合。据我所知,这个集合的元素是类型的东西A => M[B](在 scalaz 中,这种类型称为Kleisli); flatMap is the |+|幺半群的运算。

是否有一组一切皆有可能 A => Iterable[B]在 Scala 中形成一个关于此操作的幺半群(以及合适的身份选择)?不,非常不,因为有很多可能A => Iterable[B]违反单子法则。举一个简单的例子,{a: A => throw new RuntimeException()}。一个更严重的例子是,例如如果一个Set存在于一个flatMap链,这可能会破坏关联性:假设我们有:

f: String => Iterable[String] = {s => List(s)}
g: String => Iterable[String] = {s => Set(s)}
h: String => Iterable[String] = {s => List("hi", "hi")}

Then

((f |+| g) |+| h).apply("hi") = List("hi") flatMap h = List("hi", "hi")

but

(f |+| (g |+| h)).apply("hi") = List("hi") flatMap {s => Set("hi")} = List("hi")

这是令人沮丧的,因为幺半群的全部意义在于我们可以写f |+| g |+| h不用担心我们以何种方式评估它。回到 monad,重点是我们应该能够写

for {
  a <- f("hi")
  b <- g(a)
  c <- h(b)
} yield c

不用担心哪个顺序flatMaps 组成。但是对于f, g and h从上面来看,您希望上面的代码给出哪个答案? (我知道答案,但这很令人惊讶)。对于真正的 monad,除了作为 scala 编译器实现细节之外,不会出现这个问题,因为无论哪种方式答案都是相同的。

另一方面,是否的一个特定子集可能的A => M[B],例如“所有的集合A => List[B]下实施的scalazzi scala 的安全子集 https://i.stack.imgur.com/uEEhJ.png“,根据该定义形成一个单子flatMap?是的(至少对于两个 scala 函数相等的普遍接受的定义而言)。这适用于几个子集。但我认为 scala 的说法并不完全正确Iterables 一般来说形成一个单子flatMap.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

具有 flatMap 的集合是 monad 吗? 的相关文章

随机推荐