foldl实现运行时错误

Kev*_*ith 6 haskell

了解一下Haskell解释说foldl1:

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

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

我认为它的实现或多或少是以下几点:

foldl1' :: (a -> a -> a) -> [a] -> a
foldl1' f ys = foldl f (head ys) (tail ys)
Run Code Online (Sandbox Code Playgroud)

但是,这种潜在的运行时错误让我很烦恼.

为什么不foldlOption以下列方式实施?

foldlOption :: (a -> a -> a) -> [a] -> Maybe a
foldlOption f [] = Nothing
foldlOption f ys = Just (foldl f (head ys) (tail ys))
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

EDITED

更新了foldl1s和用作最后一个参数foldlOption的定义,而不是根据Lee Duhem的修正..tail ysfoldlys

Dan*_*zer 12

实际上没有理由不这样做.许多在Haskell的前奏的功能,如head,tail,init,和许多其他许多不必要的失败.

对于他们明确地注意到他们在类型中的失败会更好,但不幸的是,当Prelude被标准化时我们不能很好地改变几个核心功能head!

现在我建议不要使用许多这些功能并选择模式匹配,或者加布里埃尔·冈萨雷斯的错误库,它提供了前奏部分功能的替代版本,这些功能正常失败.

例如在Control.Error.Safe那里

foldl1Err :: e -> (a -> a -> a) -> [a] -> Either e a
Run Code Online (Sandbox Code Playgroud)

和错误也导出安全,一个类似的库Maybe具有该功能

foldl1May :: (a -> a -> a) -> [a] -> Maybe a
Run Code Online (Sandbox Code Playgroud)

完全像你想要的:)