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

时间:2015-02-11 13:49:10

标签: scala implicit-conversion higher-order-functions

我遇到了隐式转换和高阶函数的问题。似乎只有转换函数至少有两个参数,才能将函数隐式转换为二阶函数。

使用:

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

不起作用:

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

使用:

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

失败点的完整示例:

{
    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)
}

我错过了什么?

谢谢!

2 个答案:

答案 0 :(得分:3)

  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!
  // ¯\_(ツ)_/¯

问题是隐式转换如何对Scala起作用以及Scala中存在curried和uncurried函数的事实。

这应该是可行的,但不是,并且可能只是另一个编译器错误(随着越来越多地使用Scala,准备好再遇到更多)。

编辑:至于你的上一个例子

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

那是因为函数定义匹配。 conv期望函数(Int, Int) => String和scala中的正常方法定义(uncurried),就像定义baadf00d的方式一样,变成了那个。

例如,一个函数:

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

变成了

(Int, Int) => String

请注意,2个Int是tupled!这与以下内容不同:

Int => Int => String

如果您要将baadf00d重新定义为:

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

该代码不会编译,因为baadf00d现在是&#34;不同&#34;,即使它正在做同样的事情。

有关更多信息,请查看对象的定义:

Function1, Function2, Function3 ....

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

答案 1 :(得分:-1)

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

这是A => BFunction1[A,B]之间未发生的转换。

Function中还有Predef类型 - 请注意此处的类型差异:

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

它是Function1的别名,但具有不同的类型范围(如下面的评论中所述)。