结合2个列表的元素

bhe*_*her 4 scala scalaz applicative

假设我们有两个列表:

val l1=List("a","b","c")
val l2 = List("1","2","3")
Run Code Online (Sandbox Code Playgroud)

我想要的是:List("a1", "b2", "c3")即将l1的第n个元素与l2的第n个元素相加

实现它的一种方法是:

(l1 zip l2).map (c => {c._1+c._2})
Run Code Online (Sandbox Code Playgroud)

我只是想知道是否可以用Applicative实现它.我试过了 :

(l1 |@| l2) { _+ _ } 
Run Code Online (Sandbox Code Playgroud)

但它提供了所有组合:

List(a1, a2, a3, b1, b2, b3, c1, c2, c3)
Run Code Online (Sandbox Code Playgroud)

任何的想法?

谢谢

伯努瓦

mis*_*tor 5

你不能用严格的列表来做到这一点,所以改为使用惰性列表,即流.您必须Applicative[Stream]如下所示定义实例.(你会在名为ZipList的Haskell标准库中找到它.)

scala> val s1 = Stream("a", "b", "c")
s1: scala.collection.immutable.Stream[java.lang.String] = Stream(a, ?)

scala> val s2 = Stream("1", "2", "3")
s2: scala.collection.immutable.Stream[java.lang.String] = Stream(1, ?)

scala> implicit object StreamApplicative extends Applicative[Stream] {
     |   def pure[A](a: => A) = Stream.continually(a)
     |   override def apply[A, B](f: Stream[A => B], xs: Stream[A]): Stream[B] = (f, xs).zipped.map(_ apply _)
     | }
defined module StreamApplicative

scala> (s1 |@| s2)(_ + _)
res101: scala.collection.immutable.Stream[java.lang.String] = Stream(a1, ?)

scala> .force
res102: scala.collection.immutable.Stream[java.lang.String] = Stream(a1, b2, c3)
Run Code Online (Sandbox Code Playgroud)

使用严格列表无法做到这一点的原因是因为不可能在其pure上定义满足适用法则的内容.

另外,Scala让您比OP中使用的代码更简洁:

scala> (l1, l2).zipped.map(_ + _)
res103: List[java.lang.String] = List(a1, b2, c3)
Run Code Online (Sandbox Code Playgroud)