简体   繁体   English

检测什么 function 引发异常 Prelude.:!: 负索引

[英]Detect what function is raising the exception Prelude.!!: negative index

I could not figure out in my code what exception is raising (*** Exception: Prelude.:!: negative index since this exception is not very descriptive about the error. Is there any way to detect exactly what custom function is calling !! and raising this error.我无法在我的代码中弄清楚引发了什么异常(*** Exception: Prelude.:!: negative index ,因为这个异常对错误的描述不是很好。有什么方法可以准确检测自定义 function 正在调用什么!!并引发此错误。

This is a simple reproducible example of the error when is called index_around 0 [1, 2, 3] , here the exception text doesn't describe if the exception is raised by index_before or by index_after function.这是调用index_around 0 [1, 2, 3]时错误的简单可重现示例,此处的异常文本未描述异常是由index_before还是由index_after function 引发的。

index_before :: Int -> [a] -> a
index_before i list = list !! (i - 1)

index_after :: Int -> [a] -> a
index_after i list = list !! (i + 1)

index_around :: Int -> [a] -> (a, a)
index_around i list = (index_before i list, index_after i list)

There are a few methods you can use to debug haskell code:您可以使用几种方法来调试 haskell 代码:

  • Using Debug.Trace which logs messages to stderr wherever you use the trace function.无论您在何处使用trace function,都使用Debug.Trace将消息记录到stderr It requires modification of your code, and since trace is an impure function (which hides IO using unsafePerformIO ), you should use it with caution.它需要修改您的代码,并且由于trace是不纯的 function (使用unsafePerformIO IO ,您应该谨慎使用它。
  • Using the -xc RTS flag after compiling with -prof -fprof-auto , which gives you the exact call stack when an exception is raised.在使用-prof -fprof-auto编译后使用-xc RTS标志,这会在引发异常时为您提供准确的调用堆栈。
  • Using the GHCi debugger .使用GHCi调试器 A good example of how to use it can be found here .如何使用它的一个很好的例子可以在这里找到。

When you call index_around 0 [1, 2, 3] , you're calling index_before (-1) [1, 2, 3] and index_after 1 [1, 2, 3] .当您调用index_around 0 [1, 2, 3]时,您正在调用index_before (-1) [1, 2, 3]index_after 1 [1, 2, 3]

-1 is a negative index. -1是负指数。

You may wish to do some bounds checking, and employ the Maybe type.您可能希望进行一些边界检查,并使用Maybe类型。 This way the exception never happens.这样异常永远不会发生。

index_around :: Int -> [a] -> (Maybe a, Maybe a)
index_around n lst 
    | length lst == 0 = (Nothing, Nothing)
    | n == 0          = (Nothing, Just $ index_after n lst)
    | n == length lst = (Just $ index_before n lst, Nothing)
    | otherwise       = (Just ib, Just ia) 
          where ib = index_before n lst
                ia = index_after n lst

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM