Haskell のコンテナ系型クラスとそのインスタンスたち

自分用メモ。
便宜上、以下のクラス定義は GHC の標準ライブラリにあるものとは少し変へて最小化してある。

(ここら辺のクラスはコンテナと一般的に呼ばれてゐるが、何かを容れるものといふよりは物の在り方を示すものといった方が正確な気がするので modifier とでも呼びたい)

# Monad 系

## Functor

個人的には mappable とでも呼びたい。

```hs
class Functor f where
    fmap :: (a -> b) -> f a -> f b
```

### Functor だが pointed functor でないインスタンス

```hs
instance Functor ((,) a) where
    fmap f (x, y) = (x, f y)

newtype Const a b = Const { getConst :: a }
instance Functor (Const m) where
    fmap _ (Const v) = Const v
```

## Pointed

個人的にはこれを container とでも呼びたい。

注: Pointed は GHC の標準ライブラリには無い。

```hs
class Pointed f where
    pure :: a -> f a
```

### Pointed だが pointed functor でないインスタンス

- 集合

## Pointed functor

注: Pointed functor は GHC の標準ライブラリには無い。

```hs
class (Functor f, Pointed f) => PointedFunctor f where
```

### Pointed functor だが applicative でないインスタンス

そんなものある?

## Applicative

```hs
class PointedFunctor f => Applicative f where
    (<*>) :: f (a -> b) -> f a -> f b
```

または以下のように定義しても計算能力は実質的に同等

```hs
class PointedFunctor f => Applicative f where
    combine :: f a -> f b -> f (a, b)
```

### Applicative だが monad でないインスタンス

```hs
newtype ZipList a = ZipList { getZipList :: [a] }
instance Functor ZipList where
    fmap f (ZipList xs) = ZipList (map f xs)
instance PointedFunctor ZipList where
    pure x = ZipList (repeat x)
instance Applicative ZipList where
    ZipList fs <*> ZipList xs = ZipList (zipWith id fs xs)
```

## Monad

```hs
class Applicative f => Monad f where
    join :: f (f a) -> f a
```

### Monad のインスタンス

- `Identity`
- `Maybe`
- `[]`
- `Either e`
- `(->) r`
- `ST`
- `IO`
- ...

# Arrow 系

## Category

```hs
class Category cat where
    id :: cat a a
    (.) :: cat b c -> cat a b -> cat a c
```

### Category だが pointed category でないインスタンス

```hs
data (:~:) a b where
    Refl :: (:~:) a a
instance Category (:~:) where
    id          = Refl
    Refl . Refl = Refl
```

## Pointed category

注: Pointed category は GHC の標準ライブラリには無い。ここでの pointed category は単に pointed functor に倣って名付けたもので、零対象がある圏といふ意味ではない。

```hs
class Category cat => PointedCategory cat where
    arr :: (a -> b) -> cat a b
```

### Pointed category だが arrow でないインスタンス

何かあるのかもしれないけど思ひ付かない

## Arrow

```hs
class PointedCategory a => Arrow a where
    first :: a b c -> a (b, d) (c, d) 
```

### Arrow のインスタンス

```hs
instance Category (->) where
    id x = x
    g . f = \x -> g (f x)
instance PointedCategory (->) where
    arr f = f
instance Arrow (->) where
    first f ~(x, y) = (f x, y)
```

# Traversable 系

## Foldable

個人的には iterable あるいは collection とでも呼びたい。

```hs
class Foldable f where
    foldr :: (a -> b -> b) -> b -> f a -> b
```

### Foldable だが functor/traversable でないインスタンス

- [Haskell : An example of a Foldable which is not a Functor (or not Traversable)?](http://stackoverflow.com/q/8359115/2228481)

## Traversable

個人的には collectable とでも呼びたい。

```hs
class (Functor t, Foldable t) => Traversable t where
    sequenceA :: Applicative f => t (f a) -> f (t a)
```

### Traversable のインスタンス

- `Identity`
- `Maybe`
- `[]`
- `Either e`
- `(,) a`
- ...

# Monoid 系

## Monoid

```hs
class Monoid a where
    mempty  :: a
    mappend :: a -> a -> a
```

### Monoid だが alternative でないインスタンス

これらはホモジーニアスなコンテナではないので alternative はおろか functor ですらない。

```hs
instance Monoid b => Monoid (a -> b) where
    mempty _ = mempty
    mappend f g x = f x `mappend` g x

instance Monoid () where
    mempty        = ()
    _ `mappend` _ = ()
    mconcat _     = ()

instance (Monoid a, Monoid b) => Monoid (a,b) where
    mempty = (mempty, mempty)
    (a1,b1) `mappend` (a2,b2) =
        (a1 `mappend` a2, b1 `mappend` b2)

newtype All = All { getAll :: Bool }
instance Monoid All where
    mempty = All True
    All x `mappend` All y = All (x && y)

newtype Any = Any { getAny :: Bool }
instance Monoid Any where
    mempty = Any False
    Any x `mappend` Any y = Any (x || y)

newtype Sum a = Sum { getSum :: a }
instance Num a => Monoid (Sum a) where
    mempty = Sum 0
    Sum x `mappend` Sum y = Sum (x + y)

newtype Product a = Product { getProduct :: a }
instance Num a => Monoid (Product a) where
    mempty = Product 1
    Product x `mappend` Product y = Product (x * y)
```

注: GHC の標準ライブラリには `Monoid (Maybe a)` のインスタンスも含まれるが、 `Alternative Maybe` や `MonadPlus Maybe` とは異なる働きをする。

```hs
instance Monoid a => Monoid (Maybe a) where
  mempty = Nothing
  Nothing `mappend` m = m
  m `mappend` Nothing = m
  Just m1 `mappend` Just m2 = Just (m1 `mappend` m2)
```

## Alternative

Monoid な applicative

```hs
class Applicative f => Alternative f where
    empty :: f a
    (<|>) :: f a -> f a -> f a
```

### Alternative だが monad plus でないインスタンス

Monad plus のインスタンスが満たすべき公理について複数の流儀があり、それによって `Maybe` を monad plus と見做してよいかどうかが変はる。

## Monad plus

Monoid な monad

```hs
class Monad m => MonadPlus m where
   mzero :: m a 
   mplus :: m a -> m a -> m a
```

### Monad plus のインスタンス

```hs
instance MonadPlus [] where
   mzero = []
   mplus = (++)

instance MonadPlus Maybe where
   mzero = Nothing
   Nothing `mplus` y = y
   x       `mplus` _ = x
```

## Arrow plus

Monoid な arrow

```hs
class Arrow a => ArrowZero a where
    zeroArrow :: a b c

class ArrowZero a => ArrowPlus a where
    (<+>) :: a b c -> a b c -> a b c
```

### Arrow plus のインスタンス

```hs
newtype Kleisli m a b = Kleisli { runKleisli :: a -> m b }
instance Monad m => Category (Kleisli m) where
    id = Kleisli return
    (Kleisli f) . (Kleisli g) = Kleisli (\b -> g b >>= f)
instance Monad m => PointedCategory (Kleisli m) where
    arr f = Kleisli (return . f)
instance Monad m => Arrow (Kleisli m) where
    first (Kleisli f) = Kleisli (\ ~(b,d) -> f b >>= \c -> return (c,d))
instance MonadPlus m => ArrowZero (Kleisli m) where
    zeroArrow = Kleisli (\_ -> mzero)
instance MonadPlus m => ArrowPlus (Kleisli m) where
    Kleisli f <+> Kleisli g = Kleisli (\x -> f x `mplus` g x)
```