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.
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).
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.
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! This is NOT the same as:
Int => Int => String
If you were to redefine baadf00d into:
def baadf00d: Integer => Integer => String = _ => _ => ???
That code won't compile, because baadf00d is now "different", even though it is doing the same thing.
For more information, look at the definition of the objects:
Function1, Function2, Function3 ....
http://www.scala-lang.org/api/current/#scala.Function2
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With