给定任何容器类型,我们可以形成(以元素为中心的)Zipper并且知道这个结构是Comonad.最近在针对以下类型的另一个Stack Overflow问题中详细探讨了这个问题:
data Bin a = Branch (Bin a) a (Bin a) | Leaf a deriving Functor
Run Code Online (Sandbox Code Playgroud)
使用以下拉链
data Dir = L | R
data Step a = Step a Dir (Bin a) deriving Functor
data Zip a = Zip [Step a] (Bin a) deriving Functor
instance Comonad Zip where ...
Run Code Online (Sandbox Code Playgroud)
这是一个情况Zip是Comonad,虽然它的实例的建设是一个有点毛.也就是说,Zip可以完全机械地衍生出来Tree并且(我相信)任何以这种方式衍生的类型都是自动的Comonad,所以我觉得应该是这样我们可以通用和自动地构造这些类型及其组合.
实现拉链构造的一般性的一种方法是使用以下类和类型族
data Zipper t a = Zipper { diff :: D t a, here …Run Code Online (Sandbox Code Playgroud) 这是我上一个问题的后续行动.我可以用一个迭代器,fold,zip,foreach和别人遍历Scala中的一个列表.现在我想知道是否有Zipper最合适的用例.假设我需要没有并发的只读访问权限.
你能举一个这样的例子来解释为什么这Zipper是最好的选择吗?
我正在尝试使用Scala以不可变的方式编写NSGA2中使用的Deb的快速非支配排序算法(NDS).

但问题似乎比我想象的要困难,所以我在这里简化了制作MWE的问题.
想象一下,一个群体Seq[A],每个A元素decoratedA都有一个列表,其中包含指向其他群体元素的指针Seq[A].
一个函数evalA(a:decoratedA)取linkedA它包含的列表,并减少每个的值.
接下来,我将获取decoratedAPopulation人口A 的子集列表,并对evalA每个人进行调用.我有一个问题,因为在这个子集列表上的元素的每次迭代之间decoratedAPopulation,我需要A用decoratedA新的更新linkedA它包含的新的更新它包含...
更有问题的是,每个人口元素都需要更新'linkedA'来替换链接元素,如果它发生变化......

你可以看到Hum,以这种方式保持所有链表同步似乎很复杂.我提出了另一个解决方案底部,可能需要递归才能在每个EvalA替换元素的新种群后返回.

我怎样才能以不变的方式正确地做到这一点?
以可变的方式编码很容易,但我找不到以不可变的方式做到这一点的好方法,你有路径或想法吗?
object test extends App{
case class A(value:Int) {def decrement()= new A(value - 1)}
case class decoratedA(oneAdecorated:A, listOfLinkedA:Seq[A])
// We start algorithm loop with A element with value = 0
val population = Seq(new A(0), new A(0), new A(8), new A(1))
val decoratedApopulation = Seq(new …Run Code Online (Sandbox Code Playgroud)