为什么在Scala中,函数类型需要在单独的参数组中传递到函数中
我是scala新手,我用两种方法编写了相同的代码。但我有点混淆了两种方法。在第二种方法中,参数类型f是自动派生的,但在类型1中,scala编译器不能这样做。我只是想了解这背后的想法 Type1:给出编译错误为什么在Scala中,函数类型需要在单独的参数组中传递到函数中,scala,functional-programming,Scala,Functional Programming,我是scala新手,我用两种方法编写了相同的代码。但我有点混淆了两种方法。在第二种方法中,参数类型f是自动派生的,但在类型1中,scala编译器不能这样做。我只是想了解这背后的想法 Type1:给出编译错误 def rightFold[A,B](xs:List[A],z:B,f:(A,B) => B ): B = xs match { case Nil => z case Cons(x,xs) => f(x,rightFold(xs,z,f)) }
def rightFold[A,B](xs:List[A],z:B,f:(A,B) => B ): B = xs match {
case Nil => z
case Cons(x,xs) => f(x,rightFold(xs,z,f))
}
def sum1(l:List[Int]) = rightFold(l,0.0,_ + _)
类型2:工作正常
def rightFold[A,B](xs:List[A],z:B)(f:(A,B) => B ): B = xs match {
case Nil => z
case Cons(x,xs) => f(x,rightFold(xs,z)(f))
}
def sum1(l:List[Int]) = rightFold(l,0.0)(_ + _)
这与函数类型需要在单独的一组参数中传递(currying)无关。问题在于您在Scala还不知道的类型上使用
+
在执行函数时,编译器可以推断前两个参数的类型为List[Int]
和Double
。这允许解析+
,因为它知道两侧的类型是Int
和Dobule
现在,为什么编译器不能对单参数列表执行同样的操作呢?事实就是这样,类型信息在参数列表中是不可用的。如果您传入
(a:Int,b:Double)=>(a+b))而不是传入,那么类型1可以工作。对函数进行curry处理可以使用下划线语法,因为在尝试并传递加法函数时,scala编译器已经推断出A和B是什么类型。类型推断通过参数列表从左向右流动。换句话说,左参数列表中的类型信息在右参数列表中可用,但同一列表中的参数类型是独立推断的。对于单个列表,A
的推断类型取决于xs
和f
的类型。但是对于这两个参数列表,它只取决于xs
类型。Scala中需要记住的一个粗略准则是:类型推断并不完美,而且在使用时往往效果更好。区别不在于是否使用。
,而在于是否给出显式类型:(:Int)+(:Double)
在第一种情况下有效,(a,b)=>a+b
在第二种情况下有效。@Mittag是有道理的。好吧,显然不是,否则你(和无数被咬过的人)就不会问这个问题;-)但事实就是这样。Haskell说,与之相比,Scala的类型推断是有限的。首先,Scala有子类型,这使类型推断变得非常复杂。另外,Scala维护人员对任何可能危害良好、有用的编译错误都非常敏感。