我的猜测是因为“懒惰的评估”。
请注意,您不会返回任何内容。换句话说,“return”还没有被查询(当然没有return),也没有用。在return 语句中,您不在“单子”上下文中。所以没有理由评估它,你只需传递“调用树”作为结果。
换句话说,它一直在“call-tree”上,直到有人想要拿起它。
对于第二种情况,trace 将被调用是微不足道的。 monad 一直执行,直到它到达“return”,在到达 return 之前,会执行所有必要的操作,包括在需要时执行调试信息。
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 也是如此。如果你写这两个程序:
program1.hs:
import Debug.Trace
main = do return (trace "debug message 1" ())
program2.hs:
import Debug.Trace
main = do
trace "debug message 2" (return ())
然后控制台显示:
$ runhaskell program1.hs
$ runhaskell program2.hs
debug message 2
$
但是,如果您编写了 IO Bool(因此带有返回值)并且您稍后使用该值,则将执行跟踪,例如:
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 对返回的内容不感兴趣,因此不会打印跟踪:
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
$