Haskell を敬遠する理由の一つがモナドだ。圏論の用語で、圏論の本で定義を見ても何のことかさっぱりわからない。しかし、使う側から考えると、モナドの本当の意味は分からなくても、データ型の一つで、例外処理もできるすぐれものだくらいの意識で使えるような気がする。
説明より実際に使ってみたほうが早い。モナド型のデータを戻り値にする関数に lookup がある。lookup は ("a", "b") の2値のタプル(値の組)のリスト [("a","b"), ("c","d"), ("e","f")]から、タプルの第一要素をキーとして第2要素を取り出す関数だ。Perl や Ruby の連想配列のようなものだ。 Hugs> lookup "a" [("a","b"), ("b", "c"), ("d", "e")] Just "b" Hugs> lookup "f" [("a","b"), ("b", "c"), ("d", "e")] Nothing このときの戻り値の型が Maybe モナドだ。検索が成功したときは Just 値が戻されそのフィールドに検索した第2要素の値が収められている。検索が失敗したときはNothing値が返される。このような複数の種類の値が帰る時は、一般にはその値を次の関数に渡す前にロジックが必要になってくる。ところが、Maybe モナドの場合 >>= 演算子を使うとロジックなしに次の関数に値を渡すことができる。 例を挙げてみよう。上にあげたタプルのリスト以外に、階層構造をもったデータも考えられる。たとえば、[("a", [("b", "c")])] のようなデータの場合タプルのリストの第二引数が、再びタプルのリストになっている。このような場合下の例のように Just の値がタプルのリストになる。 Hugs> lookup "a" [("a", [("b", "c")])] Just [("b","c")] そこで、今度は戻り値のなかのキー "b" に対応する値 "c" を求めたい場合がある。これも一般の言語なら、if lookup("a", lst) != nothing then lookup("b", lookup("a", lst)) のようなロジックになるだろう。ところが、Maybe モナドを使うとこれが >>= 演算子ひとつで実行されてしまう。たとえば、上の例でタプル("b", "c") の第二要素 "c" の値を得たいときのプログラムは次のようになる。 Hugs> lookup "a" [("a", [("b", "c")])] >>= lookup "b" Just "c" また、検索でキーのマッチが成功しなかった場合はどのレベルで不成功でも、全体の検索が不成功だったとしてNothingが返されるだけで、エラーのためにプログラムが停止するということもない。 Hugs> lookup "d" [("a", [("b", "c")])] >>= lookup "b" Nothing Hugs> lookup "a" [("a", [("b", "c")])] >>= lookup "e" Nothing 理屈や仕組みはひどく難しいモナドだが、例外をうまく処理してくれる便利なデータ型だと割り切ってしまうと使いやすく感じる。 Haskell は理屈より使ってみることから学んだほうが分かりやすいようだ。今までの言語とは異なる感覚が必要だが、むしろ、簡潔で可読性の高いプログラムが作れるような気がする。 注: Maybe 型の値から、Just の値を取り出すには、fromJust や、maybeToList 関数を使う。 Hugs> :load Maybe Maybe> fromJust $ Just 1 1 Maybe> maybeToList $ Just 1 [1] また、Maybe 関連の関数のリストを取るには、:load Mayge, :browse Maybe をすると良いようだ。 Hugs> :load Maybe Maybe> :browse Maybe module Maybe where isJust :: Maybe a -> Bool isNothing :: Maybe a -> Bool fromJust :: Maybe a -> a fromMaybe :: a -> Maybe a -> a listToMaybe :: [a] -> Maybe a maybeToList :: Maybe a -> [a] catMaybes :: [Maybe a] -> [a] mapMaybe :: (a -> Maybe b) -> [a] -> [b] Nothing :: Maybe a -- data constructor Just :: a -> Maybe a -- data constructor maybe :: a -> (b -> a) -> Maybe b -> a
by tnomura9
| 2009-08-08 11:13
| Haskell
|
Comments(0)
|
カテゴリ
新型コロナウイルス 主インデックス Haskell 記事リスト 圏論記事リスト 考えるということのリスト 考えるということ ラッセルのパラドックス Haskell Prelude Ocaml ボーカロイド 圏論 jQuery デモ HTML Python ツールボックス XAMPP Ruby ubuntu WordPress 脳の話 話のネタ リンク 幸福論 キリスト教 心の話 メモ 電子カルテ Dojo JavaScript C# NetWalker ed と sed HTML Raspberry Pi C 言語 命題論理 以前の記事
最新のトラックバック
最新のコメント
ファン
記事ランキング
ブログジャンル
画像一覧
|
ファン申請 |
||