Combining the elements of 2 lists

混江龙づ霸主 提交于 2019-12-10 17:38:12

问题


Assume we have two lists :

val l1=List("a","b","c")
val l2 = List("1","2","3")

What I want is : List("a1", "b2", "c3") that is, adding the nth element of l1 with the nth element of l2

A way to achieve it is :

(l1 zip l2).map (c => {c._1+c._2})

I just wonder if one could achieve it with an Applicative. I tried :

(l1 |@| l2) { _+ _ } 

but it gives all the combinations :

List(a1, a2, a3, b1, b2, b3, c1, c2, c3)

Any idea?

Thank you

Benoit


回答1:


You cannot do that with strict lists, so instead use lazy lists i.e. streams. You have to define the Applicative[Stream] instance as shown below. (You'll find it in Haskell standard library under the name 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)

The reason this cannot be done with strict lists is because it is impossible to define a pure on them that satisfies the applicative laws.

As an aside, Scala lets you do this more concisely than the code you have used in OP:

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



回答2:


The answer is that you can't achieve this with an applicative as far as I can see. The applicative for list will apply the function to all combinations, as you have found out. Not great for what you want but awesome for stuff like creating cartesian products.

A slightly less verbose method might use Tuple2W.fold supplied by scalaz:

(l1 zip l2).map (_ fold (_ + _))


来源:https://stackoverflow.com/questions/9166641/combining-the-elements-of-2-lists

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!