8

昨晚在回答这个问题时,我注意到以下几点:

scala> val foo: Option[Set[Int]] = Some(Set(1, 2, 3))
foo: Option[Set[Int]] = Some(Set(1, 2, 3))

scala> import scalaz._, Scalaz._
import scalaz._
import Scalaz._

scala> foo.sequenceU
res0: scala.collection.immutable.Set[Int] = Set(1, 2, 3)

也就是说,如果foo是一个可选的整数集,则对其排序会返回一组整数。

这不是我一开始所期望的,因为排序 aF[G[A]]应该返回 a G[F[A]](假设它F是可遍历的并且G 是一个 applicative functor)。但是,在这种情况下,Option图层就会消失。

Set我知道这可能与其中一种超类型和Unapply使工作的机器之间的某些交互有关sequenceU,当我能找到几分钟的时间时,我打算研究这些类型并写下正在发生的事情的描述.

不过,这似乎是一个可能很有趣的小谜题,我想我会把它贴在这里,以防有人能打败我的答案。

4

1 回答 1

7

哇,是的。这是我可以推测正在发生的事情。因为 Set 没有它自己的 Applicative,所以我们得到了 Monoid#applicative 实例:

scala> implicitly[Unapply[Applicative, Set[Int]]].TC
res0: scalaz.Applicative[_1.M] forSome { val _1: scalaz.Unapply[scalaz.Applicative,Set[Int]] } = scalaz.Monoid$$anon$1@7f5d0856

由于 Monoid 是为 * 类型定义的,而 applicative 是为 * -> * 类型定义的,所以 Monoid 中 Applicative 的定义使用类型 lambda 楔入忽略的类型参数:

final def applicative: Applicative[({type λ[α]=F})#λ] = new Applicative[({type λ[α]=F})#λ] with SemigroupApply...

请注意,类型参数αofλ被丢弃了,所以当 Applicative#point 被调用时,它变成 Monoid#zero,而不是 Monoid[Set[Option[Int]]] 它是 Monoid[Set[Int]] .

larsh 指出,这有一个有趣的副作用,即允许将 sequenceU (ab)用作总和:

scala> List(1,2,3).sequenceU
res3: Int = 6
于 2013-05-31T13:56:02.820 回答