简体   繁体   English

根据foldr定义foldl

[英]Defining foldl in terms of foldr

myFoldl :: (a -> b -> a) -> a -> [b] -> a

myFoldl f z xs = foldr step id xs z
    where step x g a = g (f a x)

I am currently reading a book on Haskell. 我正在读一本关于Haskell的书。 And in it, it wrote its own version of the foldl function, but in terms of foldr. 在其中,它编写了自己的foldl函数版本,但就foldr而言。 I do not follow. 我不跟随。

  1. Why are there 4 arguments for foldr? 为什么有4个foldr参数?
  2. What does the id function do? id函数有什么作用?

The thing will be become obvious when to expand the expression of foldr step id xs z : 当扩展foldr step id xs z的表达式时,事情将变得明显:

As Adam Smith said in the comments: 正如亚当·斯密在评论中所说:

foldr step id xs z = (foldr step id xs) z foldr step id xs z =(foldr step id xs)z

Consider foldr step id xs firstly 首先考虑foldr step id xs

foldr step id xs
= x1 `step` (foldr step id xs1)
= x1 `step` (x2 `step` (foldr step id xs2))
...
= x1 `step` (x2 `step` ... (xn `step` (foldr step id []))...)
= x1 `step` (x2 `step` ... (xn `step` id)...)

where 哪里

xs = (x1:xs1)
xs1 = (x2:xs2), xs = (x1:x2:xs2) 
....
xsn = (xn:[]), xs = (x1:x2...xsn) respectively 

Now, apply above function with argument z, ie 现在,将上面的函数应用于参数z,即

(x1 `step` (x2 `step` ... (xn `step` id)...)) z

and let 然后让

g = (x2 `step` ... (xn `step` id)...) 

gives

(x1 `step` g) z

ie

(step x1 g) z

and now apply the where part of foldl: 现在应用foldl的where部分:

where step xga = g (fax) 其中步骤xga = g(传真)

gives

(step x1 g) z = step x1 g z = g (step z x1)

where 哪里

g (step z x1) = (x2 `step` (x3 step ... (xn `step` id)...) (step z x1)

let

g' = (x3 step ... (xn `step` id)...)

gives

(x2 `step` g') (step z x1)
= step x2 g' (step z x1)
= g' (step (step z x1) x2))
= (x3 step ... (xn `step` id)...) (step (step z x1) x2))

repeats the same steps, finally we have, 重复相同的步骤,最后我们有,

(xn `step` id) (step ....(step (step z x1) x2)....)
= step xn id (step ....(step (step z x1) x2)....)
= id (step (step ....(step (step z x1) x2)....) xn)
= (step (step ....(step (step z x1) x2)....) xn)
= foldl step z xs

and now, it is obvious that why use id function. 现在,很明显为什么要使用id函数。 finally, see why 最后,看看为什么

foldl step z xs = (step (step ....(step (step z x1) x2)....) xn)

initial case: 初始案例:

foldl step z' [] = z'

recursive case: 递归案例:

foldl step z (x1:xs1) 
= foldl step (step z x1) xs1
= foldl step (step (step z x1) x2) xs2
...
= foldl step (step (step ....(step (step z x1) x2)....) xn) []
= (step (step ....(step (step z x1) x2)....) xn)

where 哪里

z' = (step (step ....(step (step z x1) x2)....) xn) in initial case

Just same as above. 和上面一样。

As Adam Smith says in the comments, there are only three arguments to foldr . 正如亚当·斯密在评论中所说, foldr只有三个论点。 The line in question gets parsed like this: 有问题的行被解析如下:

myFoldl f z xs = (foldr step id xs) z

There are other implicit brackets too of course, but these are the important ones. 当然还有其他隐含的括号,但这些是重要的。

Here is a rewrite with the type annotations, assuming scoped type variables (ie a and b mean the same types throughout this definition). 这是一个带有类型注释的重写,假设作用域类型变量(即ab在整个定义中表示相同的类型)。

myFoldl :: (a -> b -> a) -> a -> [b] -> a
myFoldl f z xs =  goFold z
   where
      goFold :: a -> a
      goFold = foldr step id xs
      step :: b -> (a -> a) -> (a -> a)  -- Last brackets are redundant
      step x g a = g (f a x)

I've moved the foldr invocation into a separate value goFold so you can see its type and how it gets applied to the z value. 我已经将foldr调用移动到单独的值goFold因此您可以看到它的类型以及它如何应用于z值。 The step function accumulates the b values into a function of type (a -> a) . step函数将b值累加到类型(a -> a)的函数中。 Each b value processed by goFold adds an extra one of these. goFold处理的每个bgoFold额外添加其中一个。 The "zero" for functions is of course id from the Prelude: 函数的“零”当然是来自Prelude的id

id :: a -> a
id x = x

The -> function operator in the types is right associative, so the last pair of brackets in the step type are redundant. 类型中的-> function运算符是右关联的,因此step类型中的最后一对括号是多余的。 But I've written it like that because it higlights the way in which step is being used; 但我这样写的是因为它突出了使用step的方式; it takes a value and a function and returns a new function. 它需要一个值和一个函数并返回一个新函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM