「ほっ」と。キャンペーン

カテゴリ:ツールボックス( 2 )

Yet Another Haskell Tutorial 31

9.5 Monadic Combinators

Haskell の Control.Monad モジュールにはいろいろな monad combinator がそろっている。

• (=<<):: (a->mb)->ma->mb
• mapM:: (a->mb)->[a]->m[b]
• mapM_ :: (a->mb)->[a]->m()
• filterM:: (a->mBool)->[a]->m[a]
• foldM:: (a->b->ma)->a->[b]->ma
• sequence :: [m a] -> m [a]
• sequence_ :: [m a] -> m ()
• liftM:: (a->b)->ma->mb
• when:: Bool->m()->m()
• join:: m(ma)->ma

=<< 演算子の意味は >>= と同じだが、引数の配置が違う。そのため、return "hello, world" >>= putStrLn は、=<< を使って、putStrLn =<< return "hello, world" と書ける。

Prelude> return "hello, world" >>= putStrLn
hello, world
Prelude> putStrLn =<< return "hello, world"
hello, world

mapM と mapM_ はリストの map と同じような働きをするが、第1匹数の関数がモナドの関数である事と、結果をモナドでラッピングして返す所が異なっている。この関数はモナドでプログラムするときに非常に便利だ。

Prelude> mapM_ print [1,2,3]
1
2
3

mapM とアンダースコアのついた mapM_ の違いは、前者はモナド型の戻り値を返すが、後者は戻り値を返さないことだ。

Prelude> mapM print [1,2,3]
1
2
3
[(),(),()]
Prelude> mapM_ print [1,2,3]
1
2
3

foldM は foldl と動作が似ているが、foldM の第1引数はモナド型の値を戻す関数になる。

Prelude> :m Control.Monad
Prelude Control.Monad> foldM (\a b -> putStrLn (show a ++ "+" ++ show b ++ "=" ++ show (a+b)) >> return (a+b)) 0 [1..5]
0+1=1
1+2=3
3+3=6
6+4=10
10+5=15
15

sequence はアクションのリストを順番に実行する。

Prelude Control.Monad> sequence [print 1, print 2, print "world"]
1
2
"world"
[(),(),()]
Prelude Control.Monad> sequence_ [print 1, print 2, print "world"]
1
2
"world"

liftM 関数は2つの引数をとる。第1の引数に純粋関数をとり、それをモナド関数に変換して、第2引数のモナド値に関数適用する。これは、純粋関数をモナド値のコンテナの値に適用するのと同じ事になる。

Prelude Control.Monad> liftM (+1) (Just 5)
Just 6

応用でファイルの行に番号を打って表示するには次のようにする。

Prelude Control.Monad> :!echo "hello\nworld" > test.txt
Prelude Control.Monad> :!cat test.txt
hello
world
Prelude Control.Monad> :set +m
Prelude Control.Monad> do
Prelude Control.Monad|   l <- liftM lines (readFile "test.txt")
Prelude Control.Monad|   let n = zipWith (\n t -> show n ++ ' ' : t) [1..] l
Prelude Control.Monad|   mapM_ putStrLn n
Prelude Control.Monad|
1 hello
2 world

when は第1引数の条件が成立したときのみ、第2引数のモナド関数が実行される。

Prelude Control.Monad> mapM_ (\l -> when (not $ null l) (putStrLn l)) ["","abc","def","","","ghi"]
abc
def
ghi

join はモナドの値について concat と同じ働きをする。

Prelude Control.Monad> join (Just (Just 'a'))
Just 'a'
Prelude Control.Monad> join (Just (Nothing :: Maybe Char))
Nothing
Prelude Control.Monad> join (Nothing :: Maybe (Maybe Char))
Nothing
Prelude Control.Monad> join (return (putStrLn "hello"))
hello
Prelude Control.Monad> return (putStrLn "hello")
Prelude Control.Monad> join [[1,2,3],[4,5]]
[1,2,3,4,5]

Yet Another Haskell Tutorial 32 へ続く
[PR]
by tnomura9 | 2013-03-17 01:45 | ツールボックス | Comments(0)

ツールボックス

このブログで作った使えそうなツールのリスト

簡単QA最終版
簡単3択問題最終版
連想プロセッサ
連想プロセッサ最終版
超小型 irb もどき minirb
Linux用 minirb
wlocate と wgrep
コマンドフィルタ
Ruby で grep
Snippet Folder
PEGパーサジェネレータ最終版 peg.rb
  peg.rb 使い方
  整数の四則演算電卓ソース
  ハッシュで遊ぶプログラムのソース
  一行CSVパーサのソース
  コンパイル済みCSVパーサ
PEGコンパイラコンパイラ pegc.rb
  pegc.rb 用サンプルソース
ブログ用コード表示フィルタ
Ruby で表計算
  Ruby で表計算その1 その2 その3 アミノ酸データベース easydb.rb
  readline つき easydb.rb easydb2.rb
簡単プログラム開発環境
  edb.rb その1 edb.rb その2 Rubyシェル snrb
  変数内のプログラムを編集 edit.rb
[PR]
by tnomura9 | 2008-05-07 20:37 | ツールボックス | Comments(0)