Haskell中的延续与调用堆栈
Haskell(GHC)运行时如何知道在计算thunk之后接下来应该执行哪些代码 在概念层面上,这与其他编程语言中的调用堆栈有什么不同(除了在堆上存储闭合变量并具有尾部递归)?GHC(或者更确切地说,GHC RTS)与大多数东西一样,具有正常的调用堆栈 不同的是这个堆栈的内容。这与你的预期不符 假设函数Haskell中的延续与调用堆栈,haskell,ghc,Haskell,Ghc,Haskell(GHC)运行时如何知道在计算thunk之后接下来应该执行哪些代码 在概念层面上,这与其他编程语言中的调用堆栈有什么不同(除了在堆上存储闭合变量并具有尾部递归)?GHC(或者更确切地说,GHC RTS)与大多数东西一样,具有正常的调用堆栈 不同的是这个堆栈的内容。这与你的预期不符 假设函数foo调用函数bar,后者调用函数baz。您可能希望调用堆栈看起来像 foo bar baz 在某个时刻。但实际上,当foo调用bar时,“调用”真正做的就是创建一个thunk并立即返回。因此,
foo
调用函数bar
,后者调用函数baz
。您可能希望调用堆栈看起来像
foo
bar
baz
在某个时刻。但实际上,当foo
调用bar
时,“调用”真正做的就是创建一个thunk并立即返回。因此,bar
在该点不会出现在堆栈上。但是当foo
向调用者返回一些数据,并且调用者决定对其进行处理时,此时bar
可能会出现在调用堆栈上,即使foo
不可见
简言之,调用堆栈上的内容顺序与谁调用谁无关。这取决于谁看什么。您是否阅读过有关GHC工作原理的任何文档?稍微过时的无刺无标签G-machine纸和GHC评论一起涵盖了这一重要细节。@Daniel,我实际上试图阅读它们,但放弃了。像许多人一样,我通过慢慢地整理一些小信息来学习。阅读论文需要“线性”理解所有提出的概念,包括先决条件。我相信,对这个问题的回答也将有助于其他人在学习Haskell方面迈出一步。与现有文献相比,你希望在SO回答中有什么不同之处?这是一个很大的话题,“一个人必须理解先决条件”并不能通过再次写下答案来改变。我认为@sevo的观点是正确的。许多论文的目标是他们领域的专家,而不是从业者。这就是为什么我们有书籍、教程、指南和这个问答网站。然而,我同意理解先决条件是可取的(如果时间/精力允许的话)。那么最终强制thunk的代码是以类似于C调用约定的方式来实现的?或者它使用的是GHC特定的约定(和堆分配的堆栈),它们在其他方面在原则上是相似的?我在这里有点深奥,但我相信这和这个调用没有什么不同。(thunk评估代码得到一个指向正在评估的thunk的指针。我认为还有其他一些全局指针作为优化。)如果你真的对这些东西感兴趣,请查看GHC代码注释。