Idris `foldl` 默认实现
Idris `foldl` default implementation
interface Foldable t where
foldr : (func : elem -> acc -> acc) -> (init : acc) -> (input : t elem) -> acc
foldl : (func : acc -> elem -> acc) -> (init : acc) -> (input : t elem) -> acc
foldl f z t = foldr (flip (.) . flip f) id t z
这里的foldr (flip (.) . flip f) id t z
是什么意思?
还有另一种使用 foldr
来实现 foldl
的方法吗?
感谢您的回答。
上面定义的 foldl
中的第一个参数可以变成这样的 lambda:
\element -> (. (flip f element))
-- or
\element prevFun -> prevFun . flip f element
-- or
\element prevFun next -> prevFun $ f next element
让我们举一个例子,你想在列表中向左折叠[a, b, c]
。您希望最终结果为 f (f (f z a) b) c)
,其中 z
是累加器。
在第一次迭代中,第一个参数为 c
,第二个参数为 id
。因此,结果将是 id . flip f c
,或者只是 flip f c
(因为 id . f
只是 f
,正如@chepner 指出的那样)。
第二次迭代会得到 flip f c . flip f b
,之后你会得到 flip f c . flip f b . flip f a
(基本上,为每个下一个元素 x
添加一个 . flip f x
。
扩展为:
acc -> flip f c (flip f b (flip f a acc))
-- or
acc -> flip f c (flip f b (f acc a))
-- or
acc -> f (f (f acc a) b) c)
瞧瞧!我们有一个接受累加器 acc
和 returns foldl f acc t
结果的函数,因此我们只需将其应用于实际累加器 z
。
interface Foldable t where
foldr : (func : elem -> acc -> acc) -> (init : acc) -> (input : t elem) -> acc
foldl : (func : acc -> elem -> acc) -> (init : acc) -> (input : t elem) -> acc
foldl f z t = foldr (flip (.) . flip f) id t z
这里的foldr (flip (.) . flip f) id t z
是什么意思?
还有另一种使用 foldr
来实现 foldl
的方法吗?
感谢您的回答。
上面定义的 foldl
中的第一个参数可以变成这样的 lambda:
\element -> (. (flip f element))
-- or
\element prevFun -> prevFun . flip f element
-- or
\element prevFun next -> prevFun $ f next element
让我们举一个例子,你想在列表中向左折叠[a, b, c]
。您希望最终结果为 f (f (f z a) b) c)
,其中 z
是累加器。
在第一次迭代中,第一个参数为 c
,第二个参数为 id
。因此,结果将是 id . flip f c
,或者只是 flip f c
(因为 id . f
只是 f
,正如@chepner 指出的那样)。
第二次迭代会得到 flip f c . flip f b
,之后你会得到 flip f c . flip f b . flip f a
(基本上,为每个下一个元素 x
添加一个 . flip f x
。
扩展为:
acc -> flip f c (flip f b (flip f a acc))
-- or
acc -> flip f c (flip f b (f acc a))
-- or
acc -> f (f (f acc a) b) c)
瞧瞧!我们有一个接受累加器 acc
和 returns foldl f acc t
结果的函数,因此我们只需将其应用于实际累加器 z
。