【问题标题】:Cut out Nothing with foldl用 foldl 剪掉任何东西
【发布时间】:2017-11-16 12:38:16
【问题描述】:

我有一个列表 [Maybe a],我想用一个使用 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)

我的错误在哪里?

【问题讨论】:

  • 你为什么要把(x:xs)写成help (x:xs)。
  • 出了什么问题?这能编译吗?你能给出示例输入的示例输出吗?
  • 你确定你的作业没有写“foldl 或foldr”吗? foldl 在这里基本上是错误的方法。使用它自然会颠倒列表。
  • 我写 (x:xs) 是因为这是我收集所有 Just 元素的列表。
  • @Bice: 但(x:xs) 并不将项目限制为列表(类型签名已经这样做了)。它将事物限制为具有至少一个元素的列表。

标签: list haskell functional-programming maybe


【解决方案1】:

通过编写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。但是现在函数的类型不再起作用,因为foldr 中的help 函数将累加器作为第二个参数。所以我们可以翻转参数:

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:)

我们还可以使用另一个变态: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 中使用了一个 catamorphorhism,所以 catamorphception。

【讨论】:

  • 你可以更进一步,使用maybe定义助手:foldr (maybe id (:)) []。
  • @chepner:谢谢。现在我们构造了 catamorphception :)
猜你喜欢
  • 2022-01-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多