我有一个列表[也许是]我想用一个使用foldl的函数剪掉Nothing元素 例如cut [Just 2,Just 10,Nothing,Just 5] - > [2,10,5]
I wrote:
cut :: [Maybe a] -> [a]
cut a = foldl (help) [] a
where help (x:xs) Nothing = (x:xs)
help (x:xs) Just a = a:(x:xs)
我的错误在哪里?
答案 0 :(得分:3)
通过编写help (x:xs) Nothing = (x:xs)
,您使用了模式(x:xs)
,这意味着您希望累加器是至少一个元素的列表。但情况并非总是如此,例如初始累加器[]
是空列表。
我们可以简单地使用变量l
,而不是模式:
cut :: [Maybe a] -> [a]
cut a = foldl help [] a
where help l Nothing = l
help l (Just a) = a:l
请注意,您还需要为带参数的构造函数添加括号。
但是这不会解决整个模式,现在你将颠倒列表。这是因为foldl
从左到右遍历列表,因此在迭代列表时会预先添加值。我们可以使用foldr
代替。但是现在函数的类型不再有效,因为help
中的foldr
函数将累加器作为第二个参数。所以我们可以翻转一下这些论点:
cut :: [Maybe a] -> [a]
cut a = foldr help [] a
where help Nothing l = l
help (Just a) l = a:l
现在它有效。但是我们可以稍微清理一下代码。例如,在cut
函数上使用 eta -reduction:我们可以删除函数头部和主体中的a
:
cut :: [Maybe a] -> [a]
cut = foldr help []
where help Nothing l = l
help (Just a) l = a:l
并且因为help
中的第二个参数可以被移除并且正文转换为函数:
cut :: [Maybe a] -> [a]
cut = foldr help []
where help Nothing = id
help (Just a) = (a:)
我们还可以使用另一个catamorphism:foldr
是列表的变形,maybe
是Maybe
的变形,所以我们可以写一个:
maybe <value-in-case-of-nothing> <function-just-value> <Maybe value>
因此我们可以将help
重写为:
import Data.Maybe(maybe)
cut :: [Maybe a] -> [a]
cut = foldr help []
where help = maybe id (:)
或者只是将其作为foldr
:
import Data.Maybe(maybe)
cut :: [Maybe a] -> [a]
cut = foldr (maybe id (:)) []
所以现在我们在 catamorphism 中使用了 catamporhism ,所以 catamorphception 。