设置排序类型拼图

时间:2013-05-31 13:21:33

标签: scala types scalaz scalaz7

昨晚在回复this question时,我注意到以下情况:

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是一组可选的整数,则对它进行排序会返回一组整数。

这不是我最初的预期,因为对F[G[A]]进行排序应该返回G[F[A]](假设F可以遍历并且G is an applicative functor )。但在这种情况下,Option图层就会消失。

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

这似乎是一个可能有趣的小谜题,我想我会在这里发布,以防有​​人可以打败我的答案。

1 个答案:

答案 0 :(得分: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是针对种类*定义的,因此针对类型类型定义了应用* - > *,Monoid sorta中Applicative的定义使用类型lambda:

在一个被忽略的类型参数中楔入
final def applicative: Applicative[({type λ[α]=F})#λ] = new Applicative[({type λ[α]=F})#λ] with SemigroupApply...

请注意,α的类型参数λ被丢弃,因此当调用Applicative#point时,它变为Monoid#zero,而不是它是Monoid [Set [Option [Int] ]]]它是一个Monoid [Set [Int]]。

larsh指出,这有一个有趣的副作用,即所有的序列U被用作总和:

scala> List(1,2,3).sequenceU
res3: Int = 6