3

我无法在我的代码中弄清楚什么函数正在引发(*** Exception: Prelude.!!: negative index,因为这个异常对错误的描述不是很清楚。有什么方法可以准确地检测到自定义函数正在调用什么!!并引发此错误。

这是调用时错误的简单可重现示例index_around 0 [1, 2, 3],此处的异常文本未描述异常是由函数引发index_before还是由index_after函数引发。

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)
4

2 回答 2

5

有几种方法可以用来调试 haskell 代码:

  • 使用Debug.Tracewhich 将消息记录到stderr您使用该trace功能的任何位置。它需要修改您的代码,并且由于trace它是一个不纯的函数(IO使用隐藏unsafePerformIO),因此您应该谨慎使用它。
  • 在使用 编译后使用标志,它会在引发异常时为您提供确切的调用堆栈。-xc RTS-prof -fprof-auto
  • 使用GHCi调试器。如何使用它的一个很好的例子可以在这里找到。
于 2022-02-04T16:54:20.670 回答
1

当你打电话时index_around 0 [1, 2, 3],你在打电话index_before (-1) [1, 2, 3]index_after 1 [1, 2, 3]

-1是负指数。

您可能希望进行一些边界检查,并使用该Maybe类型。这样异常永远不会发生。

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
于 2022-02-04T16:35:00.483 回答