Haskell の遅延評価
Haskell の特徴に遅延評価がある。これも、説明を読んでもよく意味が分からない。遅延評価という概念がどちらからというと実装よりの考え方だからだ。使う方にしてみれば、単純に無限数列(リスト)が扱えると考えるとそう難しくもない。
無限リストはデータが無限に続くのでそのままでは使えない。しかし、それをどこかで切り取るようにすれば無限リストのデータも利用が可能になってくる。たとえば、次のようなリストは途中でCtr+Cで止めない限り無限に数列を紡ぎだす。
Prelude> [1..]
しかし、take 関数を使ってそのうちの10個だけを利用するのなら、プログラムに無限リストが現われてもちっとも構わない。
Prelude> take 10 [1..]
[1,2,3,4,5,6,7,8,9,10]
これだけではそうありがたみが感じられないが、たとえば、リストの要素に番号をつけたいと思う場合がある。その時に無限リスト[1..]とリスト["a", "b", "c", "d"]をペアのタプルを作る関数 zip の引数として与えてやると次のように簡単に、番号付きのリストが出来上がる。
Prelude> zip [1..] ["a","b","c","d"]
[(1,"a"),(2,"b"),(3,"c"),(4,"d")]
フィボナッチ数なども無限数列で作っておいて、take 関数で好きなだけ取り出せばいい。
Prelude> fib = 0 : 1 : zipWith (+) fib (tail fib)
Prelude> take 10 fib
[0,1,1,2,3,5,8,13,21,34]
このように、無限数列は数列のジェネレーターとしてとらえると考えやすい。Haskell で遅延評価の話が出てきたらどこかに無限数列(リスト)が出てくるはずなのでそれを抑えておくと直感的なイメージが作れて分かりやすく感じられる。