Combining items from 2 lists

Suppose we have two lists:

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

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

The way to achieve this:

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

I'm just wondering if this can be achieved using applicative. I tried:

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

but he gives all the combinations:

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

Any idea?

thanks

Benoit

+4
source share
2 answers

You cannot do this with strict lists, so use lazy lists instead, i.e. streams. You must define an instance of Applicative[Stream] as shown below. (You will find it in the 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 application laws.

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

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

The answer is that you cannot achieve this with the application, as far as I can see. The list app will apply this feature to all combinations as you know. Not very good for what you want, but surprising for things like the creation of Cartesian products.

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

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

Source: https://habr.com/ru/post/1395083/


All Articles