束縛 という用語の使い方に関してより詳しい解説を頂きました
上記で説明されている通り以下の本文では正確ではない用語の使い方がありますがご了承ください
Haskellの変数には値を再代入することができません。そのため変数に値を結びつけることを代入とは言わず 束縛 と言います。
例えばトップレベルに
x :: Int
x = 12
x = 23
と書けばコンパイルがエラーになってしまいます。変数への束縛はあくまで値に名前を付ける行為であって、箱のようなものに値を入れるイメージは当てはまりません。これらの違いをよく表している例が
x = x + 1
という式でしょう。代入のイメージだと変数xから取り出した値に1を足して再び変数xに代入する操作だと考えられますが、Haskellでは変数xにはx+1という値が束縛されており、そのxとはx+1という値であり、そのxとは…という評価を無限に繰り返すためxの評価は停止しません。
この性質と遅延評価(値が必要になるまで評価されないというHaskellの評価戦略)を利用した面白いプログラムの例を紹介しましょう。
> fib = 1 : 1 : zipWith (+) fib (tail fib)
> take 10 fib
[1,1,2,3,5,8,13,21,34,55]
fibはフィボナッチ数列の無限リストを実装しています。(:)は左側の値を右側のリストの先頭に付加する関数、zipWithは二つのリストの対応する位置にある値に二項演算を適用して新しいリストを作る関数、tailはリストの先頭の要素だけを取り除く関数です。
(:) :: a -> [a] -> [a]
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
tail :: [a] -> [a]
fibは1, 1という値から始まって、次はfibの1番目とfibの2番目の要素を足し合わせた値、次はfibの2番目とfibの3番目の要素を足し合わせた値、というような無限リストとして定義されています。takeはリストからn個の値を取ってくる関数なので、
take :: Int -> [a] -> [a]
fibの値を10個取ってくるとfibの評価は10番目の要素までしか必要ないので、fibが無限リストであっても遅延評価のおかげで計算が停止するという仕組みになっています。