“主要”问题更容易回答:不,不是,因为那不是它的意思。 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
不用担心哪个顺序flatMap
s 组成。但是对于f
, g
and h
从上面来看,您希望上面的代码给出哪个答案? (我知道答案,但这很令人惊讶)。对于真正的 monad,除了作为 scala 编译器实现细节之外,不会出现这个问题,因为无论哪种方式答案都是相同的。
另一方面,是否的一个特定子集可能的A => M[B]
,例如“所有的集合A => List[B]
下实施的scalazzi scala 的安全子集 https://i.stack.imgur.com/uEEhJ.png“,根据该定义形成一个单子flatMap
?是的(至少对于两个 scala 函数相等的普遍接受的定义而言)。这适用于几个子集。但我认为 scala 的说法并不完全正确Iterable
s 一般来说形成一个单子flatMap
.