Yet Another Haskell Tutorial 21

9 Monads

いよいよ Yet Another Haskell Tutorial 山系の最高峰 Monad が見えてきた。最初は知識の整理のつもりで始めたこのシリーズだったが、途中結構な難所があり、Yet Another Haskell Tutorial が初心者用の親切なチュートリアルなどではなかったことを思い知らされた。

なんで、Haskell のやさしいチュートリアルはどれもこれも易しくないのだろう。

Monad 山頂まで登れるかどうか、いささか自信がないが、登れたらHaskell 世界のすばらしい景色がみられるかもしれない。

閑話休題。さっそく、本文を見てみよう。

Haskell を学ぶ上で最も理解するのが難しい概念がモナドの概念だ。モナドを攻略するにあたって、二つの方針を考える事ができる。一つは既存のモナドの使い方を覚えるという事であり、二つ目は自分自身のモナドを作るという事だ。自分のモナドを作るという事は難しい挑戦ではあるが、それができるようになると Haskell を今までになく快適に使えるようになるだろう。

今までのところ、読者はモナドの使い方について2つ学んできた。一つは IO アクションだ。IO アクションを取り扱う上で本質的にやっかいな現実世界の問題を、モナドを使う事で一括して解決する方法を手に入れた。もう一つは、8.4.2 セクションで述べた類似の操作をつなげて使うための Computation タイプクラスだ。

どちらの場合も目的は一連のオペレーション(操作)をつなげて使う事だった。そのようなオペレーションの操作に必要な関数は次のようになる。

class Computation c where
  success :: a -> c a
  failure :: String -> c a
  augment :: c a -> (a -> c b) -> c b
  combine :: c a -> c a -> c a

これらの関数が IO にも使えるかどうかを見てみる。次の IO 関連のプログラムは、

main = do
  s <- readFile "somefile"
  putStrLn (show (f s))

Computataion (タイプ)クラスの関数 augment を使って次のように書き換える事ができる。

main = -- note the lack of a "do"
  readFile "somefile" ‘augment‘ \s ->
  putStrLn (show (f s))

(残念ながら、IO モナドの仕様で IO モナドのコンテナの値をパターンマッチで取り出せないので上の augment は IO モナドに実装する事はできない。上のプログラムは概念的なものだ。)

このように、Monad (タイプ)クラスは、本質的に上の Computation (タイプ)クラスと同じもので、次のような定義になっている。

class Monad m where
  return ::a->ma
  fail :: String -> m a
  (>>=) ::ma->(a->mb)->mb
  (>>) ::ma->mb->mb

Return 関数は success 関数に、fail 関数は failure 関数に、(>>=) (バインドと呼ぶ)演算子は augment 関数に相当している。(>>) 演算子は (>>=) 演算子の特殊なタイプだ。(>>) 演算子は次のように (>>=) 演算子で表現する事ができる。

a >> x = a >>= \_ -> x

(これまでの説明で著者が何を言いたかったのか必ずしも明快ではない。しかし、この説明で著者が言いたかったのは、Monad クラスの関数や演算子が特殊な形体をとっていても、オペレーションを組み合わせるための普通のタイプクラスの関数であるということではないのだろうか。Monad タイプクラスといえども普通のタイプクラスと同じ扱いができるという事だ。)

Yet Another Haskell Tutorial 22 へ続く ...
[PR]
by tnomura9 | 2013-03-03 19:00 | Haskell | Comments(0)
<< Yet Another Has... Yet Another Has... >>