LoginSignup
34
26

More than 5 years have passed since last update.

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

Last updated at Posted at 2016-07-04

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

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

Monad 系

Functor

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

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

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

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 の標準ライブラリには無い。

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

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

  • 集合

Pointed functor

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

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

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

そんなものある?

Applicative

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

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

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

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

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

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

Monad のインスタンス

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

Arrow 系

Category

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

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

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

Pointed category

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

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

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

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

Arrow

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

Arrow のインスタンス

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 とでも呼びたい。

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

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

Traversable

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

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

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

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

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

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 MaybeMonadPlus Maybe とは異なる働きをする。

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

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

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

Monad plus のインスタンス

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

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

Arrow plus

Monoid な arrow

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 のインスタンス

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)
34
26
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
34
26