这是我上一个问题的后续行动.我可以用一个迭代器,fold,zip,foreach和别人遍历Scala中的一个列表.现在我想知道是否有Zipper最合适的用例.假设我需要没有并发的只读访问权限.
你能举一个这样的例子来解释为什么这Zipper是最好的选择吗?
Tra*_*own 17
拉链的许多巧妙之处在于它们有一个comonad实例,它允许我们非常优雅地解决某类问题.
这是我头脑中的一个快速示例.假设我们有一系列数字,我们希望用指数移动平均线做一个简单的平滑形式,其中列表中每个位置的新值是当前值和所有其他值的平均值,但是与更远的邻居贡献更少.
这绝对不是一件非常难以计算的事情,但如果我们使用拉链和一个comonadic cobind,那么它与单线程的距离并不太远:
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
}
Run Code Online (Sandbox Code Playgroud)
现在,如果我们写:
val result = smooth(NonEmptyList[Double](0, 0, 0, 1, 0, 0, 0)).toList
Run Code Online (Sandbox Code Playgroud)
我们将得到道德等同于:
List(1 / 24, 1 / 12, 1 / 6, 1 / 3, 1 / 6, 1 / 12, 1 / 24)
Run Code Online (Sandbox Code Playgroud)
考虑到我们如何定义问题,这就是我们想要的.