在Haskell中进行简单的调试

时间:2011-08-31 06:24:28

标签: debugging haskell

我是Haskell的新手。以前我用Python和Java编程。当我调试一些代码时,我习惯在代码中间用print语句乱丢它。但是,在Haskell中这样做会改变语义,我将不得不将我的函数签名更改为具有IO内容的人。 Haskellers如何处理这个问题?我可能会遗漏一些明显的东西。请指教。

5 个答案:

答案 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 docoHaskell 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
                                       ^^