如何使用 Haskell 中的 Maybe 对象递归迭代列表

How to recursively iterate over a list with Maybe objects in Haskell

我正在尝试创建一个函数 justifyList,它接受 Maybe 个对象 ([Maybe a]) 的列表和 return [=15] 的所有对象的列表=] 类型,丢弃参数列表中 Nothing 的任何元素。

我现在的解决方案是

justifyList :: [Maybe a] -> [a]
justifyList [] = []
justifyList (x:xs) 
    | (isNothing x) = justifyList xs
    | otherwise = x : justifyList xs

我尝试递归遍历参数列表并递归地将当前元素 x 放入 returned 列表 [a],如果它是 Just类型。

但是在解释时会产生类型不匹配错误

Couldn't match type a with Maybe a

因此我的问题是;如何递归遍历 Maybe 对象列表?如果此解决方案足够,我如何将 xs 转换为 Maybe 类型?

Pattern-match 在 Maybes

justifyList :: [Maybe a] -> [a]
justifyList [] = []
justifyList (Nothing:xs) = justifyList xs
justifyList (Just x:xs) = x : justifyList xs

在行 justifyList (x:xs) x 是类型 Maybe a 然后在行 | otherwise = x : justifyList xs 你尝试添加 x::Maybe a 到列表 a.

您需要使用模式匹配打开 Maybe 类型,以便您可以获取其中的实际值。 (我将使用显式 case 语句,因为它使逻辑更容易,但最佳做法是在函数本身中使用模式匹配 - 留作 reader 的练习)。

justifyList (x:xs) = case x of
  Nothing -> justifyList xs
  Just a  -> a:justifyList xs

作为一般规则,只有在需要进行比较或函数评估等测试时才使用保护模式 (| = ...)。当您只需要有关类型的一些信息时(这在实践中很常见),请改用模式匹配或 case 语句。


对于那些可能在搜索中找到它的人,我将添加最后一点,Data.Maybe 中有一个函数 catMaybes,它已经完成了这个操作。

此类函数已存在于 Data.Maybe module and is named catMaybes :: [Maybe a] -> [a]

你可以用递归来实现这个,但是用列表理解来做可能更优雅,因为这允许我们同时有效地进行模式匹配和解包,所以:

justifyList :: [Maybe a] -> [a]
justifyList xs = [ <strong>x</strong> | <strong>Just x</strong> <- xs ]

只有满足 Just x 模式的项目才会产生一个项目,因此 Just x <- xs 也会执行过滤。

如果列表的第一个元素是Nothing,则对递归结果应用id。如果是Just x,则对递归结果应用(x:)。使用 maybe 到 select 正确的功能。

justifyList [] = []
justifyList (x:xs) = (maybe id (:) x) (justifyList xs)
  • maybe id (:) Nothing == id
  • maybe id (:) (Just x) == (x:).