haskell - 为什么我会收到有关空列表的错误?
问题描述
我做了这些功能:
-- Looks up in dict and returns Maybe key
myLookUp :: [(String, [String])] -> String -> String
myLookUp [] val = []
myLookUp ((k, vs):ds) val
| val `elem` snd (myLast ds) = myCensor val
| val `elem` vs = k
| otherwise = myLookUp ds val
-- Given a dict of tuples of strings and list of strings,
-- should return the last tuple in dict
myLast :: [(String, [String])] -> (String, [String])
myLast [] = error "Empty list"
myLast [x] = x
myLast (x:xs) = myLast xs
哪个可以编译,但是当我尝试对其进行测试时,我收到一条错误消息
ghci> myLookUp [("strength", ["ignorance"]), ("bla", ["blabla", "blabla"])] "aa"
*** Exception: Empty list
CallStack (from HasCallStack):
error, called at test.hs:103:13 in main:Main
如果我尝试删除我的基本情况myLast [] = error "Empty list"
,我会收到此错误:
myLookUp [("strength", ["ignorance"]), ("bla", ["blabla", "blabla"])] "aa"
*** Exception: test.hs:(104,1)-(105,25):
Non-exhaustive patterns in function myLast
我认为这很myLast
有效,因为我得到了这个输出:
myLast [("strength", ["ignorance"]), ("bla", ["blabla", "blabla"])]
("bla",["blabla","blabla"])
而且我认为我可以snd
在元组上使用来获取列表元素,但是由于我得到了这个错误,我不确定我做错了什么。
解决方案
试着更仔细地思考你正在尝试做的事情。此处出现空列表异常的原因是您尝试向 myLast 传递一个可能为空的列表(并且在最后一次迭代时为空)。当输入列表 (ds) 中只剩下一个元素时,您无需检查守卫。您可以通过添加:
| null ds = []
或者检查函数模式中的单个元素。此外,myLast 函数与内置的前奏函数“last”相同,因此可以替换它。还要记住你对 ds 进行空检查的位置,它必须在你尝试使用 ds 之前,但在你第一次检查之后:
myLookUp :: [(String, [String])] -> String -> String
myLookUp [] val = []
myLookUp ((k, vs):ds) val
| val `elem` vs = k
| null ds = []
| val `elem` snd (last ds) = myCensor val
| otherwise = myLookUp ds val
解决这个问题的一个更好的方法是每次迭代只检查头部的元素,在每次迭代中检查最后一个元素是非常低效的,当你只需要做一次,它会在无论如何,递归循环的最后一次迭代。
推荐阅读
- javascript - 将两个值从下拉菜单传递给角度服务
- javascript - Firebase 通过 REST 使用变量写入数据
- firebase - 使用规则保护 Firestore 数据库。检查身份验证。够了吗?
- python - 将 dropout 层提高准确性
- javascript - 在 AJAX 调用后使用 django 变量填充下拉列表
- ios - 为每个视图 iOS 创建单独的视图控制器?
- javascript - 重写下划线_.uniq
- reactjs - Ionic React - 预填充表单元素
- angular - 带有参数的 NgRx 选择器未通过单元测试
- arrays - 循环遍历 C 中的字符数组以空格结尾