Haskell GHCi如何处理中断?

Haskell GHCi如何处理中断?,haskell,lazy-evaluation,ghci,Haskell,Lazy Evaluation,Ghci,我正在试验GHCi的:sprint命令。考虑以下事项: GHCi> xs = [1..10] :: [Int] GHCi> :sprint xs xs = _ GHCi> length xs 10 GHCi> :sprint xs xs = [1,2,3,4,5,6,7,8,9,10] GHCi> xs = [1..] :: [Int] GHCi> :sprint xs xs = _ GHCi> length xs Interrupted. GHCi&

我正在试验GHCi的
:sprint
命令。考虑以下事项:

GHCi> xs = [1..10] :: [Int]
GHCi> :sprint xs
xs = _
GHCi> length xs
10
GHCi> :sprint xs
xs = [1,2,3,4,5,6,7,8,9,10]
GHCi> xs = [1..] :: [Int]
GHCi> :sprint xs
xs = _
GHCi> length xs
Interrupted.
GHCi> :sprint xs
这正如预期的那样有效。我感兴趣的是
:sprint
在中断一些计算后的行为。考虑以下事项:

GHCi> xs = [1..10] :: [Int]
GHCi> :sprint xs
xs = _
GHCi> length xs
10
GHCi> :sprint xs
xs = [1,2,3,4,5,6,7,8,9,10]
GHCi> xs = [1..] :: [Int]
GHCi> :sprint xs
xs = _
GHCi> length xs
Interrupted.
GHCi> :sprint xs
它挂起来了

预期的结果是这样的(以
s的数量为模):


是什么导致
:sprint…
冻结?为什么无法访问列表中已计算部分的相关信息?对我来说,这似乎是一个bug——没有真正的理由放弃被打断的
长度所做的所有工作。这真的是一个bug,还是我错了?

正如@Daniel Wagner在评论中解释的那样,GHCi的行为实际上完全符合您的预期。它似乎挂起是因为
length
非常快,并且计算了大量的元素,这需要
:sprint
一段时间才能打印成字符串。与普通GHCi输出不同,
:sprint
在开始打印之前强制其字符串值。如果您等待的时间足够长,
:sprint
确实会按预期打印部分字符串

您可以通过以下方式演示这一点:

GHCi> xs = [1..100000] :: [Int]
GHCi> :sprint xs
xs = _
GHCi> xs
[1,2,3,4 ... 8504^CInterrupted.
GHCi> :sprint xs
1 : 2 : 3 : 4 : ... : 8504 : _

我想它没有结冰。只是
长度
:sprint
快得多。尝试
长度(取10000 x)
后接
:sprint
,并将其与
100000
1000000
进行比较,以了解我的意思。可能在你点击^C时,
长度已经远远超过1000000个元素了。@DanielWagner我肯定下结论太快了(至少比
:sprint
快)。我习惯于常规GHCi输出从我们要求它打印列表的那一刻开始。为什么
:sprint
首先遍历整个列表?更深层次的类型构造函数会影响以前的类型构造函数吗?特别是对于列表?也许不是。但总的来说,是的。定义
数据列表a=Nil | Cons a(列表a);数据Lol=Lol | LOLOLOLOLOL
,末端有足够的垃圾,比终端宽。然后比较
:sprint
Cons-Lol(Cons-Lol-Nil)
Cons-Lol(Cons-lolol-Nil)
的完全评估版本的输出。外部
Cons
的孙子已决定第一个括号的位置。您只需稍加努力,就可以在远离括号的地方任意做出此决定。是的,第一个括号紧跟在
Cons
的子括号之后。但是它是在同一条线上还是在另一条线上是由孙子决定的@AriFordsham与
xs=map(+1)[1..10]
进行比较。thunk中的每个
(:)
都包含指向另一个thunk的链接:
1+1
,或
2+1
,等等。因此,如果您计算它的长度并运行
:sprint
,它确实会输出
s而不是
Int
s。