Haskell GHCi如何处理中断?
我正在试验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&
: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。