我有一个函数exec
,它接受3个参数,并将作为第一个参数传递的函数f
应用于其他两个参数p1
和p2
。
def exec[T](f: (T, T) => Boolean, p1: T, p2: T) = f(p1, p2)
如果我事先声明一个将作为参数传递的函数,那么一切都很好。
以某种方式,编译器可以推断eq
的参数类型,换句话说,它可以确定whatever
在这种情况下为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的类型,以便它不会因missing parameter type
而失败。
因此,不使用显式类型提示或声明的方法。
问题2
编译器如何推断eq
的类型,以及为什么它适用于p1 == p2
或p1 != p2
之类的表达式,但对于p1 >= p2
却失败(错误为value >= is not a member of type parameter whatever
)?
问题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 })
这是一个常见的习惯用法,首先将普通参数放在一个参数组上,然后再将函数放在单个参数组上。
编译器如何推断eq的类型以及为什么它适用于p1 == p2或p1!= p2之类的表达式,但对于p1> = p2则失败
因为,Scala具有普遍平等(这是人们最批评该语言的东西之一,但对于Java互操作来说是必需的。)]
因此,您始终可以比较任何类的两个对象以确保相等。这是因为在Any
超类中定义了相等性,如下所示。class Any { def equals(other: Any): Boolean }
但是,订购不是普遍的。如果需要,您可能想编写一个适用于任何类型的泛型函数,只要有这种类型的顺序即可,您可能会对
Ordering
-Ordering
感兴趣。但这是另一个问题的话题。
Scala 3(点状)将能够推断typeclass中的类型,而不必依赖多个参数列表来进行推断