Comonad型クラス
定義例
code:hs
class Functor w => Comonad w where
extract :: w a -> a
duplicate :: w a -> w (w a)
extend :: (w a -> b) -> w a -> w b
wを使ってるのはmをひっくり返してるだけmrsekut.icon
Comonadから値を取り出す
code:hs
return :: a -> m a
extract :: w a -> a
Comonadを更にComonadに包む操作
code:hs
join :: m (m a) -> m a
duplidate :: w a -> w (w a)
元のComonadの各部分に対して関数を適用し、その結果を新しいComonadにまとめる
雑に理解
extract
selectorのようなやつ
dupulicate
コモナド自身の未来を写し出す関数
現在のcomonad、複製して一部の状態を変更したもの、それをさらに一部変更したもの、、、、の集合
Comonadが取りうる状態空間
例
code:hs
data Stream a = Cons a (Stream a)
instance Functor Stream where
fmap f (Cons x xs) = Cons (f x) (fmap f xs)
instance Comonad Stream where
extract (Cons x _) = x
duplicate s@(Cons _ xs) = Cons s (duplicate xs)
extract
Streamの先頭を取り出す
duplicate
リスト全体をシフトした新しいリストを作る
こういうStreamがあるとすると
code:hs
s = Cons 1 (Cons 2 (Cons 3 (Cons 4 ... )))
こんな感じ
code:hs
duplicate s = Cons s (Cons (tail s) (Cons (tail (tail s)) (Cons (tail (tail (tail s))) ... )))
擬似的に書くと
code:hs
「コモナドはモナドの圏論的双対」ですとか、有名なモナドに対応するコモナドがあるんですね。Reader、Writer、StateにはEnv、Traced、Storeみたいに対応してたり、みんな大好きZipperもコモナドのインスタンスだったりします。Lensっていうやつは、余状態余モナドの余代数、みたいな……(笑)ref @lotz84_: コモナドは直感的には"基点付き空間"と考えられるという解説記事。空間は可能な状態の集合により形成されており extract によって現在の状態を取り出すことが出来る。コモナドを使ったUIの実装を交えて解説されている/ Comonads as Spaces