跟踪Haskell中的错误

跟踪Haskell中的错误,haskell,Haskell,如何获得有关Haskell错误发生位置的更多信息?例如,昨天我正在编写一个Haskell程序,该程序解析输入文件,转换数据,然后打印报告信息 有一次,我跑了“main”又回来了 *** Prelude.read: parse error 没有其他信息。幸运的是,我知道我只在一个地方调用了read,并且能够修复它,但为了将来: 有没有可能为这些错误获取回溯或行号 是否可以获取触发错误的实际数据,即导致分析错误的字符串 谢谢 使用GHC编辑。您没有告诉我们您正在使用哪个编译器。如果您使用,那么

如何获得有关Haskell错误发生位置的更多信息?例如,昨天我正在编写一个Haskell程序,该程序解析输入文件,转换数据,然后打印报告信息

有一次,我跑了“main”又回来了

*** Prelude.read: parse error
没有其他信息。幸运的是,我知道我只在一个地方调用了read,并且能够修复它,但为了将来:

  • 有没有可能为这些错误获取回溯或行号
  • 是否可以获取触发错误的实际数据,即导致分析错误的字符串
谢谢


使用GHC编辑

您没有告诉我们您正在使用哪个编译器。如果您使用,那么您应该看看


Haskell中的堆栈跟踪并不简单,因为它是惰性的。尽管如此,前面提到的调试器提供了一些工具(请参见上面URL中的2.5.5节跟踪和历史)。

一般来说,处理错误的方式取决于您是否有足够的上下文来调试原因

Haskell的懒散性使得堆栈跟踪难以实现,因为在错误发生时调用堆栈可能不再存在

一种简单的错误处理方法是使用任意一种类型,允许您在事情正常时返回值,或者在发生错误时使用某个上下文(错误消息、输入字符串…)


最后,在您的具体案例<代码> Read 中抛出一个异常,以便您必须捕获该代码,然后处理调用代码中的错误(请看<代码>控件>异常< /代码>包)。 第一步是将

read
替换为提升为通用错误monad的版本,
MonadError

readM :: (MonadError String m, Read a) => String -> m a
readM s | [x] <- parse = return x
        | otherwise    = throwError $ "Failed parse: " ++ show s
    where
        parse = [x | (x,t) <- reads s]
readM::(MonadError字符串m,reada)=>String->ma

readM s |[x]您可以通过导入和更改导致分析错误的字符串 你的电话

import Debug.Trace (trace) --change myRead s = read s --to myRead s = trace s (read s) --or myRead s = trace (take 100 s) (read s) 导入Debug.Trace(跟踪) --改变 myRead s=读取s --到 myRead s=跟踪s(读取s) --或 myRead s=跟踪(取100秒)(读取秒)
如果您可以在ghci中运行代码,那么调试器可以执行您想要的任何操作。下面是一个引发异常的程序

foo s i
  | i == 57 = read s
  | otherwise = i
main = mapM_ (print . foo "") [1..100]
现在将其加载到ghci并使用调试器,如下所述:

这有点困难的原因在调试器页面的前面介绍过
基本上,高效的Haskell执行不会使用任何类似于普通调用堆栈的东西,因此要获取有关异常的此类信息,您必须以某种特殊模式(调试或分析)运行,这种模式会保留此类信息。

我发现
\s->fst$head$reads s s++[error$”无法读取:“++show s]
更有用,因为当读取成功时它不会发出垃圾邮件。您最好完全避免使用部分函数。请改用
Safe.readMay
。有关更好的解决方案,请参阅
> ghci test.hs
*Main> :set -fbreak-on-error
*Main> :trace main
1
2
... snipped 3 through 55 ...
56
Stopped at <exception thrown>
_exception :: e = _
[<exception thrown>] *Main> :back
Logged breakpoint at test.hs:2:15-20
_result :: a
s :: String
[-1: test.hs:2:15-20] *Main> :list
1  foo s i
2    | i == 57 = **read s**
3    | otherwise = i
[-1: test.hs:2:15-20] *Main> s
""
[-1: test.hs:2:15-20] *Main> 
> ghc -prof -auto-all test.hs
> ./test +RTS -cs
1
2
... snipped 3 through 55 ...
56
*** Exception (reporting due to +RTS -xc): (THUNK_2_0), stack trace: 
  Main.foo,
  called from Main.main,
  called from Main.CAF
  --> evaluated by: Main.main,
  called from Main.CAF
test: Prelude.read: no parse