pure 用于 zip 列表会永远重复该值,因此无法为 Scala 的 List(或类似列表的任何东西)定义一个 zippy 应用实例。 Scalaz 确实为 Stream 和适当的 zippy 应用程序实例提供了一个 Zip 标签,但据我所知,它仍然很糟糕。例如,这不起作用(但应该):
import scalaz._, Scalaz._
val xs = Tags.Zip(Stream(1, 2, 3))
val fs = Tags.Zip(Stream[Int => Int](_ + 3, _ + 2, _ + 1))
xs <*> fs
您可以直接使用应用程序实例(如在另一个答案中),但拥有语法很好,编写“真实”(即未标记)包装器并不难。这是我使用的解决方法,例如:
case class ZipList[A](s: Stream[A])
import scalaz._, Scalaz._, Isomorphism._
implicit val zipListApplicative: Applicative[ZipList] =
new IsomorphismApplicative[ZipList, ({ type L[x] = Stream[x] @@ Tags.Zip })#L] {
val iso =
new IsoFunctorTemplate[ZipList, ({ type L[x] = Stream[x] @@ Tags.Zip })#L] {
def to[A](fa: ZipList[A]) = Tags.Zip(fa.s)
def from[A](ga: Stream[A] @@ Tags.Zip) = ZipList(Tag.unwrap(ga))
}
val G = streamZipApplicative
}
然后:
scala> val xs = ZipList(Stream(1, 2, 3))
xs: ZipList[Int] = ZipList(Stream(1, ?))
scala> val fs = ZipList(Stream[Int => Int](_ + 10, _ + 11, _ + 12))
fs: ZipList[Int => Int] = ZipList(Stream(<function1>, ?))
scala> xs <*> fs
res0: ZipList[Int] = ZipList(Stream(11, ?))
scala> res0.s.toList
res1: List[Int] = List(11, 13, 15)
不管怎样,at least a couple of years 似乎已经被打破了。