SICP : Ex1.28 (番外編:乱数ライブラリについて)

id:lethevert:20060108:p1 で定義した乱数ライブラリを使って回答したのですが、これを使って、参照透過性について多少考察します。
fast_prime_pという関数の内部では、*(Random Int)を生成して、値を取り出して、*(Random Int)を破棄して、取り出した値だけを返しています。そのため、fast_prime_pは(確率は低いものの)評価するタイミングによって、違う値を返す可能性があります。
純粋関数型のConcurrent Cleanでは、遅延評価なので、このような関数は問題を起こす可能性があるのだと思っていたのだけれど、実際どういう問題が起こるのか?

例を挙げて考える

たとえば、faという関数が、毎回返す値が違うとして、次のような関数の引数として適用することを考える。

double a
	= a + a

faは、一回目の評価では「1」を返し、2回目の評価では「2」を返すとすると、applicative-orderの場合は、

double fa
 -> double 1
 -> 1 + 1
 -> 2

となるが、normal-orderの場合は、

double fa
 -> fa + fa
 -> 1 + 2
 -> 3

となって、矛盾が発生する。
ここまではOK。でも、Concurrent Cleanの評価はもうちょっと複雑だ。つまり、こんな感じになるはず。

double fa
 -> a + a where a = fa
 -> a + a where a = 1
 -> 1 + 1
 -> 2

これなら矛盾は生じないはず。この点で、ちょっと考え込んでいるのだ。