有什么证据表明Clojure Zippers会因为表达为comonads而受益?

haw*_*eye 5 haskell clojure zipper

在本演示文稿 [2005]中,我们在幻灯片32中阅读:

zipper数据类型隐藏了一个comonad.这正是构建属性评估所需的comonad.

所以看起来你可以用Comonads来表达Zippers.这在Scala中甚至可能出现.

查看拉链源,我们看到拉链表示为Clojure元数据.

我的问题是,有什么证据证明Clojure Zippers会因为表达为comonads而受益?

埃里克建议好处是

所以我们需要在原始组中获得所有可能的拉链!

J. *_*son 8

你问的问题有点结构性的谬误.它不是拉链,可以表示为Comonads,而是说它们是本质.

同样,整数只需是幺(有两种方式!)您是否选择接受这样的事实.

因此,您应该问的问题是"我可以通过识别共同结构来提高清晰度吗?"而不是询问有什么好处?

答案是"是的!"


Comonadic结构意味着在任何拉链上都存在两种有趣的方法.第一个是明显的,显然是有用的 - "这里"功能.为了使这个更具体,我将制作一个列表拉链

data Zipper a = Zipper { before :: [a], here :: a, after :: [a] }
Run Code Online (Sandbox Code Playgroud)

现在here :: Zipper a -> a是通常称为的comonadic函数extract.

extract = here
Run Code Online (Sandbox Code Playgroud)

因此,可以公平地说,每次检查拉链指向的东西时,您都在使用comonadic界面.

也就是说,extract界面是无聊的一面.更有趣的是extend.

extend :: (Zipper a -> b) -> Zipper a -> Zipper b
Run Code Online (Sandbox Code Playgroud)

什么extend捕捉在拉链应用"语境转型"的每个元素的想法.Comonadic结构指出,有一种标准且结构良好的方法可以通过" extend转换"到整个comonad来实现.

这样的例子可能是将卷积应用于列表 - 例如,一点点模糊功能:

blurKernel :: Fractional a => Zipper a -> a
blurKernel (Zipper prior current future) =
  (a + current + c) / 3
  where
    a = case prior of
      [] -> 0
      (p:ps) -> p
    c = case future of
      [] -> 0
      (p:ps) -> p

blur :: Fractional a => Zipper a -> Zipper a
blur = extend blurKernel
Run Code Online (Sandbox Code Playgroud)

那么为什么要用blur这些术语写呢?是不是有一种自然的,递归的或迭代的表达方式可以起作用并且更明显?

好吧,通过识别blur基于comonadic扩展,我们在Zippers操作中暴露了通用结构.这对维持DRY有益.

我们也开始认识到Zippers的一些深刻意义 - 每个拉链都有comonadic extend所以也许我们可以通过某种方式推广blur到所有Fractional类型的Zipper blurKernel并将extend其整合到我们关心的每个Zipper中.


在任何情况下,我希望我的例子证明Zippers是comonads,无论你是否注意到它.

这通常就是好的Haskell抽象的情况 - 它们是关于某些代码运行方式的自然属性.为方便起见,类型类仅捕获它们.Maybe/ State/ List/ etc即使不是Monads 也是monad .和Zipper/ Store/ Trace是即使他们不是comonads Comonad秒.