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

时间:2014-08-19 05:26:46

标签: haskell clojure zipper

this presentation [2005]中我们在幻灯片32中读到:

  

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

所以看来你可以表达Zippers in terms of Comonads。这甚至看起来possible in Scala

查看zipper source,我们看到拉链表示为Clojure元数据。

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

Eric suggests好处是

  

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

1 个答案:

答案 0 :(得分:8)

你问的问题有一些结构性的谬误。 Zippers 不能表示为Comonads,而是 本质上。

同样,整数只是幺半群(以两种方式!),无论你是否选择接受这一事实。

所以,不要问你应该问什么好处是“我可以通过识别共同结构来提高清晰度吗?”

答案是“是的!”


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

data Zipper a = Zipper { before :: [a], here :: a, after :: [a] }

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

extract = here

因此,可以公平地说每次检查拉链指向的东西时,你都在使用comonadic接口

那就是说,extract是界面的无聊一面。更有趣的是extend

extend :: (Zipper a -> b) -> Zipper a -> Zipper b

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

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

好吧,通过认识blur基于comonadic扩展,我们在Zippers操作中暴露了常见的结构。这有利于维持DRY。

我们也开始认识到Zippers的一些深刻内容 - 每个拉链都有comonadic extend所以我们可以通过某种方式概括blur来概括Fractional所有blurKernel类型的拉链1}}和extend在我们关心的每个拉链中。


无论如何,我希望我的例子证明Zippers是comonads,无论你是否注意到它。

这通常是好的Haskell抽象的情况 - 它们是关于某些类型的代码运行方式的自然属性。为方便起见,仅键入类捕获它们。 Maybe / State / List /等即使不是Monad,也会是monad。而Zipper / Store / Trace即使不是Comonad也是comonads。