[英]Zipper to iterate over list in Scala
这是我先前问题的跟进。 我可以使用迭代器, fold
, zip
, foreach
和其他迭代器在Scala中的列表上进行迭代。 现在,我想知道是否存在最适合使用Zipper
用例。 假设我需要没有并发的只读访问权限。
您能举一个这样的例子,并解释为什么Zipper
是最佳选择吗?
拉链的许多优点之一就是它们有一个comonad实例,这使我们可以非常优雅地解决一类问题。
这是一个简单的例子。 假设我们有一个数字序列,我们想用指数移动平均值进行简单的平滑,其中列表中每个位置的新值是当前值和所有其他值的平均值,但是较远的邻居贡献较少。
强制性地计算这并不是一件非常困难的事情,但是如果我们使用拉链和共电结合,则距离单线也不太远:
import scalaz._, Scalaz._
val weights = Stream.from(1).map(1.0 / math.pow(2, _))
def sumNeighborWeights(neighbors: Stream[Double]) =
neighbors.fzipWith(weights)(_ * _).sum
def smooth(data: NonEmptyList[Double]) = data.toZipper.cobind { z =>
(z.focus + sumNeighborWeights(z.lefts) + sumNeighborWeights(z.rights)) / 3
}
现在,如果我们写:
val result = smooth(NonEmptyList[Double](0, 0, 0, 1, 0, 0, 0)).toList
我们在道德上等同于:
List(1 / 24, 1 / 12, 1 / 6, 1 / 3, 1 / 6, 1 / 12, 1 / 24)
给定我们如何定义问题,这就是我们想要的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.