deh*_*ehq 8 haskell fold function-composition
所以,我真的在煎我的大脑,试着理解foldl.foldr的成分.这是一个例子:
(foldl.foldr) (+) 1 [[1,2,3],[4,5,6]]
Run Code Online (Sandbox Code Playgroud)
结果是22,但这里到底发生了什么?
对我来说,这就是发生的事情:foldl (+) 1 [6,15].我的疑问与该foldr部分有关.它不应该将1添加到所有子列表中吗?像这样:foldr (+) 1 [1,2,3].在我脑海中,1只添加了一次,是不是?(可能不是,但我想知道如何/为什么!).
我很困惑(也许让所有的困惑,哈哈).谢谢!
Dan*_*her 14
(foldl.foldr) (+) 1 [[1,2,3],[4,5,6]]
Run Code Online (Sandbox Code Playgroud)
变
foldl (foldr (+)) 1 [[1,2,3],[4,5,6]]
Run Code Online (Sandbox Code Playgroud)
所以你得到了
foldl (foldr (+)) (foldr (+) 1 [1,2,3]) [[4,5,6]]
Run Code Online (Sandbox Code Playgroud)
在第一步之后foldl,或
foldl (foldr (+)) 7 [[4,5,6]]
Run Code Online (Sandbox Code Playgroud)
如果我们评估应用foldr(除非严格性分析器启动,它实际上仍然是一个未评估的thunk,直到foldl遍历整个列表,但下一个表达式更具可读性,并评估)
foldl (foldr (+)) (foldr (+) 7 [4,5,6]) []
Run Code Online (Sandbox Code Playgroud)
最后
foldl (foldr (+)) 22 []
~> 22
Run Code Online (Sandbox Code Playgroud)
Pet*_*lák 13
我们来看看foldl . foldr.他们的类型是
foldl :: (a -> b -> a) -> (a -> [b] -> a)
foldr :: (c -> d -> d) -> (d -> [c] -> d)
Run Code Online (Sandbox Code Playgroud)
我有意使用不同类型变量和I加入括号以致变得更加明显,我们现在视其为一个参数的函数(并且它们的结果的函数).纵观foldl我们看到它是一种升降功能的:鉴于生产函数a的a使用b,我们抬起它,使其工作在[b](重复计算).功能foldr类似,只是反转的参数.
如果我们申请会发生什么foldl . foldr?首先,让我们派生出类型:我们必须统一类型变量,以便foldr匹配参数的结果foldl.所以我们必须替换a = d, b = [c]:
foldl :: (d -> [c] -> d) -> (d -> [[c]] -> d)
foldr :: (c -> d -> d) -> (d -> [c] -> d)
Run Code Online (Sandbox Code Playgroud)
所以我们得到了
foldl . foldr :: (c -> d -> d) -> (d -> [[c]] -> d)
Run Code Online (Sandbox Code Playgroud)
它的含义是什么?首先,foldr提升类型的参数c -> d -> d以在列表上工作,并反转其参数以便我们得到d -> [c] -> d.接下来,foldl再次提升此功能以进行处理[[c]]- 列表[c].
在您的情况下,提升的操作(+)是关联的,因此我们不关心其应用程序的顺序.双提升只是创建一个在所有嵌套元素上应用操作的函数.
如果我们只使用foldl,效果更好:我们可以提升多次,比如
foldl . foldl . foldl . foldl
:: (a -> b -> a) -> (a -> [[[[b]]]] -> a)
Run Code Online (Sandbox Code Playgroud)