在下面的代码中,我无法理解累加器参数是如何发送的。
meanFold :: [Double] -> Double
meanFold l = (foldr op unit l) 0 0
where
unit :: Double -> Double -> Double
unit n sum = sum / n
op :: Double -> (Double ->Double ->Double) -> (Double -> Double -> Double)
(x `op` y ) n sum = y (n+1) (sum +x)
我知道 foldr 将首先对列表 l 中的最后一个元素和我选择的单位(即函数 "unit")应用运算符 op
。
但是 meanFold 的累加器参数是如何传递给 unit 函数的,使得 sum 和 n 初始为 0?
最佳答案
I understand that foldr will firstly apply the operator op for the last element in the list
我也不完全确定你是否理解这一点。首先让我们看一下 foldr
的类型(专门用于列表)及其定义。
foldr :: (a -> b -> b) -> b -> [a] -> b
foldr f e [] = e
foldr f e (x:xs) = f x (foldr f xs)
在这种情况下,a
是 Double
,而 b
是 Double -> Double -> Double
。前者你知道它是 Double
因为你正在折叠一个 double 列表。后者是 unit
的类型,也就是你在空的情况下返回的。
所以你的 foldr
正在做的是从 double 列表中计算 Double -> Double -> Double
类型的函数。在空的情况下,您只需返回函数,
unit n sum = sum / n
这是将其第二个参数除以第一个参数的函数。那是 (/) 但它的参数交换了。在折叠的每个步骤中,您使用列表的元素修改该二进制函数。你通过 op
op :: Double -> (Double ->Double ->Double) -> (Double -> Double -> Double)
(x `op` y ) n sum = y (n+1) (sum +x)
我真的不喜欢那里的字母 y
,因为它使它看起来像 double 。让我们将其重写为 h
。并且让我们对 n
和 sum
进行抽象,使用 lambda 更容易理解正在发生的事情。
op :: Double -> (Double ->Double ->Double) -> (Double -> Double -> Double)
(x `op` h) = \n sum -> h (n+1) (sum +x)
因此,给定列表中的 double 值 x
,以及到目前为止计算的二进制函数 h
(最初是 unit
),我们是计算一个新函数,
\n sum -> h (n+1) (sum+x)
与前面的函数 h
类似,不同之处在于它在应用 之前将
。 1
与第一个参数相加,将 x
与第二个参数相加h
所以最后对于一个列表 [x1, x2, x3]
那个 fold 会返回函数,
\n sum -> (x1+x2+x3+sum) / (1+1+1+n)
当你把它应用到你得到的两个零上时,
(\n sum -> (x1+x2+x3+sum) / (1+1+1+n)) 0 0
= (x1+x2+x3+0) / (1+1+1+0)
= (x1+x2+x3) / (1+1+1)
关于haskell - 累加器参数如何发送给函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53452943/