厳密なリストではそれを行うことができないため、代わりに遅延リスト、つまりストリームを使用してください。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)
厳密なリストでこれを行うことができない理由はpure
、適用法を満たす a をそれらに定義することが不可能だからです。
余談ですが、Scala を使用すると、OP で使用したコードよりも簡潔にこれを行うことができます。
scala> (l1, l2).zipped.map(_ + _)
res103: List[java.lang.String] = List(a1, b2, c3)