>>290
仕様上は保障されていないと思うけど、WinGHCiで

Prelude> :m + Debug.Trace
Prelude Debug.Trace> let bar = let {foo = "eval foo" `trace` (1,2); a = fst foo; b = snd foo} in a + b
Prelude Debug.Trace> bar
eval foo
3

となったので、少なくともこの単純な例の場合、ghciではfooは一回しか評価されないみたいね。


しかし、次の場合は二回評価される:

Prelude Debug.Trace> let bar = let {foo x = "eval foo" `trace` (x + 1, x + 2); a = fst $ foo 0; b = snd $ foo 0} in a + b
Prelude Debug.Trace> bar
eval foo
eval foo
3


で、次の例だと一回しか評価されない:

Prelude Debug.Trace> let bar = let {foo x = "eval foo" `trace` (x + 1, x + 2); (a, b) = foo 0} in a + b
Prelude Debug.Trace> bar
eval foo
3


結論としては、「いろいろ考えるのは面倒なので、>>289方式」で良いと思う。