haskell - Haskell - 在自定义 atIndex 函数上处理列表超出范围时出错
问题描述
我在 1 天前开始使用 Haskell,我试图做一些例子。我遇到了一个无法解决的问题。
问题是我的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
超过arr_size
. 谢谢你的帮助!
解决方案
让我们看看这扩展成什么。
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 的惰性评估。
推荐阅读
- nginx - SageMaker TensorFlow 服务堆栈比较
- javascript - 如何在 Node.js 中通过 mailchimp-api-v3 提交表单(添加订阅者)?
- javascript - JSDoc:将类型分配给内联变量
- php - 注意警报试图获取非数组 var 的索引
- node.js - Node.js 应用程序未在 AWS Elastic Beanstalk 上运行
- javascript - 将数据推入数组 Ajax
- azure - Azure 容器实例未连接 kafka 集群
- json - 使用 mongo-go-driver 将结果转换为没有结构的 JSON
- c - 为什么 char * 和 char ** 具有相同的值?
- apostrophe-cms - 使用 apostrophe-monitor 调试带有断点的 Apostrophe CMS