scala E:B,f:(B,A)=>B):B

tct7dpnv  于 2022-11-09  发布在  Scala
关注(0)|答案(2)|浏览(241)

我对这意味着什么感到困惑。我理解慌乱,但我似乎不能完全读懂代码。

def foldLeft [A,B](xs:List[A], e:B, f:(B,A)=>B): B
ff29svar

ff29svar1#

让我们深入研究这个方法签名:

foldLeft[A,B](xs: List[A], e: B, f: (B, A) => B): B
  • foldLeft是一个有3个参数的方法
  • AB类型参数
  • xs是方法的第一个参数,类型为List[A]
  • e是第二个参数,类型为B
  • f是第三个参数,类型为(B, A) => B
  • 类型(B, A) => B表示一个函数分别接受BA类型的两个参数,并返回B
  • 最后,B是该方法的返回类型
nuypyhwy

nuypyhwy2#

只有几条建议。
顺便说一句,没有什么好插手的。

def foldLeft[A,B](xs: List[A], e: B, f: (B, A) => B): B

如果您有f: B => A => Bdef foldLeft[A, B](xs: List[A])(e: B)(f: (B, A) => B): Bdef 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 类

case class Value[A](value: A)

让我们将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表示)。
我们可以通过两种方式递归地完成这项工作(至少)。要么是简单的递归

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)
}

或具有助手函数和累加器的tail recursion

def valuesToValue[A](values: List[Value[A]]): Value[List[A]] = {
  @tailrec
  def loop(values: List[Value[A]], acc: Value[List[A]]): Value[List[A]] = values match {
    case Nil     => Value(acc.value.reverse)
    case v :: vs => loop(vs, Value(v.value :: acc.value))
  }

  loop(values, Value(Nil))
}

非常简单。只是在 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]]

def valuesToValue[A](values: List[Value[A]]): Value[List[A]] =
  values.foldRight( Value(Nil: List[A]) ){
    (v, res) => Value(v.value :: res.value)
  }

让我们用foldLeft重写第二个递归(尾部第一个)。
首先,让我们回想一下,由于引用,我们可以将助手loop理解为Value[List[A]] => Value[List[A]]的单参数函数

def loop(values: List[Value[A]]): Value[List[A]] => Value[List[A]] = values match {
  case Nil     => acc => Value(acc.value.reverse)
  case v :: vs => acc => loop(vs)(Value(v.value :: acc.value))
}

现在,分支case Nil => ...中的值成为foldLeft的第一个参数。如果将递归调用loop(vs)(_)的结果替换为新变量res(函数),则分支case v :: vs => ...的值将成为foldLeft的第二个参数

def valuesToValue[A](values: List[Value[A]]): Value[List[A]] = {
  def loop(values: List[Value[A]]): Value[List[A]] => Value[List[A]] =
    values.foldRight[Value[List[A]] => Value[List[A]]](
                  acc => Value(acc.value.reverse)
    )(
      (v, res) => acc => res(Value(v.value :: acc.value))
    )

  loop(values)(Value(Nil))
}

因此,粗略地说,分支case Nil => ...case v :: vs => ...的值变成了foldRight/foldLeft的参数,这取决于我们是使用简单递归还是使用累加器进行尾递归计算。

相关问题