我已经定义了无限列表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'
,那么:p
会冻结pathCounts
,同时仍会继续pathCounts'
:
ghci> head . head $ pathCounts'
1
ghci> :p pathCounts'
pathCounts' = (1 : (_t4::[Integer])) : (_t5::[[Integer]])
ghci> :p pathCounts
^CInterrupted.
我希望:p pathCounts
与:p pathCounts'
打印相同,因为我只对其进行了部分评估。为什么不起作用?
答案 0 :(得分:8)
啊,但那是有趣的一点!事实上,你已经完全评估了我希望
: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'
会将其全部打印出来 - 而且并非如此。 t表示第一和第二部分之间存在的共享。
现在,map f (repeat x) = repeat (f x)
怎么会遇到同样的问题呢?好吧,有一点是,尽管:p
是一个指称正确的方程,但在Haskell的GHC实现中,该方程在操作上并不合理 - map
完全与操作语义有关。并且在指称语义上嗤之以鼻。特别是,repeat x
没有(不能)观察map f (repeat x)
中存在的共享;因此它产生一个非循环的无限列表。由于map f (repeat x)
共享较少,因此强制部分dim i as integer
'puts the list otems at the end of the previous row
for i = 1 to Cells(Rows.Count, "A").End(xlUp).Row
if not range("A" & i) Like "A#" then
if range("E" & i - 1) = "" Then'I assumed only 3 possible bullets, but suit this to your liking. If there are many bullets put this in a loop.
range("E" & i - 1) = range("A" & i)
ElseIf range("E" & i - 1)(,2) = "" Then
range("E" & i - 1)(,2) = range("A" & i)
ElseIf range("E" & i - 1)(,3) = "" Then
range("E" & i - 1)(,3) = range("A" & i)
Rows("i").delete Shift:=xlUp 'deletes the line
end if
next
不会导致内存中的表示完全评估。