带有运行时错误的 foldl 实现 [英] foldl Implementation with Runtime Errors
问题描述
向你学习 Haskell 解释了 foldl1
:
foldl1 和 foldr1 函数的工作方式很像 foldl 和 foldr,只是您不需要为它们提供明确的起始值.他们假设列表的第一个(或最后一个)元素是起始元素值,然后从它旁边的元素开始折叠....
The foldl1 and foldr1 functions work much like foldl and foldr, only you don't need to provide them with an explicit starting value. They assume the first (or last) element of the list to be the starting value and then start the fold with the element next to it. ...
因为它们依赖于它们折叠起来的列表中至少有一个元素,如果使用空列表调用它们会导致运行时错误
Because they depend on the lists they fold up having at least one element, they cause runtime errors if called with empty lists
我认为它的实现或多或少如下:
I figured its implementation is, more or less, the following:
foldl1' :: (a -> a -> a) -> [a] -> a
foldl1' f ys = foldl f (head ys) (tail ys)
但是,这个潜在的运行时错误困扰着我.
But, this potential run-time error troubles me.
为什么不以如下方式实现foldlOption
?
Why not implement foldlOption
in the following way?
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
已编辑
更新了 foldl1
和 foldlOption
的定义以使用 tail ys
作为 foldl
的最后一个参数,而不是 ys
根据 Lee Duhem 的更正..
Updated foldl1
's and foldlOption
's definitions to use tail ys
as the last argument to foldl
, not ys
per Lee Duhem's correction. .
推荐答案
实际上没有充分的理由不这样做.Haskell 前奏中的许多函数,如 head
、tail
、init
和许多其他函数都不必要地失败.
There's actually no good reason why not to do this. Many of the functions in Haskell's prelude like head
, tail
, init
, and many many others fail unnecessarily.
让他们明确指出他们在类型中的失败会好得多,但不幸的是,当 Prelude 被标准化时,这不是发生的事情,我们不能很好地改变几个核心函数,比如 head
!
It would be much nicer for them to explicitly note their failure in the types, but that's unfortunately just not what happened when Prelude was standardized and we can't very well change several core functions like head
!
现在我建议不要使用这些函数中的许多函数并选择模式匹配,或者 Gabriel Gonzalez 的 errors 库,它提供Prelude 的部分功能的替代版本,这些功能正常失败.
Nowadays I recommend simply not using many of these functions and opting for pattern matching, or Gabriel Gonzalez's errors library which provides alternate versions of prelude's partial functions which fail properly.
例如在Control.Error.Safe
中有
foldl1Err :: e -> (a -> a -> a) -> [a] -> Either e a
和错误也导出安全,一个类似的库,带有 Maybe
的功能
and errors also exports safe, a similar library with Maybe
's which has the function
foldl1May :: (a -> a -> a) -> [a] -> Maybe a
完全像你想要的:)
这篇关于带有运行时错误的 foldl 实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!