Parallel and Concurrent Programming in Haskell という本を以前読書会で読んだが、当時はあまり理解できなかった部分もあったのでもう一度読んでサンプルコードなど書いてみようと思い立った。この本はわかりやすいし並列並行プログラミングに関して必要な要素がまとまっているとてもいい本だと思うので内容をまとつつやってみる。
英語でよければwebですべて読める
http://chimera.labs.oreilly.com/books/1230000000929/index.html
本はこちら
- 作者: Simon Marlow
- 出版社/メーカー: O'Reilly Media
- 発売日: 2013/07/12
- メディア: Kindle版
- この商品を含むブログ (2件) を見る
- 作者: Simon Marlow,山下伸夫,山本和彦,田中英行
- 出版社/メーカー: オライリージャパン
- 発売日: 2014/08/21
- メディア: 大型本
- この商品を含むブログ (2件) を見る
今回は第2章について
章のタイトル:Basic Parallelism: The Eval Monad
この章では並列プログラミングの基本的な考え方を説明している。
また、プログラムの性能チェックのやり方についてもこの章で説明されている。
最初は遅延評価とWeak Head Normal Form(WHNF)について
haskellは遅延評価を採用している言語であり各変数は必要とされるまで評価されない。
これについてghciにて確かめていく
>let x = 1 + 2 :: Int >:sprint x x = _
:sprintで変数の現在の状態を見ることができる。_は評価されていないことを表す。
上記だとxに1+2を束縛したがそれに対してなんの処理も行っていないためxは未評価となっている
seqを適用すると第一引数をWHNFまで評価することができる
WHNFとは以下のどれかを満たすもの
- data constructorが先頭に出た形
- 引数が一つ以上足りないbuild-in関数
- ラムダ式
上記のxにseqを適用してみると評価されて以下のようになる
> seq x () () > :sprint x 3
ちなみにghc7.8.3だとxの型をIntとして上記のように指定しないとNumとして保持されるため
seqで評価しても:sprintの結果は_のままになるので注意
これはMonomorphismRestrictionというオプションがデフォルトでtrueになったことに依るらしい
http://www.reddit.com/r/haskell/comments/2j56e0/sprint_behaves_differently_in_ghc_783/
リストでやってみると以下のようになる
>let ys = map id [1..3] :: [Int] >:sprint ys ys = _ >seq ys () >:sprint ys ys = _ : _ >length ys >:sprint ys ys = [_,_,_] >ys [1,2,3] >:sprint ys ys = [1,2,3]
ysに束縛する際に[Int]を忘れないように注意
seqを適用した段階でdata constructorが出た形(WHNF)になっている
lengthを適用すると中身は_で要素が3つという形に簡約される
lengthの結果に要素自体は必要ないため中身の評価は行われていない
最後にysを表示すると、表示に必要になるため中身まで評価される
2章の後半はEval Monadについてとその具体例
別にまとめることにする