繁体   English   中英

为什么:当我给它这个核心值时,p冻结在GHCi中?

[英]Why does :p freeze in GHCi when I give it this corecursive value?

我已经定义了无限列表的无限列表pathCounts和无限列表的有限列表pathCounts'

import Data.Function (fix)

nextRow xs = fix $ \ys -> zipWith (+) xs (0:ys)

pathCounts = repeat 1 : map nextRow pathCounts
pathCounts' = map (take 100) pathCounts

放入ghci,如果我根本没有评估,我可以成功使用:p

ghci> :p pathCounts
pathCounts = (_t1::[[Integer]])
ghci> :p pathCounts'
pathCounts' = (_t2::[[Integer]])

但是如果我部分地评估pathCounts' ,那么:ppathCounts上冻结,同时仍然在pathCounts'pathCounts'

ghci> head . head $ pathCounts'
1
ghci> :p pathCounts'
pathCounts' = (1 : (_t4::[Integer])) : (_t5::[[Integer]])
ghci> :p pathCounts
^CInterrupted.

我希望:p pathCounts打印相同:p pathCounts' ,因为我只是部分评估它。 为什么不工作?

我希望:p pathCounts打印相同:p pathCounts' ,因为我只是部分评估它。

啊,但那是有趣的一点! 事实上,你已经完全评估了pathCounts (无限长)的头部。 让我们用一个稍小的例子来简化讨论:

> let v = repeat 1 :: [Int]
> head v
1
> :p v
^C

我声称在完全评估head v ,事实上v也被完全评估。 这是因为,在存储器中, v是循环单链表。 因此,如果您已经足够了解第一个元素,那么就没有什么可以评估了!

结果是当你要求:print它时,GHC正式尝试构造一个表示结构的所有评估部分的字符串 - 显然不能,因为它永远不会停止遍历。 :p根本没有办法表明在结构中共享。)

相比:

> let x = 1 :: Int; v = (x, x)
> fst v
1
> :p v
(1,1)

虽然您只要求评估v的第一部分,但事实上所有的v都已经在这里进行了评估,因此:p打印全部 - 并不表示第一部分和第二部分之间存在共享。

现在,为什么pathCounts'没有同样的问题? 那么,有一点是,尽管map f (repeat x) = repeat (fx)是一个表示上正确的方程,但在Haskell的GHC实现中,该方程在操作上并不合理 - 并且:p是关于操作的语义和拇指在指称语义上的鼻子。 特别是, map不会(不能)观察repeat x存在的共享; 因此它产生一个非循环的无限列表。 由于map f (repeat x)具有较少的共享,因此强制map f (repeat x)一部分不会导致完全评估的内存中表示。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM