scala - 组合 2 个列表的元素

标签 scala scalaz applicative

假设我们有两个列表:

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

我想要的是:List("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]实例如下图。 (您可以在 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)

关于scala - 组合 2 个列表的元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9166641/

相关文章:

scala - Lift 和 Lifty 入门

scala - 如何表达 Scala 的 Try 的 *finally* 等价物?

scala - 在 Scalaz 中使用自定义半群类时遇到问题

haskell - 应用风格的计算成本

haskell - GHCi 中 Applicative 的 pure 的奇怪行为

F#记录构造函数

scala - Akka TypedActor - 如何正确处理带有上下文的异步响应

scala - 为什么 sbt 会给出 Akka 和 ScalaTest 依赖项的多个依赖项警告?

performance - 以更实用的方式 (scalaz) 使用 Scala 会导致性能/可维护性损失吗?

scala - 为什么scalaz-stream中有两种网络io的实现?