Haskell中实现列表特定元素访问:禁用prelude的!!函数时如何自定义?
实现Haskell的
!!函数(禁用Prelude版本) 你写的代码是无限递归——右边直接调用了!!本身,没有终止条件,肯定跑不起来。下面给两种可行的实现方式:
方式一:递归模式匹配(最基础实现)
这是最直观的方式,通过列表模式匹配一步步缩小问题规模:
(!!) :: [a] -> Int -> a [] !! _ = error "索引超出列表范围" (x:_) !! 0 = x (_:xs) !! n | n < 0 = error "负索引无效" | otherwise = xs !! (n - 1)
逻辑说明:
- 空列表无论索引是什么,直接抛出错误(和Prelude原生
!!行为一致) - 索引为0时,直接返回列表第一个元素
- 索引大于0时,递归处理剩余列表,同时将索引减1
- 单独处理负索引的非法情况,直接报错
方式二:借助Prelude的drop和head函数
如果允许使用其他Prelude函数,可以结合drop(丢弃前n个元素)和head(取列表首元素)来实现:
(!!) :: [a] -> Int -> a xs !! n | n < 0 = error "负索引无效" | null (drop n xs) = error "索引超出列表范围" | otherwise = head (drop n xs)
逻辑说明:
- 先判断索引是否为负,非法则报错
- 用
drop n xs得到丢弃前n个元素后的列表,若该列表为空,说明索引超出范围,报错 - 否则取这个新列表的首元素,就是目标位置的元素
两种实现的行为都和Prelude原生!!保持一致:索引从0开始计数,负索引或超出列表长度都会触发运行时错误。
内容的提问来源于stack exchange,提问作者KPheesh
相关产品推荐
相关产品推荐

