【问题标题】:foldl Implementation with Runtime Errors带有运行时错误的 foldl 实现
【发布时间】:2014-04-20 23:21:05
【问题描述】:

Learn You a Haskell 解释foldl1

foldl1 和 foldr1 函数的工作方式与 foldl 和 foldr 非常相似,只是 您不需要为它们提供明确的起始值。他们 假设列表的第一个(或最后一个)元素是开始 值,然后从它旁边的元素开始折叠。 ...

因为他们依赖于他们折叠起来的列表,其中至少有一个 元素,如果使用空列表调用它们会导致运行时错误

我认为它的实现或多或少如下:

foldl1' :: (a -> a -> a) -> [a] -> a
foldl1' f ys = foldl f (head ys) (tail ys)

但是,这个潜在的运行时错误让我很困扰。

为什么不按以下方式实现foldlOption

foldlOption :: (a -> a -> a) -> [a] -> Maybe a
foldlOption f [] = Nothing
foldlOption f ys = Just (foldl f (head ys) (tail ys))

REPL

*Main> foldlOption (\acc elem -> if (elem > acc) then elem else acc) []
Nothing

-- find max
*Main> foldlOption (\acc elem -> if (elem > acc) then elem else acc) [1,100,2,3]
Just 100

已编辑

更新了foldl1foldlOption 的定义以使用tail ys 作为foldl 的最后一个参数,而不是ys 根据Lee Duhem 的更正。 .

【问题讨论】:

  • 我认为foldl1的等同定义是foldl1' f ys = foldl f (head ys) (tail ys),或者foldl1' f (y:ys) = foldl f y ys
  • 谢谢,李。我刚刚更新并列出了您的更正。

标签: haskell


【解决方案1】:

实际上没有充分的理由不这样做。 Haskell 前奏曲中的许多功能,如headtailinit,以及许多其他功能都不必要地失败。

让他们明确指出他们在类型上的失败会更好,但不幸的是,当 Prelude 标准化时并没有发生这种情况,我们不能很好地改变几个核心功能,比如head

现在我建议不要使用这些函数中的许多并选择模式匹配,或者 Gabriel Gonzalez 的 errors 库,它提供了正确失败的前奏部分函数的替代版本。

例如在Control.Error.Safe

foldl1Err :: e -> (a -> a -> a) -> [a] -> Either e a

而且errors也导出safe,一个类似Maybe的库,有这个功能

foldl1May :: (a -> a -> a) -> [a] -> Maybe a

和你想要的完全一样:)

【讨论】:

    猜你喜欢
    • 2020-01-03
    • 1970-01-01
    • 2015-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-15
    • 1970-01-01
    相关资源
    最近更新 更多