5

このプレゼンテーション[2005] では、スライド 32 を読みました。

ジッパー データ型はコモナドを隠します。これはまさに、属性評価を構築するために必要なコモンドです。

したがって、 Zippers を Comonads で表現できるようです。これは Scala でも可能なようです。

ジッパー ソースを見ると、Clojure メタデータとして表現されているジッパーが表示されます。

私の質問は、Clojure Zippers が comonads として表現されることで利益を得るという証拠は何ですか?

エリックは、メリットは

そのため、元のグループに可能なすべてのジッパーを取得する必要があります!

4

1 に答える 1

8

あなたが求めているものには、構造上の誤りが少しあります。ジッパーはコモナドと表現できるのでなく、本来あるべきものです。

同様に、事実を受け入れるかどうかに関係なく、整数は単純に(2 つの点で!) モノイドです。

ですから、何がメリットかを問う代わりに、「共通構造を認識することで明快さを向上させることができますか?」と問うべきです。

そこでの答えは「はい!」です。


共通構造とは、どのジッパーにも 2 つの興味深いメソッドが存在することを意味します。1 つ目は、「here」関数です。これをより具体的にするために、リストジッパーを作成します

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

そして今here :: Zipper a -> a、通常 として知られている共通関数extractです。

extract = here

したがって、zipper が指すものを調べるときはいつでも、comonadic interface を使用していると言っても過言ではありません。

extractはいえ、インターフェースの退屈な側面です。さらに興味深いのはextend.

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

捉えてextendいるのは、ジッパーのすべての要素に「文脈化された変換」を適用するというアイデアです。extend共通構造は、共通共通構造全体への変換を「ing」することによって、これを行うための標準的で適切に構造化された方法があることに注意します。

このような例は、リストに畳み込みを適用することです。たとえば、少しぼかし関数を適用します。

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で、Zippers の操作で共通の構造が明らかになりました。これは、DRY を維持するのに役立ちます。

我々はまた、Zippers について何か重要なことを認識し始めました — すべての Zipper は共通項を持っているので、何らかの方法でのみ一般化して、関心のある各 Zipper でそれをing することで、extendおそらくタイプblurのすべてのZipper に一般化できます。FractionalblurKernelextend


いずれにせよ、私の例が、あなたが気付くかどうかにかかわらず、Zippers がコモナドであることを示してくれることを願っています。

これは通常、優れた Haskell 抽象化の場合に当てはまります。それらは、特定の種類のコードが動作する方法に関する自然な特性です。型クラスは、便宜上それらをキャプチャするだけです。Maybe// State/ Listetc は s でなくてもモナドになりますMonad。そしてZipper//は sでなくてもコモナドになりStoreます。TraceComonad

于 2014-08-19T11:51:31.163 に答える