LoginSignup
17
17

More than 5 years have passed since last update.

復習 モナド

Last updated at Posted at 2013-02-01

はじめに

monad って一体なんなのって、象の絵がかいてある本とか、色々な所で色々なやり方で論じられていると思うので、適宜調べればいいと思うんですけど、やっぱり自分用のまとめも欲しい。とりあえずここに『復習 モナド』としてまとめておきます。

レジュメ

monad.hs
-- 射の合成
(.)   ::                 (  b ->   c) -> (  a ->   b) -> (  a ->   c)
(<=<) :: Monad    m   => (  b -> m c) -> (  a -> m b) -> (  a -> m c)
(=<=) :: Comonad  w   => (w b ->   c) -> (w a ->   b) -> (w a ->   c)
(<<<) :: Category cat => cat b c      -> cat a b      -> cat a c

-- 関手
($)   ::                    (  a ->   b) -> (  a ->   b)
map   ::                    (  a ->   b) -> ([a] -> [b])
(<$>) :: Functor     f =>   (  a ->   b) -> (f a -> f b)

-- Applicative
repeat ::                  a -> [a]
pure   :: Applicative f => a -> f a
(<*>)  :: Applicative f => f (a -> b) -> (f a -> f b)

-- Monad
fmap      :: Functor f => (a -> b) -> (f a -> f b)
return    :: Monad   m => a -> m a
join      :: Monad   m => m (m a) -> m a
(=<<)     :: Monad   m => (a -> m b) -> (m a -> m b)

-- Comonad
fmap      :: Functor f => (a -> b) -> (f a -> f b)
head      ::              [a] -> a
extract   :: Comonad w => w a -> a
duplicate :: Comonad w => w a -> w (w a)
(<<=)     :: Comonad w => (w a ->   b) -> (w a -> w b)

合成と圏論

小さいプログラムを『合成 compose』して、大きなプログラムを作りたい。たとえば f :: Float -> Int という「関数」と g :: Int -> String という「関数」を組み合わせて、 (g . f) :: Float -> String という「関数」を作れる。

a -> b の a の方を『ドメイン domain』、 b の方を『余ドメイン codomain』と呼ぼう。関数 g のドメインと関数 f の余ドメインが両方とも Int だから、合成できることが分かる。

「関数」だけじゃなくて、「無限リストの処理」とか「副作用のある計算」みたいなプログラムでも同じことができる。こういった、ドメインと余ドメインを持っていて合成できるものを『射 morphism』、その全体を『圏 category』と呼ぶ。圏論は圏や射についての理論。

Haskellの (.) 演算子は関数の合成。同様に (<=<) 演算子はKleisli圏(後で出てきます)の射 (a -> m b) の合成。Haskellにはそのまま Category という名前の型クラスが定義されていて、 (<<<) 演算子はどの圏の射の合成にも使える、オールマイティーな演算子。逆向きの (>=>) や (>>>) という演算子もある。

関手とFunctor型クラス

2013年2月2日 内容が間違っているので修正

HaskellのFunctor型クラスの定義する fmap 関数は、リストのに対する map 関数を一般化したものだと思える。「関数 (a -> b)」を「コンテナ型の関数 (f a -> f b)」に変換してくれる関数を定義している。

関数の圏の対象からコンテナ型の関数の圏の対象への関数 a -> f a は『対象関数 object function』、Qiita内で圏論に言及するエントリのまとめ (2)関数からコンテナ型の関数への写像 (a -> b) → (f a -> f b) は『射関数 mapping function』にあたる。関手はこの2つの関数から成り立っている。(Functor型クラスでは射関数 fmap だけが定義されている)

『関手 functor』はには次の性質が成り立つ。

functor.hs
-- 合成の保存
functor (g <<< f) === functor g <<< functor f
-- 恒等射の保存
functor id === id

恒等射は他の射と合成しても何も変わらない射。

id.hs
id <<< f === f
g <<< id === g

よく分からないイメージ図。


  a       →【g】→      b

           ⇩ map

 [a]   →【map g】→    [b]


  a       →【g】→      b

           ⇩ fmap

 f a   →【fmap g】→   f b

(<$>) 演算子はfmapの別名で、(fmap f)(f <$>) は同じ。

どうやら時間切れのようだ……

続きはまた次回。

17
17
1

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
17
17