在Haskell中使用什么而不是主循环?

时间:2012-01-26 08:10:21

标签: haskell

我需要在Haskell中使用main的循环。我试过这个:

main :: IO ()
main =
  do
    putStrLn "do something"
    main

以上代码是否采取正确的方法?这种无限递归会导致溢出吗?

2 个答案:

答案 0 :(得分:37)

这很好;不会发生堆栈溢出。 Haskell中的堆栈溢出(实际上,任何非严格的语言)与其他语言中的堆栈溢出不同;它们是在没有评估它们的情况下积累大量价值而产生的,但你们并没有在这里积累任何东西;只是排序一系列无限的动作。您可以这样想:打印一行后,操作将被丢弃,控件直接传递到main;没有任何东西保留在堆栈上,因为没有什么必须返回。

同样的原因是你可以在不耗尽内存的情况下迭代无限列表:当程序进一步向下列表时,垃圾收集器会回收先前的列表单元格,因为它们不再需要。在这种情况下,之前的顺序被回收,因为没有理由保留你已经执行过的动作。

也就是说,编写这个特定示例的更好方法是:

import Control.Monad

main :: IO ()
main = forever $ putStrLn "do something"

当然,如果您的循环有意终止,这将不起作用。 forever本身是通过递归实现的,因此除了可读性之外没有任何其他好处。

答案 1 :(得分:2)

您观察到的是“尾调用消除/优化”的结果,这对Haskell来说并不特别。参见例如http://en.wikipedia.org/wiki/Tail_call