简体   繁体   English

仅当要转换的函数具有至少两个参数时,才能将函数隐式转换为二阶函数

[英]Implicit conversion of a function to a second-order-function only works if the function to convert has at least two parameters

I have a problem of implicit conversions and higher-order functions. 我有隐式转换和高阶函数的问题。 It seems that an implicit conversions of a function to a second-order-function only works, if the function to convert has at least two parameters. 似乎只有转换函数至少有两个参数,函数到二阶函数的隐式转换才有效。

Works: 作品:

implicit def conv(foo: Integer => String): String => String = null

Does not work: 不起作用:

implicit def conv(foo: Integer => String): String => String => String = null

Works: 作品:

implicit def conv(foo: (Integer, Integer) => String): String => String => String = null

Full example with point of failure: 完整的失败点示例:

{
    implicit def conv(foo: Integer => String): String => String = null

    def baadf00d(foo: Integer): String = null

    def deadbeef(foo: String => String) = null

    deadbeef(conv(baadf00d))

    deadbeef(baadf00d)
}

{
    implicit def conv(foo: Integer => String): String => String => String = null

    def baadf00d(foo: Integer): String = null

    def deadbeef(foo: String => String => String) = null

    deadbeef(conv(baadf00d))

    deadbeef(baadf00d) // <-------- DOES NOT COMPILE!
}

{
    implicit def conv(foo: (Integer, Integer) => String): String => String => String = null

    def baadf00d(foo: Integer, bar: Integer): String = null

    def deadbeef(foo: String => String => String) = null

    deadbeef(conv(baadf00d))

    deadbeef(baadf00d)
}

What am I missing? 我错过了什么?

Thanks! 谢谢!

  implicit def conv(foo: Integer => String): String => String => String = ???

  def baadf00d(i: Integer): String = ???
  def goodf00d: Integer => String = _ => ???

  def deadbeef(foo: String => String => String) = ???

  deadbeef(conv(baadf00d))

  deadbeef(baadf00d) // <-------- DOES NOT COMPILE!
  deadbeef(goodf00d) // <-------- COMPILE!
  // ¯\_(ツ)_/¯

The issue is how implicit conversions work on Scala and the fact that there are curried and uncurried functions in Scala. 问题是隐式转换如何对Scala起作用以及Scala中存在curried和uncurried函数的事实。

This is something that SHOULD work but doesn't and is probably just yet another compiler bug (get ready to meet many more as you use Scala more and more). 这应该是应该工作但不会,并且可能只是另一个编译器错误(随着您越来越多地使用Scala,准备好满足更多)。

EDIT: As for your last example 编辑:至于你的最后一个例子

implicit def conv(foo: (Integer, Integer) => String): String => String => String = null

def baadf00d(foo: Integer, bar: Integer): String = null

def deadbeef(foo: String => String => String) = null

That's because there the function definitions do match. 那是因为函数定义确实匹配。 The conv expects a function (Int, Int) => String and a normal method definition (uncurried) in scala, like how baadf00d is defined, turns into that. conv期望一个函数(Int, Int) => String和scala中的普通方法定义(uncurried),就像baadf00d的定义一样,转变为。

For example, a function: 例如,一个函数:

def f(a: Int, b: Int): String

Gets turned into a 变成了一个

(Int, Int) => String

Notice that the 2 Ints are tupled! 请注意,2个Int是有问题的! This is NOT the same as: 这与以下内容不同:

Int => Int => String

If you were to redefine baadf00d into: 如果你要将baadf00d重新定义为:

def baadf00d: Integer => Integer => String = _ => _ => ???

That code won't compile, because baadf00d is now "different", even though it is doing the same thing. 该代码将无法编译,因为baadf00d现在“不同”,即使它正在做同样的事情。

For more information, look at the definition of the objects: 有关更多信息,请查看对象的定义:

Function1, Function2, Function3 ....

http://www.scala-lang.org/api/current/#scala.Function2 http://www.scala-lang.org/api/current/#scala.Function2

implicit def conv1(a: Function1[Int, String]): Function2[String, String, String] = null
def baadf00d1(i: Int): String = null
def deadbeef1(arg: Function2[String, String, String]) = null  
deadbeef(baadf00d) // compiles

It's the conversion between A => B and Function1[A,B] that isn't happening. 这是A => BFunction1[A,B]之间没有发生的转换。

Also there is a Function type in Predef -- notice the type differences here: Predef还有一个Function类型 - 请注意这里的类型差异:

scala> val f1: Function[Int, Int] = null
f1: Function[Int,Int] = null

scala> val f2: Function1[Int, Int] = null
f2: Int => Int = null

scala> :type f1
Function[Int,Int]

scala> :type f2
Int => Int

It's an alias to Function1 , but with different type bounds (as pointed out in the comments below). 它是Function1的别名,但具有不同的类型边界(如下面的注释中所指出的)。

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

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