【问题标题】:Haskell: TCO and Lazy evaluationHaskell:TCO 和惰性评估
【发布时间】:2017-01-18 11:40:19
【问题描述】:

我试图理解为什么当c 无效时第一个main 不终止,而第二个终止。来自描述here main 只是一个未评估的 thunk,executing 它只是在构建数据结构。我试图在这里应用相同的原则,看看为什么第一个 main 不会终止。如果有人可以帮助我理解这部分,或者给我指点来理解这将是很棒的。除此之外,为什么 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

谢谢。

【问题讨论】:

  • 您意识到return 只是一个库函数,其工作方式与过程语言中的return 关键字完全不同?
  • @leftaroundabout :意识到关于这个的“某些东西”是不正确的,因为我正在点击“POST”,然后立即看到了这个评论。谢谢。
  • 除了接受答案之外,没有办法“关闭”问题吗?如果是这样,我需要等待一段时间才能接受答案。将阅读 stackoverflow 文档。现在,要接受,我还要再等 7 分钟 :-)。
  • @user3169543 不急于接受答案。支持您认为有用的答案,然后回来,说明天,并接受您认为最好的答案。尽早接受意味着您不太可能收到非常好的答案,因为回答者可能对问题失去兴趣,而且通常第一个答案可能不像以下答案那样正确(或不正确)或不完整(或不完整)。

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


【解决方案1】:

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

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

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() 的调用是inside分支else,而在前一种情况下,它是outside,因此在每个@987654325 处调用@ 调用。

还要注意,Haskell 中的 return 确实终止函数调用。只是一个IO动作,有一定的价值,没有副作用。

例如:

main = do
    c <- return 1
    print c

在上面的代码中,return 确实阻止print 的输出。

【讨论】:

    猜你喜欢
    • 2014-02-08
    • 2018-11-11
    • 1970-01-01
    • 2013-03-11
    • 1970-01-01
    • 2015-05-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多