Haskell - 在自定义atIndex函数上处理列表超出范围时出错

时间:2018-05-28 18:04:37

标签: haskell

我1天前创办了Haskell,我试图做一些例子。我遇到了一个无法修复的问题。

问题是我的 a b c 0 abc 2.001 1.001 1 abc NaN 0 2 abc 0.0 2.001 3 abc 6.001 0 比较不起作用。编程只是igrones stament并继续执行if语句。 (注释为代码注释)
代码:

else


控制台输出:

lengthOf :: Num t => [t] -> t
lengthOf []  = 0
lengthOf arr = lengthOfAcc arr 1
    where
        lengthOfAcc :: Num t => [t] -> t -> t
        lengthOfAcc (_:t) counter = 
            if null t
                then counter
            else
                lengthOfAcc t (counter + 1)

atIndex :: (Ord t, Num t) => [t] -> t -> t
atIndex [] _      = error "atIndex: Empty list passed!"
atIndex arr index =
    if index < 0
        then error "atIndex: Index cannot be smaller than 0!"
    else
        atIndexAcc arr index 0 (lengthOf arr)

    where
        atIndexAcc :: (Ord t, Eq t, Num t) => [t] -> t -> t -> t -> t
        atIndexAcc (h:t) index counter arr_size = 
            if counter == index
                then h
            else
                if counter > arr_size -- This is not working. I don't know why.
                    then error "atIndexAcc: Out of array range!"
                else
                    atIndexAcc t index (counter + 1) arr_size

如你所见。当*EB_Functions> lengthOf [5, 10, 15, 20, 25] 5 *EB_Functions> atIndex [5, 10, 15, 20, 25] 1 10 *EB_Functions> atIndex [5, 10, 15, 20, 25] 3 20 *EB_Functions> atIndex [5, 10, 15, 20, 25] 7 *** Exception: EB_Quick_F.hs:(71,9)-(78,61): Non-exhaustive patterns in function atIndexAcc 超过时,我应该怎么做才能执行该行 counter。谢谢你的帮助!

1 个答案:

答案 0 :(得分:3)

让我们看看它扩展到了什么。

atIndex [5, 10, 15, 20, 25] 7
atIndexAcc [5, 10, 15, 20, 25] 7 0 (lengthOf [5, 10, 15, 20, 25])
-- counter is strictly evaluated for both index and arr_size checks
-- arr_size is evaluated to perform counter > arr_size check
atIndexAcc [5, 10, 15, 20, 25] 7 0 5
atIndexAcc [10, 15, 20, 25] 7 1 5
atIndexAcc [15, 20, 25] 7 2 5
atIndexAcc [20, 25] 7 3 5
atIndexAcc [25] 7 4 5
atIndexAcc [] 7 5 5

当它停止时 - 因为[](h:t)不匹配,你会得到非详尽的模式。您需要一个可以接受空列表的atIndexAcc版本。请注意,您比较了counter > arr_size,这也是不可能发生的,因为您在计算时遍历列表;只有在列表用完时它们才相等。

此外,获取列表的长度意味着遍历整个列表;这不是索引它的必要条件,并且会强制整个列表存在于内存中。这不适用于无限列表,这可能是由于Haskell的惰性评估所致。