あなたが求めているものには、構造上の誤りが少しあります。ジッパーはコモナドと表現できるのではなく、本来あるべきものです。
同様に、事実を受け入れるかどうかに関係なく、整数は単純に(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 に一般化できます。Fractional
blurKernel
extend
いずれにせよ、私の例が、あなたが気付くかどうかにかかわらず、Zippers がコモナドであることを示してくれることを願っています。
これは通常、優れた Haskell 抽象化の場合に当てはまります。それらは、特定の種類のコードが動作する方法に関する自然な特性です。型クラスは、便宜上それらをキャプチャするだけです。Maybe
// State
/ List
etc は s でなくてもモナドになりますMonad
。そしてZipper
//は sでなくてもコモナドになりStore
ます。Trace
Comonad