我是Haskell的新手。以前我用Python和Java编程。当我调试一些代码时,我习惯在代码中间用print
语句乱丢它。但是,在Haskell中这样做会改变语义,我将不得不将我的函数签名更改为具有IO
内容的人。 Haskellers如何处理这个问题?我可能会遗漏一些明显的东西。请指教。
答案 0 :(得分:8)
Read this。您可以使用Debug.Trace.trace
代替print语句。
答案 1 :(得分:5)
我能够创建双重个性IO
/ ST
monad类型类,当monadic计算类型为IO
时会打印调试语句,当它键入为{{{ 1}}。这里的演示和代码:Haskell -- dual personality IO / ST monad?。
当然ST
更像是一把瑞士军刀,特别是当它包裹着一个有用的特殊情况时,
Debug.Trace
可以像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
答案 2 :(得分:3)
您可以使用Debug.Trace。
答案 3 :(得分:2)
其他答案将official doco和Haskell wiki链接在一起,但是如果您已经回答了这个问题,那么就假设您出于任何原因而退缩了。 wikibook还有一个使用斐波那契的示例,我发现它更易于访问。这是一个故意的基本示例,可能会有所帮助。
假设我们从这个非常简单的函数开始,出于重要的商业原因,该函数在字符串中添加“ bob”,然后将其反转。
bobreverse x = reverse ("bob" ++ x)
GHCI中的输出:
> bobreverse "jill"
"llijbob"
我们看不到这可能是怎么回事,但是附近有问题,所以我们添加了调试。
Import Debug.Trace
bobreverse x = trace ("DEBUG: bobreverse" ++ show x) (reverse ("bob" ++ x))
输出:
> bobreverse "jill"
"DEBUG: bobreverse "jill"
llijbob"
我们使用show
只是为了确保x
在输出之前正确转换为字符串。我们还添加了一些括号以确保参数正确分组。
总而言之,trace
函数是一个装饰器,它输出第一个参数并返回第二个参数。它看起来像是一个纯函数,因此您无需将IO
或其他签名带入函数即可使用它。如果您好奇的话,它是通过作弊来实现的,以上链接的文档中对此进行了进一步的解释。
答案 4 :(得分:1)
我真的很喜欢Dons关于它的简短博客: https://donsbot.wordpress.com/2007/11/14/no-more-exceptions-debugging-haskell-code-with-ghci/
简而言之:使用ghci,例如一个程序,代码名为HsColour.hs
$ ghci HsColour.hs
*Main> :set -fbreak-on-exception
*Main> :set args "source.hs"
现在运行你的程序跟踪,GHCi将在调用错误时停止你的程序:
*Main> :trace main
Stopped at (exception thrown)
好的,好的。我们有一个例外......让我们稍微回顾一下,看看我们在哪里。现在观看我们通过我们的计划及时向后旅行,使用(奇怪,我知道)“:后退”命令:
[(exception thrown)] *Main> :back
Logged breakpoint at Language/Haskell/HsColour/Classify.hs:(19,0)-(31,46)
_result :: [String]
这告诉我们,在遇到错误之前,我们在第19行的Language / Haskell / HsColour / Classify.hs文件中。我们现在处于相当不错的状态。让我们看看到底在哪里:
[-1: Language/Haskell/HsColour/Classify.hs:(19,0)-(31,46)] *Main> :list
18 chunk :: String -> [String]
vv
19 chunk [] = head []
20 chunk ('\r':s) = chunk s -- get rid of DOS newline stuff
21 chunk ('\n':s) = "\n": chunk s
^^