foldl没有任何东西

时间:2017-11-16 12:38:16

标签: list haskell functional-programming maybe

我有一个列表[也许是]我想用一个使用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)

我的错误在哪里?

1 个答案:

答案 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是列表的变形,maybeMaybe的变形,所以我们可以写一个:

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