Haskell:TCO和懒惰的评估

use*_*543 0 haskell lazy-evaluation tail-call-optimization

我试图理解为什么第一个main在无效时终止c,而第二个终止.从描述来看, 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
Run Code Online (Sandbox Code Playgroud)

谢谢.

Bak*_*riu 5

尾调用优化与此行为无关.问题只是第一个代码包含无限循环而第二个代码不包含.

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

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

    print(c)
    loop()
Run Code Online (Sandbox Code Playgroud)

而后者类似于:

def loop():
    c = getChar()
    if valid c:
        do_something()
    else:
        do_something_else()
        print(c)
        loop()
Run Code Online (Sandbox Code Playgroud)

注意在后一种情况下,调用loop()分支内部,else而在前者中它是在外部,因此在每次loop调用时调用.

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

例如:

main = do
    c <- return 1
    print c
Run Code Online (Sandbox Code Playgroud)

在上面的代码中return,不会阻止输出print.