# コモナド

モナドの圏論的双対

``````class Functor w => Comonad w where
extract   :: w a -> a
duplicate :: w a -> w (w a)
extend    :: (w b -> a) -> w b -> w a

duplicate = extend id
extend f  = fmap f . duplicate
``````

## 代表的なコモナド

### Env

``````type Env e a = (e, a)

extract = snd
extend f w = (fst w, f w)
``````

### Traced

Writerモナドの圏論的双対

``````type Traced e a = e -> a

instance Monoid e => Comonad (Traced e) where
extract m = m mempty
extend f m = \c -> f (\c' -> m (c <> c'))
``````

### Store

Stateモナドの圏論的双対

``````data Store s a = Store (s -> a) s

instance Functor (Store s) where
fmap f (Store g s) = Store (f . g) s

extract (Store f s) = f s
extend f (Store g s) = Store (f . Store g) s
``````

LensはStoreコモナドの余代数

``````type Lens s a = a -> Store s a
``````

### Stream

``````data Stream a = Cons a (Stream a)

instance Functor Stream where
fmap f (Cons x xs) = Cons (f xs) (fmap f xs)

extract (Cons x _) = x
duplicate xs@(Cons _ xs') = Cons xs (duplicate xs')
extend f xs@(Cons _ xs') = Cons (f xs) (extend f xs')
``````

### List Zipper

``````data Zipper a = Zipper [a] a [a]

left, right :: Zipper a -> Zipper a
left (Zipper (l:ls) c rs)) = Zipper ls l (c:rs)
right (Zipper ls c (r:rs)) = Zipper (c:ls) r rs

instance Functor Zipper where
fmap f (Zipper ls c rs) = Zipper (fmap f ls) (f c) (fmap f rs)

iterate1 :: (a -> a) -> a -> [a]
iterate1 f = tail . iterate f

extract (Zipper _ c _) = c
duplicate z = Zipper (iterate1 left z) z (iterate1 right z)
extend f z = Z (fmap f \$ iterate1 left z) (f z) (fmap f \$ iterate1 right z)

``````

## コモナドトランスフォーマー

``````class ComonadTrans t where
lower :: Comonad w => t w a -> w a
``````

## 圏論のコモナド

The comonad is a comonoid in the category of endofunctors.