trace2 :: Show a => [Char] -> a -> a
trace2 name x = trace (name ++ ": " ++ show x) x
可以像(trace2 "first arg" 3) + 4一样使用
编辑
如果需要源位置,您可以将其设置得更好
{-# LANGUAGE TemplateHaskell #-}
import Language.Haskell.TH
import Language.Haskell.TH.Syntax as TH
import Debug.Trace
withLocation :: Q Exp -> Q Exp
withLocation f = do
let error = locationString =<< location
appE f error
where
locationString :: Loc -> Q Exp
locationString loc = do
litE $ stringL $ formatLoc loc
formatLoc :: Loc -> String
formatLoc loc = let file = loc_filename loc
(line, col) = loc_start loc
in concat [file, ":", show line, ":", show col]
trace3' (loc :: String) msg x =
trace2 ('[' : loc ++ "] " ++ msg) x
trace3 = withLocation [| trace3' |]
然后,在一个单独的文件中[与上面的定义不同],您可以写入
{-# LANGUAGE TemplateHaskell #-}
tr3 x = $trace3 "hello" x
6条答案
按热度按时间mbzjlibv1#
其他答案将official doco和Haskell wiki联系起来,但如果你已经找到了这个答案,让我们假设你出于某种原因拒绝了这些答案。wikibook也有一个使用斐波那契的示例,我发现它更容易理解。这是一个故意的基本示例,希望能有所帮助。
假设我们从这个非常简单的函数开始,出于重要的业务原因,它将“bob”添加到字符串,然后反转它。
GHCI中的输出:
我们看不出这怎么可能出错,但确实有问题,所以我们添加了debug。
输出:
我们使用
show
只是为了确保x
在输出之前被正确地转换为字符串,我们还添加了一些括号以确保参数被正确地分组。总之,
trace
函数是一个装饰器,它打印第一个参数并返回第二个参数。它看起来像一个纯函数,所以你不需要在函数中引入IO
或其他签名来使用它。它通过欺骗来实现这一点,如果你好奇的话,可以在上面的链接文档中进一步解释。exdqitrt2#
Read this。可以使用
Debug.Trace.trace
代替print语句。ny6fqffe3#
我能够创建一个双重人格
IO
/ST
monad类型类,它将在一元计算类型为IO
时打印调试语句,在类型为ST
时打印调试语句。Haskell -- dual personality IO / ST monad?.当然
Debug.Trace
更多的是一把瑞士军刀,特别是当用一个有用的特殊情况 Package 时,可以像
(trace2 "first arg" 3) + 4
一样使用编辑
如果需要源位置,您可以将其设置得更好
然后,在一个单独的文件中[与上面的定义不同],您可以写入
然后测试一下
xa9qqrwz4#
您可以使用Debug.Trace来实现这一点。
xoefb8l85#
我真的很喜欢唐斯关于它的短博客:https://donsbot.wordpress.com/2007/11/14/no-more-exceptions-debugging-haskell-code-with-ghci/
简而言之:使用ghci,例如一个代码名为HsColour.hs的程序
现在,在跟踪打开的情况下运行程序,GHCi将在调用error时停止程序:
好的,很好。我们遇到了一个例外......让我们稍微后退一点,看看我们现在在程序中使用(我知道这很奇怪)“:back”命令进行时间回溯:
这告诉我们,在遇到error之前,我们在第19行的Language/Haskell/HsColour/Classify.hs文件中。现在我们的状态很好。让我们看看具体位置:
f87krz0w6#
这可能是对这个问题的一个非正统的回答,但是,让我简单地说:
我有一个习惯,就是在代码中间乱放print语句。
这是一个非常不好的习惯,很多编程学生在学习如何进行心理代码演练时养成了这个习惯(当然我自己也养成了这个习惯)。这个习惯留在学生身上,而且很难把它弄出来。为了确保代码的正确性并使您能够了解正在发生的事情。
你不应该在你的代码中乱放print语句。在任何编程语言中。你应该写测试,而不是乱放print语句。在Haskell的例子中,你应该学习写doctest,或者unit tests with hspec。使用测试来帮助你理解什么可行,什么不可行,写测试来确保你的函数的正确性。
要理解Haskell代码,请使用
GHCI
。使用交互式解释器来玩函数。加载您正在使用的模块,并使用GHCI交互式地“检查它”。当然,在某些情况下,调试**是必须的。所有其他优秀的答案会给予你一些关于如何在Haskell中进行调试的见解。但是,在Haskell中调试是一个苛刻的情妇,根据我个人的经验,最好避免。除非你真的,真的需要这样做。