如何在Haskell中推理空间复杂性
我试图找到一种形式化的方法来思考haskell中的空间复杂性。我发现了图形简化(GR)技术,在我看来这是一种可行的方法。但我在某些情况下应用它时遇到了问题。考虑下面的例子: 假设我们有一棵二叉树:如何在Haskell中推理空间复杂性,haskell,complexity-theory,space,graph-reduction,Haskell,Complexity Theory,Space,Graph Reduction,我试图找到一种形式化的方法来思考haskell中的空间复杂性。我发现了图形简化(GR)技术,在我看来这是一种可行的方法。但我在某些情况下应用它时遇到了问题。考虑下面的例子: 假设我们有一棵二叉树: data Tree = Node [Tree] | Leaf [Int] makeTree :: Int -> Tree makeTree 0 = Leaf [0..99] makeTree n = Node [ makeTree (n - 1) , makeTr
data Tree = Node [Tree] | Leaf [Int]
makeTree :: Int -> Tree
makeTree 0 = Leaf [0..99]
makeTree n = Node [ makeTree (n - 1)
, makeTree (n - 1) ]
和两个遍历树的函数,一个(count1)可以很好地流式处理,另一个(count2)可以同时在内存中创建整个树;据档案员说
count1 :: Tree -> Int
count1 (Node xs) = 1 + sum (map count1 xs)
count1 (Leaf xs) = length xs
-- The r parameter should point to the root node to act as a retainer.
count2 :: Tree -> Tree -> Int
count2 r (Node xs) = 1 + sum (map (count2 r) xs)
count2 r (Leaf xs) = length xs
我想我理解它在count1的情况下是如何工作的,以下是我认为在图形缩减方面发生的情况:
count1 $ makeTree 2
=> 1 + sum $ map count1 xs
=> 1 + sum $ count1 x1 : map count1 xs
=> 1 + count1 x1 + (sum $ map count1 xs)
=> 1 + (1 + sum $ map count1 x1) + (sum $ map count1 xs)
=> 1 + (1 + sum $ (count1 x11) : map count1 x1) + (sum $ map count1 xs)
=> 1 + (1 + count1 x11 + sum $ map count1 x1) + (sum $ map count1 xs)
=> 1 + (1 + count1 x11 + sum $ map count1 x1) + (sum $ map count1 xs)
=> 1 + (1 + 100 + sum $ map count1 x1) + (sum $ map count1 xs)
=> 1 + (1 + 100 + count x12) + (sum $ map count1 xs)
=> 1 + (1 + 100 + 100) + (sum $ map count1 xs)
=> 202 + (sum $ map count1 xs)
=> ...
我认为从序列中可以清楚地看出,它在恒定的空间中运行,但在count2的情况下会发生什么变化呢
我理解其他语言中的智能指针,因此我模糊地理解count2函数中的额外r参数以某种方式防止树的节点被破坏,但我想知道确切的机制,或者至少是一个我可以在其他情况下使用的正式机制
感谢您的关注。您可以使用Adam Bakewell的空间语义
- ,2000年
或者从中工作。您能告诉我如何称呼count2吗?您的注释表明您执行了如下操作:让t=count2t中的maketree2t@lngo,是的,这是我用于测试的代码。您应该阅读一些关于垃圾收集的内容。count2不在(几乎)常量空间中运行这一事实不是Haskell的属性,而是特定Haskell实现的属性。即使对于count2,垃圾收集树也是完全合理的,但它需要编译器证明count2的第一个参数永远不可到达。这有点棘手。@Peter——线束代码中的let绑定不应该对GC产生影响。问题不在于名称是否在范围内,而在于对象是否可访问。在SPJ的两本书中有更多的细节:谢谢,第一个链接似乎直接解决了我的问题。