我是一个Haskell新手,正在尝试一些东西。我创建了一个有保障的递归函数。请看下面的函数:
filterAge :: [Person] -> [String]
filterAge (x:xs)
| (x:xs) == [] = []
| (getAge x) < 30 || (getAge x) > 40 = [] ++ filterAge xs
| otherwise = [getName x] ++ filterAge xs
我有一个数据集,其中包括10个人,我在这个方法中使用它。当我尝试这个函数时,它返回了所有正确的人,但之后它出现了一个非全面模式错误:
["Lise","Jaap","Elle","Ebba"*** Exception: D:\...:(44,1)-(47,77): Non-exhaustive patterns in function filterAge
我发现它从未到达第一个保护程序。所以我进行了一些尝试,并发现了一些非常奇怪的事情(在我看来):
*Main> let (x:xs) = []
*Main> (x:xs) == []
False
现在我的主要问题是:为什么
(x:xs) == []
返回False?如果有更好的方法可以帮我完成这个函数,那就太棒了,但这并不是非常重要。
提前感谢!
编辑
感谢Willem Van Onsem和Lambda.xy.x,他们很快回答了我的问题。这导致了以下完美运行的函数:
filterAge :: [Person] -> [String]
filterAge [] = []
filterAge (x:xs)
| (getAge x) < 30 || (getAge x) > 40 = [] ++ filterAge xs
| otherwise = [getName x] ++ filterAge xs
但是如果你想得到最好的版本,你需要查看Willem Van Onsem的答案。
(x:xs) == []
永远不可能成功,因为(x:xs)
是至少含有一个元素的列表。 - Willem Van Onsem[]
和_ : _
,具有最外层构造函数[]
的列表永远不能将:
作为最外层构造函数。 - lambda.xy.xfilterAge (x:xs)
的定义中进行了模式匹配,并在那里排除了空列表。最简单的解决方法是在上面添加一个定义filterAge []
。或者你可以定义 filterAge xs 并在任意列表上进行匹配。 - lambda.xy.xx:xs
可以为空,在SO上已经出现了几次。我们应该选择一个规范问题(可能是这个),并将未来的出现视为重复。 - chi