方括号的“严格”

“Strictness” of square brackets

我将这些定义放在一个文件中:

x = 'a' : 'b' : 'c' : []
y = ['a', 'b', 'c']

(重要的是在文件中定义它们,而不是在 GHCi 中,因为在后一种情况下事情会变得更奇怪,但这是另一个问题。)

现在,我在 GHCi 中加载这个文件并且:

λ> :sprint x
x = _
λ> :sprint y
y = _
λ> seq x ()
()
λ> seq y ()
()
λ> :sprint x
x = 'a' : _
λ> :sprint y
y = "abc"

这是怎么回事?我明白在 x 的情况下会发生什么,这正是我所期望的。但是 y 呢?

我看到的似乎与报告的 section 3.7 相矛盾,该报告说:

Translation: The following identity holds:

[e1, …, ek] = e1 : (e2 : ( … (ek : [])))

此外:

y = [toUpper 'a', 'b', undefined]
λ> seq y ()
()
λ> :sprint y
y = "Ab*** Exception: Prelude.undefined
λ> :sprint y
*** Exception: Prelude.undefined

对于 Char 的列表,甚至强制执行实际评估,但对于其他类型,事情仍然很奇怪:

x = True : False : id False : []
y = [True, False, id False]
λ> seq x ()
()
λ> seq y ()
()
λ> :sprint x
x = True : _
λ> :sprint y
y = [True,False,_]

这似乎仅限于sprint。如果你写一个像

这样的简单程序
import Control.Exception

x, y :: String
x = 'a' : 'b' : undefined : []
y = ['a', 'b', undefined]

main :: IO ()
main = do
    evaluate x
    evaluate y
    putStrLn "Done"

然后 evaluating both to WHNF 继续而不触及 undefined

我的猜测是,出于某种奇怪的原因,GHCi 决定将 x 作为列表打印,但 y 作为字符串打印,这是强制对整个 [=14 进行评估的原因=],而不是 seq/evaluate 调用。