我把这些定义放在一个文件中:
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相矛盾,后者说:
翻译:以下身份证明:
[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,_]
答案 0 :(得分:3)
这似乎仅限于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 WHNF 继续进行undefined
。
我的猜测是因为一些奇怪的原因GHCi决定打印x
作为列表,但y
作为字符串,这是强制评估整个y
的事情而不是seq
/ evaluate
来电。