Foldright foldleft
先来看一下foldleft的一个简单定义
@annotation.tailrec
deffoldLeft[A,B](as:List[A],z:B)(f:(B,A)=>B):B = as match{
case Nil=> z
case Cons(h,t) =>foldLeft(t,f(z,h))(f)
}
尾递归版本foldleft,每次把第一个h与z进行f运算然后递归调用foldleft
Foldright很多情况下不是尾递归的,我们要改写成尾递归形式
使用尾递归的foldleft来实现foldright
def foldRight1[A,B](as: List[A], z: B)(f: (A, B) => B): B = {
foldLeft(reverse(as), z)((b, a) => f(a, b))
}
def foldRight2[A,B](as: List[A], z: B)(f: (A, B) => B): B = {
foldLeft(as, (b: B) => b) ((g, a) => b =>g(f(a, b))) (z)
}
第一个里面使用的是通过foldleft来实现的一个reverse函数
defreverse(ns:List[A]):List[A] = {
foldLeft(ns,List[A]())((acc,h)=>Cons(h,acc))
}
很简单,略过
第二个函数就不是很好懂了,我们来把它拆开
改写一下定义:
def foldRight3[A,B](as: List[A], outerIdent: B)(combiner: (A, B)=> B): B =
我们不需要直接build出 B 的value,因此我们使用了一个函数 BtoB:B=>B fold的过程需要 a:A 和一个函数 g: B=>B.
因此我们有了一个新函数
(b => g(f(a,b))): B=>B.
我们可以把fold过程写成这样:
As.foldLeft(identity _)((g, a) => g compose (b => f(a, b)))(z)
我们来看一下这个语句:对于 as 中的所有元素 a,我们部分施用 b=> f (b,a),这个函数是个B=>B类型的。然后我们将函数复合一下:
(g, a) => b => g(f(a, b)). 最后把这整个的函数应用到z上,就是
((g, a)=> b => g(f(a, b))) (z)