Вы не можете сделать это со строгими списками, поэтому вместо этого используйте ленивые списки, то есть потоки.Вы должны определить экземпляр Applicative[Stream]
, как показано ниже.(Вы найдете его в стандартной библиотеке Haskell под именем ZipList.)
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)
Причина, по которой это невозможно сделать со строгими списками, заключается в том, что невозможно определить pure
для них, удовлетворяющихПрикладные законы.
Кроме того, Scala позволяет вам сделать это более кратко, чем код, который вы использовали в OP:
scala> (l1, l2).zipped.map(_ + _)
res103: List[java.lang.String] = List(a1, b2, c3)