我有一个列表 [也许是一个],我想在其中使用使用 Foldl 的函数剪切 Nothing 元素 例如剪切 [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)
我的错误在哪里?
最佳答案
通过编写 help (x:xs) Nothing = (x:xs)
您已经使用了模式 (x:xs)
这意味着您希望累加器是一个包含至少一个元素的列表。但情况并非总是如此,例如初始累加器 []
是空列表。
我们可以简单地使用变量l
,而不是模式:
cut :: [Maybe a] -> [a]
cut a = foldl help [] a
where help <b>l</b> Nothing = <b>l</b>
help <b>l</b> <b>(</b>Just a<b>)</b> = a:<b>l</b>
请注意,您还需要为带参数的构造函数添加括号。
但这并不能解决整个模式,现在您将颠倒列表。这是因为 foldl
从左到右迭代列表,因此您在迭代列表时会在前面添加值。我们可以使用 foldr
来代替。但现在该函数的类型不再起作用,因为 foldr
中的 help
函数将累加器作为第二个参数。所以我们可以翻转参数:
cut :: [Maybe a] -> [a]
cut a = fold<b>r</b> help [] a
where help <b>Nothing l</b> = <b>l</b>
help <b>(Just a) l</b> = a:<b>l</b>
现在可以了。不过,我们可以稍微清理一下代码。例如,在 cut
函数上使用 eta 缩减:我们可以删除函数头部和主体中的 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 = <b>id</b>
help (Just a) = <b>(a:)</b>
我们还可以使用另一种变形:foldr
是列表的变形,而maybe
是Maybe
的变形,所以我们可以写一个:
maybe <value-in-case-of-nothing> <function-just-value> <Maybe value>
因此我们可以将帮助
重写为:
<b>import Data.Maybe(maybe)</b>
cut :: [Maybe a] -> [a]
cut = foldr help []
where help = <b>maybe id (:)</b>
或者只是将其作为 foldr
的参数注入(inject):
import Data.Maybe(maybe)
cut :: [Maybe a] -> [a]
cut = foldr <b>(maybe id (:))</b> []
所以现在我们在catamporhism内使用catamporhism,所以catamorphception。
关于list - 用 Foldl 剪掉任何内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47329843/