如何在Haskell中推理空间复杂性

如何在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

我试图找到一种形式化的方法来思考haskell中的空间复杂性。我发现了图形简化(GR)技术,在我看来这是一种可行的方法。但我在某些情况下应用它时遇到了问题。考虑下面的例子:

假设我们有一棵二叉树:

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年
Haskell目前缺乏标准的操作语义。我们认为,应该提供这样的语义,以便能够对程序的操作属性进行推理,确保实现能够保证某些空间和时间行为,并帮助确定空间故障的来源。我们为核心Haskell程序的顺序求值提出了一个小步确定语义,并证明了它是渐近空间和时间使用的精确模型。语义是图形符号的形式化,因此它提供了有用的心智模型和精确的数学符号。我们讨论它对教育、规划和实施的影响。基本语义通过一元IO机制进行扩展,以便包含实现控制下的所有空间


或者从中工作。

您能告诉我如何称呼count2吗?您的注释表明您执行了如下操作:让t=count2t中的maketree2t@lngo,是的,这是我用于测试的代码。您应该阅读一些关于垃圾收集的内容。count2不在(几乎)常量空间中运行这一事实不是Haskell的属性,而是特定Haskell实现的属性。即使对于count2,垃圾收集树也是完全合理的,但它需要编译器证明count2的第一个参数永远不可到达。这有点棘手。@Peter——线束代码中的let绑定不应该对GC产生影响。问题不在于名称是否在范围内,而在于对象是否可访问。在SPJ的两本书中有更多的细节:谢谢,第一个链接似乎直接解决了我的问题。