モナドってなにさ？

# はじめに

ちょいと Haskell やってみる。むずい。
私は分析は得意ではないが、把握は得意な方です。
そう、私はジェネラリストです。

# モナドとは？

Haskell 対話環境が教えてくれる。
`$ ghci`

```haskell:ghci(Haskell)
GHCi, version 8.0.2: http://www.haskell.org/ghc/  :? for help
Prelude> :info Monad
class Applicative m => Monad (m :: * -> *) where
  (>>=) :: m a -> (a -> m b) -> m b
  (>>) :: m a -> m b -> m b
  return :: a -> m a
  fail :: String -> m a
  {-# MINIMAL (>>=) #-}
  	-- Defined in ‘GHC.Base’
instance Monad (Either e) -- Defined in ‘Data.Either’
instance Monad [] -- Defined in ‘GHC.Base’
instance Monad Maybe -- Defined in ‘GHC.Base’
instance Monad IO -- Defined in ‘GHC.Base’
instance Monad ((->) r) -- Defined in ‘GHC.Base’
instance Monoid a => Monad ((,) a) -- Defined in ‘GHC.Base’
```

わからん。が、
`class Applicative m => Monad (m :: * -> *)` となっていて、
意味は「`m` が `Monad` であるならば、`m` は `Applicative` でなければならない」と。

# アプリカティブとは？

```haskell:ghci
Prelude> :info Applicative
class Functor f => Applicative (f :: * -> *) where
  pure :: a -> f a
  (<*>) :: f (a -> b) -> f a -> f b
  (*>) :: f a -> f b -> f b
  (<*) :: f a -> f b -> f a
  {-# MINIMAL pure, (<*>) #-}
  	-- Defined in ‘GHC.Base’
instance Applicative (Either e) -- Defined in ‘Data.Either’
instance Applicative [] -- Defined in ‘GHC.Base’
instance Applicative Maybe -- Defined in ‘GHC.Base’
instance Applicative IO -- Defined in ‘GHC.Base’
instance Applicative ((->) a) -- Defined in ‘GHC.Base’
instance Monoid a => Applicative ((,) a) -- Defined in ‘GHC.Base’
```

やはりだが「`Applicative` であるためには `Functor` でなければならない」と。

# ファンクターとは？

```haskell:ghci
Prelude> :info Functor
class Functor (f :: * -> *) where
  fmap :: (a -> b) -> f a -> f b
  (<$) :: a -> f b -> f a
  {-# MINIMAL fmap #-}
  	-- Defined in ‘GHC.Base’
instance Functor (Either a) -- Defined in ‘Data.Either’
instance Functor [] -- Defined in ‘GHC.Base’
instance Functor Maybe -- Defined in ‘GHC.Base’
instance Functor IO -- Defined in ‘GHC.Base’
instance Functor ((->) r) -- Defined in ‘GHC.Base’
instance Functor ((,) a) -- Defined in ‘GHC.Base’
```

制約の連鎖が止まった。

# 再びモナドとは？

ファンクターの拡張版をアプリカティブという。
アプリカティブの拡張版をモナドという。

# 再びファンクターとは？

```haskell:Haskell
-- '引数 -> 返り値'（ラムダ抽象）
class Functor (f :: * -> *) where -- '*' は具体型を表す
  fmap :: (a -> b) -> f a -> f b  -- 'a' 'b' は任意型を表す
```

`f` がファンクターであるためには `fmap` という関数を持っていなければならない。
「オレが世界征服を果たすためには `fmap` 貫光殺砲を体得しなければならない」（？

`map` と聞けば反射的にリストを思い浮かべる。

```haskell:ghci
> :type map
map :: (a -> b) -> [a] -> [b]
--  :: (a -> b) -> [] a -> [] b と等価
-- '[]' はリスト生成前置関数
```

`fmap` と `map` を見比べると `f = []` だなと。
リストはファンクターなのかもしれないと。

```haskell:ghci
Prelude> :info Functor
class Functor (f :: * -> *) where
  fmap :: (a -> b) -> f a -> f b
  (<$) :: a -> f b -> f a
  {-# MINIMAL fmap #-}
  	-- Defined in ‘GHC.Base’
instance Functor (Either a) -- Defined in ‘Data.Either’
instance Functor [] -- Defined in ‘GHC.Base’  <== ここだよー くさかりまさおー
instance Functor Maybe -- Defined in ‘GHC.Base’
instance Functor IO -- Defined in ‘GHC.Base’
instance Functor ((->) r) -- Defined in ‘GHC.Base’
instance Functor ((,) a) -- Defined in ‘GHC.Base’
```

[GHC.Base](http://hackage.haskell.org/package/base-4.12.0.0/docs/src/GHC.Base.html) を覗くと、

```haskell:GHC.Base
instance Functor [] where
    {-# INLINE fmap #-}
    fmap = map
```

まんまだ。
リスト型 `[]` は、`fmap` を満たす `map` を持っているのでファンクターである。

ピッコロ「孫、手をぬきやがって、オレはまじめに修行して新開発したってのによ」

```haskell:Haskell
-- ピッコロ型と型生成関数の宣言
-- 'deriving (Show)' で「うまいこと文字列で表現してくれ」と頼んでいる
data Piccolo a = Piccolo a deriving (Show)

-- ピッコロ型はファンクターである
instance Functor Piccolo where
  -- fmap 実装（'g' は任意関数を表す）
  fmap g (Piccolo x) = Piccolo (g x)

-- 必殺技のアルゴリズム（値を適当倍する）
cannon :: Float -> Float
cannon = (* 4.131)
```

ピッコロ「`fmap` 貫光殺砲うけてみろ！」

```haskell:ghci
> fmap cannon (Piccolo 322)
Piccolo 1330.182
```

ラディッツ「くそ！こいつら戦闘力を自在に操りやがる！！」

関数型言語を知らない人も昨今は `map` の有り難みを知っている。
「配列とかリストとかの要素に、一気に処理をかけるやつだよね」

そう、ファンクターとは、それを更に抽象化したものだ。
配列とかリストやらの並びに制限されない `map`、
すなわち `fmap` に適用できるものだ。

この「○○に制限されない」の○○を「文脈（コンテキスト）」と言う。
上記に示した `:info Functor` の `instance` は文脈をも表している。

`Either` は「どちらか」を、
`[]` は「並び」を、
`Maybe` は「無いか有るか」を、
`IO` は「入出力」を、
`(->)` は「関数」を、
`(,)` は「組」を。

圏論の `Functor` ではなく、
`Mappable` と命名した方が分かりやすいのでは？という意見があるらしい。

# 再びアプリカティブとは？

ナッパ「あいつナメック星人だぜ」
ピッコロ「オレはナメック星人だったのか・・・」

```haskell:Haskell
data Namekian a = Namekian a deriving (Show)

instance Functor Namekian where
  fmap g (Namekian x) = Namekian (g x)

cannon :: Float -> Float
cannon = (* 4.131)
```

ネイル「わ・・・わたしと同化しろ・・・」
ピッコロ「なに！？きさまと！？」

```haskell:Haskell
class Functor f => Applicative (f :: * -> *) where
  pure :: a -> f a
  (<*>) :: f (a -> b) -> f a -> f b -- '<*>' は２引数の中置関数を表す

instance Applicative Namekian where
  pure = Namekian
  Namekian g <*> namekian = fmap g namekian

-- 同化のアルゴリズム（てきとー）
assimilate :: Float -> Float -> Float
assimilate m n = m * n / 1000
```

ネイル「お・・・おまえのその力が数倍にもなる・・・」

```haskell:ghci
> piccolo = Namekian 41310
> nail = Namekian 42000
> newPiccolo = pure assimilate <*> piccolo <*> nail
> newPiccolo
Namekian 1735020.0
> fmap cannon newPiccolo
Namekian 7167367.5
```

ピッコロ「こっ これが同化というやつなのか・・・！！」

ファンクターでは無理だった２引数関数を扱えるようになった。
それだけではない。一気に神様とだって融合できるのだ。

```haskell:Haskell
assimilate3 :: Float -> Float -> Float -> Float
assimilate3 x y z = x * y * z / 1000
```
```haskell:ghci
> kami = Namekian 220
> pure assimilate3 <*> piccolo <*> nail <*> kami
Namekian 3.8170442e8 -- もうよくわかんね
```

アプリカティブとは、関数のアリティをも制限しないファンクターなのである。
そういうことから `Applicative` ではなく、
`Zippable` の方が分かりやすいのでは？という意見があるらしい。

だが、これで終わっては次段階のモナドを見誤る。
Haskell の関数に `sequenceA` というものがある。
実際の定義よりもシンプルに下記に示す。

```haskell:Haskell
sequenceA :: Applicative f => [f a] -> f [a]
-- 空リストならば、そのまま文脈に包む
sequenceA []     = pure []
-- リストの要素を、文脈に包まれたリストに再帰的に詰め込む
-- ':' は２引数の中置関数（コンシング/詰め込みを表す）
sequenceA (x:xs) = pure (:) <*> x <*> sequenceA xs -- 再帰定義
```

ピッコロはよく自らを増殖（分裂）して戦ったものだ。

```haskell:ghci
> piccolo = Namekian 322
> replicate 3 piccolo
[Namekian 322,Namekian 322,Namekian 322]
> sequenceA (replicate 3 piccolo)
Namekian [322,322,322]
```

`replicate` は単に値を複製しているが、
`sequenceA` はそこから文脈を取り出し外側に置く。
言い換えれば、文脈（コンテキスト）を伴った反復処理を実現している。

# つまりモナドとは？！

「プログラミングの基礎」として出てくる言葉「逐次、分岐、反復」。
乱暴に言えば、この３つの機能を備えたものはチューリング完全となる。

アプリカティブまでによって逐次・反復は実現できた。
（逐次：`Applicative`、反復：`Functor`）
その拡張版がモナドなのである。
何を求め拡張するのか？
残された「分岐」である。

そう、モナドはチューリング完全を実現できるのである。
この点に関して `IO` がどうとか、`do` がどうとかの話は必要がない。
プログラマの立場からしたら、まずはこの話だけで十分ではないか？
○○モナドはこんなに便利なんだと先に聞かされても気持ちが悪い。
真っ先に知りたいのは「モナドが何者であるか」だ。

`Monad` の別名も提案があがっている。
`Chainable`, `Joinable`, `FlatMappable`

モナドの定義など見なくとも納得がいく。

連鎖できるのだ。
繋げられるのだ。
平坦に写像できるのだ。

そう、モナドならね。

なにを？
文脈を伴った計算を。

なぜ？
チューリング完全だから。

モナドはチューリング完全な Haskell の内部 DSL だ。
しかも（やはり）それはファースト・クラスなのである。
おお、すごい。

という理解でよいのでしょうか？