使用跟踪函数在Haskell的do表示法中进行惰性评估 [英] Lazy evaluation in Haskell's do notation using the trace function

查看:43
本文介绍了使用跟踪函数在Haskell的do表示法中进行惰性评估的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道为什么此调试消息1"没有在此代码段中显示:

I want to know why this "debug message 1" doesn't get printed in this snippet:

import Debug.Trace

main = do
    return (trace "debug message 1" ())
    trace "debug message 2" (return ())

打印出第二个调试消息2",但不打印调试消息1".似乎两个表达式都相同.

The second "debug message 2" is printed out, but not "debug message 1". It seems that both expressions are the same.

我尝试将调试消息1"绑定到一个变量,然后在另一个地方使用该变量,实际上确实触发了评估并打印了调试消息1",但是我仍然不明白为什么会发生这种情况

I tried binding the "debug message 1" to a variable, and then using that variable in another place, it did in fact trigger the evaluation and print "debug message 1", but I still don't understand why this happens.

如果我翻转语句的顺序,结果仍然相同:

If I flip the order of the statements, it is still the same result:

import Debug.Trace

main = do
    trace "debug message 2" (return ())
    return (trace "debug message 1" ())

调试消息1"从不打印(使用runhaskell).

"debug message 1" is never printed (using runhaskell).

推荐答案

我的猜测是因为惰性评估".

My guess would be because of "lazy evaluation".

请注意,您不会返回任何东西.换句话说,尚未查询返回"(也没有返回),也没有用.在 return 语句中,您不在单子"上下文中.因此,没有理由对其进行评估,只需将调用树"作为结果传递即可.

Note that you don't return anything. In other words, the "return" is not been queried yet (well there is no return), nor is it useful. Inside the return statement, you are not in a "monadic" context. So there is no reason to evaluate it, you simply pass the "call-tree" as the result.

换句话说,它会保留在"通话树"上,直到有人要拿起它为止.

In other words, it remains on the "call-tree" until someone wants to pick it up.

在第二种情况下,调用 trace 很简单.执行monad直到到达" return "为止,并且在达到该 return 之前,将采取所有必要的操作,包括在需要时执行调试信息.

For the second case it is trivial that the trace will be called. The monad is executed until it reaches a "return", and before that return is reached, all necessary actions are taken, including executing debug info if needed.

ghci 中的示例:

Example in ghci:

$ ghci
GHCi, version 7.6.3: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude> import Debug.Trace
Prelude Debug.Trace> do return (trace "debug message 1" ())
Prelude Debug.Trace> do trace "debug message 2" (return ())
debug message 2

runhaskell 相同.如果您编写这两个程序:

Same for runhaskell. If you write these two programs:

program1.hs :

program1.hs:

import Debug.Trace

main = do return (trace "debug message 1" ())

program2.hs :

program2.hs:

import Debug.Trace

main = do
    trace "debug message 2" (return ())

然后控制台显示:

$ runhaskell program1.hs
$ runhaskell program2.hs
debug message 2
$ 

但是,如果您编写一个 IO Bool (因此具有返回值),并且以后使用该值,则将执行跟踪,例如:

If you however write an IO Bool (thus with return value) and you later use that value, the trace will be executed, for instance:

testFun :: IO Bool
testFun = do
    trace "foo" $ return $ trace "Hello" True

main :: IO ()
main = do
    b <- testFun
    print b

这将导致:

$ runhaskell program3.hs
foo
Hello
True
$ 

但是,如果您省略了 print b 并放入了 return(),那么Haskell对返回的内容将不感兴趣,因此不会打印跟踪:/p>

If you however omit the print b and put return () instead, Haskell has no interest in the what is returned and thus doesn't print the trace:

testFun :: IO Bool
testFun = do
    trace "foo" $ return $ trace "Hello" True

main :: IO ()
main = do
    b <- testFun
    return ()   --we ran `testFun` but are not interested in the result

结果是:

$ runhaskell program4.hs
foo
$ 

这篇关于使用跟踪函数在Haskell的do表示法中进行惰性评估的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆