Concurrent Clean : 正格性について(2)

例を挙げて説明してみます。

lazy = x

strict :: !a -> a
strict a = a

strict2 :: !(!a, !b) -> (!a, !b)
strict2 (a, b) = (a, b)

maketupple :: a b -> (a, b)
maketupple a b = (a, b)

idtupple :: !(a, b) -> (a, b)
idtupple (a, b) = (a, b)

1:  idtupple $ maketupple (strict lazy) (strict lazy)
2:  idtupple $ strict2 $ maketupple lazy lazy

というようなことを書いたとして、xは正格評価されるかというと、そんなことはないんですね。
確かに、(strict x)が評価されるときには、xは正格評価されるのですが、(strict x)の値が必要になるまでは評価されないのです。
たとえば、1の式が評価されると、

idtupple $ maketupple (strict lazy) (strict lazy)

idtupple ((strict lazy), (strict lazy))

((strict lazy), (strict lazy))

となり、strict関数は評価されずに残るので、lazyは評価されません。
しかし、2の式では、

idtupple $ strict2 $ maketupple lazy lazy

idtupple $ strict2 (lazy, lazy)

idtupple $ strict2 (x, x)

idtupple (x, x)

(x, x)

と評価されて、xが出現します。

      • -

ちなみに、idtuppleに正格性注釈が全くついていないと、1の評価結果は、

maketupple (strict lazy) (strict lazy)

になるし、2の評価結果は、

strict2 $ maketupple lazy lazy

になるだけです。