Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 使用多态函数作为参数_Scala_Generics_Type Inference - Fatal编程技术网

Scala 使用多态函数作为参数

Scala 使用多态函数作为参数,scala,generics,type-inference,Scala,Generics,Type Inference,我有一个函数exec,它接受3个参数,并将一个函数f作为第一个参数传递给另外两个-p1和p2 def exec[T](f: (T, T) => Boolean, p1: T, p2: T) = f(p1, p2) 如果我预先声明一个函数,并将其作为参数传递,那么一切都可以正常工作 不知何故,编译器可以推断出eq的参数类型,或者换句话说,它可以计算出在本例中的Int // declaring a function with type parameter (polymorphic m

我有一个函数
exec
,它接受3个参数,并将一个函数
f
作为第一个参数传递给另外两个-
p1
p2

  def exec[T](f: (T, T) => Boolean, p1: T, p2: T) = f(p1, p2)
如果我预先声明一个函数,并将其作为参数传递,那么一切都可以正常工作

不知何故,编译器可以推断出
eq
的参数类型,或者换句话说,它可以计算出
在本例中的
Int

  // declaring a function with type parameter (polymorphic method)
  def eq[whatever](p1: whatever, p2: whatever) = p1 == p2
  // using a declared function
  println(exec(eq, 10, 10))
如果我显式地指定
Int
,它也可以正常工作,如下所示

  // specifying type explicitly in function literal
  println(exec((p1: Int, p2: Int) => p1 == p2, 10, 10))
  // specifying type parameter
  println(exec[Int]((p1, p2) => p1 == p2, 10, 10))
问题1

有可能工作到下面吗

println(exec((p1, p2) => p1 == p2, 10, 10))
例如,通过使用隐式,以不同的方式定义
exec
,或者使用其他方式,使编译器能够推断p1和p2的类型,从而不会因
缺少参数类型而失败

因此没有使用显式类型提示或声明的方法

问题2

编译器如何推断
eq
的类型,以及为什么它适用于
p1==p2
p1!=p2
,但对于
p1>=p2
(错误为
值>=不是类型参数的成员,无论什么

问题1:是否可以让下面的内容正常工作

如果您可以像这样重写
exec

def exec[T](p1: T, p2: T)(f: (T, T) => Boolean) = f(p1, p2)
println(exec(10, 10) { case (p1, p2) => p1 == p2 })
然后,编译器将已经知道函数的输入类型。
因此,您可以这样称呼它:

def exec[T](p1: T, p2: T)(f: (T, T) => Boolean) = f(p1, p2)
println(exec(10, 10) { case (p1, p2) => p1 == p2 })
这是一个常见的习惯用法,先将普通参数放在一个参数组上,然后将函数放在一个参数组上

编译器如何推断eq的类型,以及为什么它适用于p1==p2或p1!=p2但p1>=p2时失败

因为,Scala具有普遍的平等性(这是人们对该语言批评最多的事情之一,但这对于Javainterop是必要的)

因此,您始终可以比较任意类的两个对象是否相等。
这是因为等式在Any超类中定义如下

class Any {
  def equals(other: Any): Boolean
}
但是,排序并不普遍。
如果您愿意,您可能想编写一个通用函数,该函数适用于任何类型,只要该类型有订单,您可能会对-。
但这是另一个问题的主题。

Scala 3(dotty)将能够推断
exec
中的类型,而不必依赖多个参数列表来帮助推断

scala> def exec[T](f: (T, T) => Boolean, p1: T, p2: T) = f(p1, p2)
     | exec((p1, p2) => p1 == p2, 10, 10)
def exec[T](f: (T, T) => Boolean, p1: T, p2: T): Boolean
val res0: Boolean = true

还记得我前几天说过的“总体改进”吗?这里有一个:p@LuisMiguelMej艾苏阿雷斯考虑把它作为一个答案。这将是一个很好的例子。我相信最好的答案是让它成为一个社区答案,你可以继续添加你发现的例子。@LuisMiguelMejíaSuárez谢谢!一个小的补充-不需要匿名部分函数。它的工作原理也是这样的
println(exec(10,10)((p1,p2)=>p1==p2))
。快速描述在这种情况下,为什么在Scala 2中需要进行类型派生-