top page > computer > haskell > web_lecture > for_programmer > common_monad.html
更新日:
文責: 重城良国

共通する枠組み: モナド

(工事中 60%)

はじめに

「失敗する可能性のある関数をつなぐ」ことと「メモリ機能つきの電卓をエミュレートする」こととのあいだに何の共通点があるのだろうか。普通に考えてこれら2つのコーディングに共通点はない。そんななかでかなり茫漠とした共通点を無理矢理見つけることができる。それは「値から複雑な値への変換」を連鎖させることだ。

MaybeとState

Maybeをつなぐときに使った関数は

retM :: a -> Maybe a
bindM :: Maybe a -> (a -> Maybe b) -> Maybe b

のふたつだ。一方、Stateをつなぐときに使った関数は

retC :: a -> State a
bindC :: State a -> (a -> State b) -> State b

のふたつだ。これらの型はMaybeとStateをとりかえただけになっている。共通する構造を抽出すると

ret :: a -> m a
bind :: m a -> (a -> m b) -> m b

となる。MaybeやStateで見たようにこのふたつは

arr :: (a -> b) -> (a -> m b)
pipe :: (a -> m b) -> (b -> m c) -> (a -> m c)

のふたつと同じことだ。関数pipeは関数bindから以下のように導くことができる。

(f `pipe` g) x = f x `bind` g

モナド

関数retとbindを持ち以下の規則を満たすものがモナドである。

ret `pipe` f == f
f `pipe` ret == f
(f `pipe` g) `pipe` h == f `pipe` (g `pipe` h)

これをモナド則と呼ぶ(一般的なモナド則から変形してあるので知っている人用にことわりをいれる必要がある)。これは関数retが「値を単純にモナドにつつみこむこと」とモナド関数をつなげるときに左結合も右結合も変わらないことを意味する(もっと本質をついた解釈があれば置きかえる)。

まとめ

何であれ

a -> m a
m a -> (a -> m b) -> m b

というふたつの型の関数がありそれらがモナド則を満たしさえすれば型mはモナドである。MaybeもStateもモナドだ。なかみが何であれ関係ない。形式を満たしさえすればモナドだ。「モナド」は内容ではなく形式だ。MaybeとStateのあいだにはほとんど共通点はない。ただモナドという形式を満たすというだけだ。

冗長だがより理解しやすいモナド関数のペアは

(a -> b) -> (a -> m b)
(a -> m b) -> (b -> m c) -> (a -> m c)

である。つまり

ということだ。

(「文脈」という言葉について吟味する)

「電卓をエミュレートする」へもどる 「ファンクターとモナドのあいだ」へ

正当なCSSです! HTML5 Powered with CSS3 / styling, and Semantics