def foldLeft[A,B](xs: List[A], e: B, f: (B, A) => B): B
如果您有f: B => A => B或def foldLeft[A, B](xs: List[A])(e: B)(f: (B, A) => B): B或def foldLeft[A, B]: List[A] => B => ((B, A) => B) => B等,则Currying将是Currying。现在foldLeft只是一个higher-order function(方法),即接受另一个函数(f)的函数。
def valuesToValue[A](values: List[Value[A]]): Value[List[A]] = values match {
case Nil => Value(Nil)
case v :: vs => Value(v.value :: valuesToValue(vs).value)
}
2条答案
按热度按时间ff29svar1#
让我们深入研究这个方法签名:
foldLeft
是一个有3个参数的方法A
和B
为类型参数xs
是方法的第一个参数,类型为List[A]
e
是第二个参数,类型为B
f
是第三个参数,类型为(B, A) => B
(B, A) => B
表示一个函数分别接受B
和A
类型的两个参数,并返回B
B
是该方法的返回类型nuypyhwy2#
只有几条建议。
顺便说一句,没有什么好插手的。
如果您有
f: B => A => B
或def foldLeft[A, B](xs: List[A])(e: B)(f: (B, A) => B): B
或def foldLeft[A, B]: List[A] => B => ((B, A) => B) => B
等,则Currying将是Currying。现在foldLeft
只是一个higher-order function(方法),即接受另一个函数(f
)的函数。foldRight
/foldLeft
的维基文章:https://en.wikipedia.org/wiki/Fold_(higher-order_function)
尤其要看看下面的图片,我们是如何解构一个列表的,以及我们从什么地方开始进行计算:
foldRight
/foldLeft
视为定义recursion的一种简单方法(而不是模式匹配列表和进行递归调用)。让我们来考虑一个例子。让我们进行一些递归。例如,让我们有一个 Package 类
让我们将
Value[A]
的列表转换为一个值,该值将A
的列表 Package 为Value[List[A]]
。例如,我们希望将List(Value(1), Value(2), Value(3))
转换为Value(List(1, 2, 3))
(我实际上需要这样的函数recently)。当然,我们可以使用.map
做到这一点,但让我们假装不知道map
(我们可以进行Map并不奇怪,因为map
可以通过foldRight
/foldLeft
表示)。我们可以通过两种方式递归地完成这项工作(至少)。要么是简单的递归
或具有助手函数和累加器的tail recursion
非常简单。只是在 Package --打开 Package 。
valuesToValue
的两个递归实现都可以用foldRight
/foldLeft
(自动)重写。以前的递归可以用foldRight
重写。后面的递归(尾部递归)可以用foldLeft
重写。让我们用
foldRight
重写第一个递归。分支case Nil => ...
的值成为foldRight
的第一个参数。如果我们用新变量res
替换递归调用valuesToValue(vs)
的结果,那么来自分支case v :: vs => ...
的值将成为foldRight
的第二个参数,因此在foldRight
的第二个参数中,我们将有一个函数v: Value[A]
和res: Value[List[A]]
让我们用
foldLeft
重写第二个递归(尾部第一个)。首先,让我们回想一下,由于引用,我们可以将助手
loop
理解为Value[List[A]] => Value[List[A]]
的单参数函数现在,分支
case Nil => ...
中的值成为foldLeft
的第一个参数。如果将递归调用loop(vs)(_)
的结果替换为新变量res
(函数),则分支case v :: vs => ...
的值将成为foldLeft
的第二个参数因此,粗略地说,分支
case Nil => ...
和case v :: vs => ...
的值变成了foldRight
/foldLeft
的参数,这取决于我们是使用简单递归还是使用累加器进行尾递归计算。