假设我们有两个列表:
val l1=List("a","b","c") val l2 = List("1","2","3")
我想要的是:列表(“a1”,“b2”,“c3”),即将l1的第n个元素与l2的第n个元素相加
实现它的一种方法是:
(l1 zip l2).map (c => {c._1+c._2})
我只是想知道是否可以用Applicative实现它.我试过了 :
(l1 |@| l2) { _+ _ }
但它提供了所有组合:
List(a1,a2,a3,b1,b2,b3,c1,c2,c3)
任何的想法?
谢谢
伯努瓦
解决方法
你不能用严格的列表做到这一点,所以改为使用惰性列表,即流.您必须定义Applicative [Stream]实例,如下所示. (你会在名为ZipList的Haskell标准库中找到它.)
scala> val s1 = Stream("a","c") s1: scala.collection.immutable.Stream[java.lang.String] = Stream(a,?) scala> val s2 = Stream("1","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,c3)
使用严格列表无法做到这一点的原因是因为不可能在它们上定义满足适用法则的纯粹.
另外,Scala让您比OP中使用的代码更简洁:
scala> (l1,l2).zipped.map(_ + _) res103: List[java.lang.String] = List(a1,c3)