Scala 什么';concat中foldRight和foldLeft的区别是什么

Scala 什么';concat中foldRight和foldLeft的区别是什么,scala,Scala,为什么我不能在以下代码中使用“左折”: def concatList[T](xs: List[T],ys:List[T]): List[T]= (xs foldLeft ys)(_::_) 事实上,我很难理解foldRight和foldLeft之间的区别,有没有任何例子来说明真正的区别 谢谢。好吧,你可以 scala> def concatList[T](xs: List[T],ys:List[T]) = (xs foldLeft ys)( (a, b) =

为什么我不能在以下代码中使用“左折”:

def concatList[T](xs: List[T],ys:List[T]): List[T]=
     (xs foldLeft ys)(_::_)
事实上,我很难理解foldRight和foldLeft之间的区别,有没有任何例子来说明真正的区别

谢谢。

好吧,你可以

scala> def concatList[T](xs: List[T],ys:List[T]) = 
         (xs foldLeft ys)( (a, b) => b :: a )
concatList: [T](xs: List[T], ys: List[T])List[T]

scala> concatList(List(1,2,3), List(6,7,8))
res0: List[Int] = List(3, 2, 1, 6, 7, 8)
这是你期待的结果吗?我不这么认为

首先,让我们看一下褶皱的签名和
(只是为了说明目的进行了简化,但非常适合我们的情况):

现在,在foldLeft we
xs.foldLeft(ys)
中应用一个参数列表,并统一来自foldLeft示例调用的签名的类型:

List[T]:List[Int],因此应用于foldLeft签名的T:Int和R:List[Int]给出

foldLeft[List[Int]](r:List[Int])( f:(List[Int],Int) => List[Int] )
现在,对于
::
的用法,
a::b
编译为
b.:(a)
,Scala通常将其称为一种正确的关联方法。这是以
结尾的方法的特殊语法,在定义列表时非常方便:
1::2::Nil
就像编写
Nil:::(2)。:(1)

继续我们对
foldLeft
的实例化,我们需要传递的函数必须如下所示:
(List[Int],Int)=>List[Int]
。考虑<代码>(a,b)=a::b,如果我们将其与我们的代码类型> f < /代码> GET:

a:List[Int]和b:Int,将其与
a2::b2
,a2:Int,b2:List[Int]的签名进行比较。为了进行编译,a和a2以及b和b2必须具有相同的类型。他们没有

注意,在我的示例中,我反转了参数,使a匹配b2的类型,b匹配a2的类型

我将提供另一个编译版本:

def concatList[T](xs: List[T],ys:List[T]) = (xs foldLeft ys)( _.::(_) )
简而言之,请看foldRight签名

def foldRight[R](r:R)(f: (T,R) => R):R
参数已经反转,因此使
f=\u::\ u
为我们提供了正确的类型

哇,这是关于类型推断的很多解释,我很准时,但我仍然需要解释一下左右折叠的含义之间的差异。现在,我们来看看这两种想象:

注意,foldl和foldr的参数是反向的,它首先将函数和它们作为初始参数,
r
在签名中,而不是
用于列表构造,它只使用
。两个非常小的细节。

好吧,你可以

scala> def concatList[T](xs: List[T],ys:List[T]) = 
         (xs foldLeft ys)( (a, b) => b :: a )
concatList: [T](xs: List[T], ys: List[T])List[T]

scala> concatList(List(1,2,3), List(6,7,8))
res0: List[Int] = List(3, 2, 1, 6, 7, 8)
这是你期待的结果吗?我不这么认为

首先,让我们看一下褶皱的签名和
(只是为了说明目的进行了简化,但非常适合我们的情况):

现在,在foldLeft we
xs.foldLeft(ys)
中应用一个参数列表,并统一来自foldLeft示例调用的签名的类型:

List[T]:List[Int],因此应用于foldLeft签名的T:Int和R:List[Int]给出

foldLeft[List[Int]](r:List[Int])( f:(List[Int],Int) => List[Int] )
现在,对于
::
的用法,
a::b
编译为
b.:(a)
,Scala通常将其称为一种正确的关联方法。这是以
结尾的方法的特殊语法,在定义列表时非常方便:
1::2::Nil
就像编写
Nil:::(2)。:(1)

继续我们对
foldLeft
的实例化,我们需要传递的函数必须如下所示:
(List[Int],Int)=>List[Int]
。考虑<代码>(a,b)=a::b,如果我们将其与我们的代码类型> f < /代码> GET:

a:List[Int]和b:Int,将其与
a2::b2
,a2:Int,b2:List[Int]的签名进行比较。为了进行编译,a和a2以及b和b2必须具有相同的类型。他们没有

注意,在我的示例中,我反转了参数,使a匹配b2的类型,b匹配a2的类型

我将提供另一个编译版本:

def concatList[T](xs: List[T],ys:List[T]) = (xs foldLeft ys)( _.::(_) )
简而言之,请看foldRight签名

def foldRight[R](r:R)(f: (T,R) => R):R
参数已经反转,因此使
f=\u::\ u
为我们提供了正确的类型

哇,这是关于类型推断的很多解释,我很准时,但我仍然需要解释一下左右折叠的含义之间的差异。现在,我们来看看这两种想象:


注意,foldl和foldr的参数是反向的,它首先将函数和它们作为初始参数,
r
在签名中,而不是
用于列表构造,它只使用
。两个非常小的细节。

一个从左到右,另一个从右到左。一个从左到右,另一个从右到左。