首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >e:B,f:(B,A)=>B):B

e:B,f:(B,A)=>B):B
EN

Stack Overflow用户
提问于 2022-10-01 04:24:05
回答 2查看 132关注 0票数 0

我搞不懂这意味着什么。我理解赛跑,但我似乎看不清所有的代码。

代码语言:javascript
复制
def foldLeft [A,B](xs:List[A], e:B, f:(B,A)=>B): B
EN

回答 2

Stack Overflow用户

发布于 2022-10-01 06:41:56

只是几个建议。

顺便说一句,没有人跑进来。

代码语言:javascript
复制
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等,那么foldLeft就是高阶函数 (方法),即接受另一个函数(f)的函数。

  • 您可以阅读关于foldRight/foldLeft的wiki文章

职能)

特别是看看我们是如何解构一个列表的,并从我们执行计算的目的出发:

  • 您可以将foldRight/foldLeft看作是定义递归 (而不是模式匹配列表和进行递归调用)的一种简单方法。

让我们考虑一个例子。让我们进行一些递归。例如,让我们有一个包装类

代码语言:javascript
复制
case class Value[A](value: A)

让我们将一个Value[A]列表转换为一个值,将一个A列表(即List[Value[A]] )包装到Value[List[A]]中。例如,我们希望将List(Value(1), Value(2), Value(3))转换为Value(List(1, 2, 3)) (我实际上需要这样的函数最近)。当然,我们可以用.map来完成这个任务,但是让我们假设我们不知道map (我们可以进行映射,因为map可以通过foldRight/foldLeft表示)。

我们可以通过两种方式递归地完成这个任务(至少)。简单递归

代码语言:javascript
复制
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)
}

或带有辅助函数和累加器的尾递归

代码语言:javascript
复制
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))
}

非常简单。只是包装-拆开。

valuesToValue的两个递归实现都可以(自动)用foldRight/foldLeft重写。前一个递归可以用foldRight重写.后一种递归(尾一)可以用foldLeft重写.

让我们用foldRight重写第一次递归。分支case Nil => ...的值成为foldRight的第一个参数。如果将递归调用的结果替换为一个新的变量case v :: vs => ...,则分支valuesToValue(vs)的值将成为foldRight的第二个参数,因此在foldRight的第二个参数中,我们将有一个v: Value[A]res: Value[List[A]]函数。

代码语言:javascript
复制
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]]中的一个单参数函数。

代码语言:javascript
复制
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的第一个参数。如果我们用一个新变量(函数)替换递归调用case v :: vs => ...的结果,则分支loop(vs)(_)的值将成为foldLeft的第二个参数。

代码语言:javascript
复制
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的参数,这取决于我们是用简单递归计算还是用累加器计算尾递归。

票数 3
EN

Stack Overflow用户

发布于 2022-10-01 11:43:31

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

代码语言:javascript
复制
foldLeft[A,B](xs: List[A], e: B, f: (B, A) => B): B
  • foldLeft是一种具有三个参数的方法
  • AB是类型参数
  • xs是该方法的第一个参数,属于List[A]类型。
  • e是第二个参数,类型为B
  • f是第三个参数,类型为(B, A) => B
    • 类型(B, A) => B表示一个函数,它分别接受BA类型的两个参数,并返回一个B

  • 最后,B是该方法的返回类型。
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73915799

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档