Jac*_*aie 11 debugging haskell
我是Haskell的新手.以前我用Python和Java编程.当我调试一些代码时,我习惯用print代码中间的语句乱丢它.但是,在Haskell中这样做会改变语义,我将不得不将我的函数签名更改为具有IO东西的那些.Haskellers如何处理这个问题?我可能会遗漏一些明显的东西.请指教.
其他答案将官方 doco和Haskell wiki链接起来,但是如果您已经回答了这个答案,那么假设您出于任何原因放弃了这些答案。在维基还具有使用斐波那契,我发现更容易的例子。这是一个刻意的基本示例,可能会有所帮助。
假设我们从这个非常简单的函数开始,出于重要的业务原因,它向字符串添加“bob”,然后将其反转。
bobreverse x = reverse ("bob" ++ x)
Run Code Online (Sandbox Code Playgroud)
GHCI 中的输出:
> bobreverse "jill"
"llijbob"
Run Code Online (Sandbox Code Playgroud)
我们不知道这怎么可能会出错,但接近它的东西,所以我们添加了调试。
> bobreverse "jill"
"llijbob"
Run Code Online (Sandbox Code Playgroud)
输出:
> bobreverse "jill"
"DEBUG: bobreverse "jill"
llijbob"
Run Code Online (Sandbox Code Playgroud)
我们使用show只是为了确保x在输出之前正确转换为字符串。我们还添加了一些括号以确保参数正确分组。
总之,该trace函数是一个装饰器,它打印第一个参数并返回第二个参数。它看起来像一个纯函数,所以你不需要IO在函数中引入或其他签名来使用它。它通过作弊来做到这一点,如果您好奇的话,这在上面的链接文档中有进一步的解释。
我能够创建一个双重个性IO/ STmonad类型类,它会在输入monadic计算时打印调试语句IO,当它被输入时,它们会打印出来ST.演示和代码在这里:Haskell - 双重人格IO/ST monad?.
当然Debug.Trace更多的是瑞士军刀,特别是当用一个有用的特殊情况包裹时,
trace2 :: Show a => [Char] -> a -> a
trace2 name x = trace (name ++ ": " ++ show x) x
Run Code Online (Sandbox Code Playgroud)
可以使用像 (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' |]
Run Code Online (Sandbox Code Playgroud)
然后,在一个单独的文件[来自上面的定义],你可以写
{-# LANGUAGE TemplateHaskell #-}
tr3 x = $trace3 "hello" x
Run Code Online (Sandbox Code Playgroud)
并测试出来
> tr3 4
[MyFile.hs:2:9] hello: 4
Run Code Online (Sandbox Code Playgroud)