Haskell中如何正确处理自定义数据类型的列表?
正确实现
areAllAdults的方式 你的代码存在两个问题:
- 模式匹配语法错误:你把列表头的
(Human name age)和尾xs直接拆分写在函数名后,正确写法应该将整个列表模式((Human name age):xs)作为函数参数,用括号包裹完整。 - 缺少递归终止条件:递归处理列表必须覆盖空列表场景,空列表中没有未成年人,应返回
True。
方式一:递归实现
areAllAdults :: [Human] -> Bool -- 空列表的终止条件 areAllAdults [] = True -- 匹配非空列表,取出第一个Human的年龄判断,再递归处理剩余列表 areAllAdults ((Human _ age):xs) = age > 21 && areAllAdults xs
这里用_代替name,因为我们不需要用到名字,通配符可以避免未使用变量的警告。
方式二:用高阶函数all简化实现
Haskell的all函数可以直接判断列表中所有元素是否满足指定条件,写法更简洁:
areAllAdults :: [Human] -> Bool areAllAdults humans = all (\(Human _ age) -> age > 21) humans -- 也可以用点风格进一步简化: -- areAllAdults = all (\(Human _ age) -> age > 21)
如果后续需要对Human做排序、比较等操作,还可以为其实现Ord类型类(比如按年龄或名字排序),就像你示例中quicksort用到的Ord a约束那样:
-- 按年龄排序的Ord实例 instance Ord Human where compare (Human _ age1) (Human _ age2) = compare age1 age2
内容的提问来源于stack exchange,提问作者Sven
相关产品推荐
相关产品推荐

