Haskell-如何在函数中打印某些值以进行调试?

时间:2018-11-23 05:34:04

标签: haskell

我是Haskell新手,我想做一些有副作用的事情:

i = 3.0

main :: IO ()
main = let m = print i in putStrLn "Hello world"

然后我知道i运行时main的值,但是I没有打印。我在!之前添加了m,但是它也不起作用。我想知道如何破解这个,谢谢!!

3 个答案:

答案 0 :(得分:4)

要进行调试,请使用trace和朋友。

import Debug.Trace
i = 3.0

main :: IO ()
main = traceShow i $ putStrLn "Hello world"

See it live

请注意,跟踪显示在标准 error 流中,就像调试输出一样。

您使用的trace函数不必是IO类型的。例如,这也将起作用:

add a b = a + traceShow i b

跟踪功能对于Haskell有点陌生,因为它们在技术上不纯。但是,副作用的范围是有限的,并且程序本身无法观察到,因此还可以。

More info

答案 1 :(得分:3)

您创建了m,但从未使用过。要解决该问题,您可以尝试:

i = 3.0

main :: IO ()
main = let m = print i in m >> putStrLn "Hello world"

答案 2 :(得分:3)

IO操作中,您可以像平常一样仅使用putStrLnprint,例如

do
  print i
  putStrLn "Hello world"

print i >> putStrLn "…"不满意。这是等效的,但实际上并没有更好,因为实际上不需要命名操作m

let m = print i  -- define an action
in do
  m  -- ensure the action is actually executed
  putStrLn "Hello world"

在纯函数中,可以使用trace中的traceShowDebug.Trace

traceShow i (putStrLn "Hello world")

但是请注意,这些表达式会在表达式受强制时打印,由于懒惰的求值结果,其顺序可能与您期望的顺序不同,或者,如果从不使用值,则根本不会打印。您可以在尝试单子代码时使用seqBangPatterns添加严格性注释,以帮助确保在您期望的情况下强制执行操作– !m = …对您的工作不起作用的原因IO动作是严格注解仅使表达式 evaluated ,产生IO动作,但不 execute 动作,因为它没有与其他动作进行排序作为main的一部分。请记住:您只能(完全)构造 IO动作并将其绑定在一起。运行时才是真正执行它们的地方。

最后,在没有IO可用的“纯”单子目录中,您仍然可以使用trace&c。,例如在monad列表中:

numbers :: [Int]
numbers = do
  x <- [1, 2, 3]
  traceShow x (pure ())
  y <- [4, 5, 6]
  traceShow y (pure ())
  pure (x * y)