简体   繁体   English

使用多态 function 作为参数

[英]Using polymorphic function as a parameter

I have a function exec which accepts 3 parameters and applies a function f passed as first argument to the other two - p1 and p2 .我有一个 function exec程序,它接受 3 个参数并应用 function f作为第一个参数传递给其他两个 - p1p2

  def exec[T](f: (T, T) => Boolean, p1: T, p2: T) = f(p1, p2)

Everything works fine if I declare in advance a function which will be passed as an argument.如果我提前声明一个 function 将作为参数传递,一切正常。

Somehow compiler can infer types for arguments of eq or in other words it can figure out that whatever in this case is Int不知何故,编译器可以推断出eq的 arguments 的类型, 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))

It also works fine if I explicitly specify Int as shown below如果我明确指定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))

Question 1问题 1

Is it possible to get below working?是否有可能低于工作?

println(exec((p1, p2) => p1 == p2, 10, 10))

For example, by using implicits, defining exec differently or using some other way making it possible for compiler to infer types of p1 and p2 so that it does not fail with missing parameter type .例如,通过使用隐式、不同地定义exec或使用其他方式使编译器能够推断 p1 和 p2 的类型,这样它就不会因missing parameter type而失败。

So no explicit type hints or declared methods are used.所以没有使用明确的类型提示或声明的方法。

Question 2问题2

How does compiler infer types for eq and why it works for expressions like p1 == p2 or p1 != p2 but fails for p1 >= p2 (error is value >= is not a member of type parameter whatever )?编译器如何推断eq的类型以及为什么它适用于p1 == p2p1 != p2等表达式但p1 >= p2失败(错误是value >= is not a member of type parameter whatever )?

Question 1 Is it possible to get below working?问题1 是否有可能低于工作?

If you can rewrite exec like this:如果您可以像这样重写exec

def exec[T](p1: T, p2: T)(f: (T, T) => Boolean) = f(p1, p2)

Then, the compiler will already know the input type of the function.然后,编译器将已经知道 function 的输入类型。
So, you will be able to call it like this:所以,你可以这样称呼它:

println(exec(10, 10) { case (p1, p2) => p1 == p2 })

This is a common idiom, to put plain parameters first and then a function on a single parameter group.这是一个常见的习惯用法,先放置普通参数,然后在单个参数组上放置 function。

How does compiler infer types for eq and why it works for expressions like p1 == p2 or p1 != p2 but fails for p1 >= p2编译器如何推断 eq 的类型以及为什么它适用于 p1 == p2 或 p1 != p2 等表达式但对于 p1 >= p2 失败

Because, Scala has universal equality (which is one of the things people most criticize of the language, but it was necessary for Java interop).因为, Scala具有普遍平等(这是人们最批评该语言的事情之一,但对于Java互操作来说是必要的)。

So, you can always compare two objects of any class for equality.因此,您始终可以比较任何 class 的两个对象是否相等。
That is because equality is defined in the Any superclass as follows.这是因为在Any超类中定义了相等性,如下所示。

class Any {
  def equals(other: Any): Boolean
}

But, ordering is not universal.但是,排序不是普遍的。
If you want, you may want to write a generic function which works for any type as long as there is an order for such type, you may be interested in theOrdering - typeclass .如果你愿意,你可能想写一个通用的 function 只要有这种类型的订单,它就适用于任何类型,你可能对Ordering - typeclass感兴趣。
But that is topic for another question.但这是另一个问题的主题。

Scala 3 (dotty) will be able to infer the types in exec without having to rely on multiple parameter lists to help inference 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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM