5

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

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

因此,您似乎可以用 Comonads 来表达 Zippers这在 Scala 中似乎是可能的。

查看zipper 源代码,我们看到 zippers 表示为 Clojure 元数据。

我的问题是,有什么证据表明 Clojure 拉链会从以共单胞形式表达中受益?

Eric 建议这样做的好处是

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

4

1 回答 1

8

您所问的内容存在一些结构性谬误。并不是说 Zippers可以表示为 Comonads,而是它们天生的。

同样,无论您是否选择接受这个事实,整数都是幺半群(有两种方式!)。

所以,与其问有什么好处,你应该问的是“我可以通过识别单子结构来提高清晰度吗?”

答案是“是的!”


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

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

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

extract = here

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

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

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

抓住的是extend对拉链中的每个元素应用“上下文转换”的想法。Comonadic 结构指出,有一种标准且结构良好的方法可以通过“ extending”到整个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 的一些深刻的东西——每个 zipper 都有 comonadic extend,所以也许我们可以通过某种方式只概括并在我们关心的每个 Zipper 中泛化它来概括blur所有类型的 Zipper。FractionalblurKernelextend


无论如何,我希望我的例子能够证明无论你是否注意到,Zippers 都是共生词。

良好的 Haskell 抽象通常就是这种情况——它们是某些类型代码操作方式的自然属性。类型类只是为了方便而捕获它们。Maybe// State/ Listetc 将是 monad,即使它们不是Monads。和Zipper/ Store/Trace即使它们不是Comonads 也会是共胞。

于 2014-08-19T11:51:31.163 回答