【发布时间】:2012-11-26 18:15:40
【问题描述】:
我对用递归替换循环的想法感到满意。我正在摆弄一个宠物项目,我想测试一些文本输入功能,所以我写了一个小命令行界面,它反复询问输入,直到它收到特定的退出命令。
看起来像这样:
getCommandsFromUser = do
putStrLn "Enter command: "
keyboardInput <- getLine
let command = map toLower keyboardInput
if command == "quit"
then
putStrLn "Good-bye!"
else do
-- stuff
-- more stuff
putStrLn ("Sending command: " ++ commandURI)
simpleHTTP $ getRequest commandURI
getCommandsFromUser
main = do
getCommandsFromUser
这完全符合预期,但是来自 C/Java 背景,它仍然让我大脑深处、黑暗、无意识的部分发痒,让我想在荨麻疹中爆发,因为我无法摆脱这样的想法,即每一个对 getCommandsFromUser 的递归调用正在创建一个新的堆栈帧。
现在,我对 IO、monad、状态、箭头等一无所知。我仍在通过 Real World Haskell 工作,我还没有达到那部分,并且其中一些代码与我在 Google 上找到的东西的模式匹配。
此外,我知道 GHC 的全部意义在于,它是一个令人发狂的优化编译器,旨在完成令人难以置信的事情,例如漂亮地展开尾递归函数等。
那么有人可以解释一下这个实现是否“正确”,如果是的话,请向我解释一下幕后发生的事情,如果这个程序被无限数量的人掌握,它会阻止它崩溃。猴子?
我知道尾调用优化是什么。我更关心它在这种情况下是如何工作的,以及正在发生的动作和一般功能杂质。
这个问题并不是因为我对 Haskell 如何使用堆栈感到困惑,并且我期望它像命令式语言一样工作;它基于这样一个事实,即我不知道 Haskell 是如何处理堆栈的,并且想知道它与传统的类 C 语言有何不同。
【问题讨论】:
-
我建议您在 SO 或一般网络上查找“尾调用优化”。这是一个通用的编译器/语言概念,不仅由 Haskell 编译器实现,也由 GCC 等实现。
-
@ThomasM.DuBuisson 从对 TCO 的严格解释来看,实际上并不明显它适用于
(>>=)右侧的事物。事实上,对于许多单子来说,它不是。非常小心以确保它确实适用于 IO。 -
@ThomasM.DuBuisson 如原始问题所述,我熟悉尾调用优化及其工作原理。我在 Haskell 的情况下询问它,特别是它在这种(单子的,不纯的)情况下的使用。
-
“尾调用优化”并不是一个真正有意义的短语,当您谈论评估像 Haskell 这样的非严格语言时。评估以完全不同的方式进行; “TCO”是您默认获得的,根本不是真正的“优化”。
标签: memory recursion functional-programming haskell