Haskell:TCO和懒惰的评估

时间:2016-09-10 13:24:31

标签: haskell lazy-evaluation tail-call-optimization

我试图了解当main无效时第一个c没有终止的原因,而第二个终止时。来自说明here  main只是一个未评估的thunk,executing它只是构建数据结构。我试图在这里应用相同的原理,看看为什么第一个主要没有终止。如果有人可以帮助我理解这一部分,或者给我指点理解这将是伟大的。除此之外,为什么GHCI无法将其识别为TCO?这不符合定义吗?

main = loop                                                                     
  where                                                                         
   loop =  do                                                                   
     c <- getChar                                                               
     case valid c of                                                            
       Nothing -> return ()                                                     
       Just b  -> print b                                                       
     print c                                                                    
     loop                                                                       

> main :: IO ()
> main = loop
>   where
>   loop =  do
>     c <- getChar
>     case validate c of
>       Nothing -> return ()
>       Just b  -> do
>         print b
>         loop

感谢。

1 个答案:

答案 0 :(得分:5)

尾部调用优化 与此行为有关。问题很简单,第一个代码包含无限循环而第二个代码不包含。

你的第一个代码类似于命令式(python-like):

def loop():
    c = getChar()
    if valid c:
        do_something()
    else:
        do_something_else()

    print(c)
    loop()

虽然后者类似于:

def loop():
    c = getChar()
    if valid c:
        do_something()
    else:
        do_something_else()
        print(c)
        loop()

请注意,在后一种情况下,对loop()的调用分支else内,而在前者之外,因此被调用每次loop次调用。

另请注意,Haskell中的return 终止函数调用。这只是IO动作,具有一定的价值且没有副作用。

例如:

main = do
    c <- return 1
    print c

在上面的代码中,return执行而非会阻止print的输出。