flatMap的集合是monad吗? [英] Is a collection with flatMap a monad?
问题描述
Scala具有定义的特征Iterable[A]
Scala has the trait Iterable[A]
that defines
def flatMap[B](f: (A) ⇒ GenTraversableOnce[B]): Iterable[B]
肯定看起来就像单子上的bind函数,文档提示它是单子,但是有两个反对意见,一个是次要,一个是主要:
That certainly looks like the bind function on a monad, and the documentation hints that it is a monad, but there are two objections, one minor and one major:
- 次要的:传递的函数的返回类型是此
GenTraversableOnce
.我认为,这只是判断单调性时可以忽略的一种便利. - 主要的:monad的值"是它包含的所有值的列表,但是该函数一次被赋予一个值.
- the minor one: the return-type of the function passed in is this
GenTraversableOnce
. I think this is just a convenience that can be overlooked when judging monad-ness. - the major one: the "value" of the monad is the list of all the values it contains, but the function is given the values one at a time.
这些问题是否破坏了收藏的单调性?
Do these problems break the monad-ness of the collection?
推荐答案
主要"问题更容易回答:不,不是,因为那不是什么意思.一个monad不需要具有任何特定的值"或没有任何值",只需以特定的方式与功能组合即可.
The "major" concern is easier to answer: no, it doesn't, because that's not what it means. A monad is not required to have any particular "value" or none, only to compose with functions in particular ways.
对于未成年人",您应该关注类型.恰当地,一个monad是一个monoid(具有一些附加约束),这意味着它是具有某些操作的集合.据我所知,该集合的元素是类型为A => M[B]
的事物(在scalaz中,该类型称为Kleisli
); flatMap
是monoid的|+|
操作.
For the "minor" one, you're right to be concerned about the types. Properly, a monad is a monoid (with some additional constraints), meaning it's a set with certain operations. The elements of this set are, as far as I can tell, things of type A => M[B]
(in scalaz this type is called Kleisli
); flatMap
is the |+|
operation of the monoid.
Scala中的所有可能的 A => Iterable[B]
集合相对于此操作(以及适当的身份选择)是否构成一个单面体?不,不是非常,因为有很多A => Iterable[B]
可能违反单子法则.对于一个简单的示例,{a: A => throw new RuntimeException()}
.一个更严重的例子是如果flatMap
链中存在Set
,则这可能会破坏关联性:假设我们具有:
Does the set of all possible A => Iterable[B]
in Scala form a monoid with respect to this operation (and a suitable choice of identity)? No, very much not, because there are plenty of possible A => Iterable[B]
that violate the monad laws. For a trivial example, {a: A => throw new RuntimeException()}
. A more serious example is that e.g. if a Set
is present in a flatMap
chain, this can break associativity: suppose we have:
f: String => Iterable[String] = {s => List(s)}
g: String => Iterable[String] = {s => Set(s)}
h: String => Iterable[String] = {s => List("hi", "hi")}
然后
((f |+| g) |+| h).apply("hi") = List("hi") flatMap h = List("hi", "hi")
但是
(f |+| (g |+| h)).apply("hi") = List("hi") flatMap {s => Set("hi")} = List("hi")
令人不安,因为monoid的全部目的是我们可以编写f |+| g |+| h
,而不用担心我们用哪种方式对其进行评估.回到monads,重点是我们应该能够写
which is upsetting, because the whole point of a monoid is that we can write f |+| g |+| h
and not worry about which way we evaluate it. Going back to monads, the point is that we should be able to write
for {
a <- f("hi")
b <- g(a)
c <- h(b)
} yield c
,而不必担心flatMap
的组成顺序.但是对于上面的f
,g
和h
,您期望上面的代码给出哪个答案? (我知道答案,但这很令人惊讶).使用真正的monad时,除了作为scala编译器的实现细节之外,其他问题都不会出现,因为两种方法的答案都是相同的.
and not worry about which order the flatMap
s are composed in. But for the f
, g
and h
from above, which answer do you expect the above code to give? (I know the answer, but it's quite surprising). With a true monad, the question wouldn't come up except as a scala compiler implementation detail, because the answer would be the same either way.
另一方面, 的特定子集是否可能A => M[B]
,例如在 scalazz的scalazzi安全子集下实现的所有A => List[B]
集合",就该定义而言构成了monad flatMap
的?是(至少对于两个scala函数何时相等的公认定义).这适用于几个子集.但是我认为说Scala Iterable
的 通常在flatMap
下形成monad并不是完全正确的.
On the other hand, does a particular subset of possible A => M[B]
, e.g. "the set of all A => List[B]
implemented under the scalazzi safe subset of scala", form a monad with respect to that definition of flatMap
? Yes (at least for the commonly accepted definition of when two scala functions are equal). And there are several subsets for which this applies. But I think it's not entirely true to say that scala Iterable
s in general form a monad under flatMap
.
这篇关于flatMap的集合是monad吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!