Scala strange implicit boxing conversion error - scala

Can someone tell me why the following does not work?
object TestObject {
def map(f: (Double, Double) => Double, x2: Array[Double]) = {
val y = x2.zip( x2 )
val z = y.map(f)
z
}
}
Produces this error:
type mismatch; found : (Double, Double) => Double required: ((Double, Double)) => ?

In this snippet, f is a function taking two Double parameters and returning a Double.
You are attempting to call f by passing a single argument of type Tuple2[Double,Double].
You can fix this by changing the type of f in the first place:
object TestObject {
def map(f: ((Double, Double)) => Double, x2: Array[Double]) = {
val y = x2.zip( x2 )
val z = y.map(f)
z
}
}
You could also declare it as f: Tuple2[Double, Double] => Double to be clearer (this is entirely equivalent).
Conversely, you could change your call like this:
object TestObject {
def map(f: (Double, Double) => Double, x2: Array[Double]) = {
val y = x2.zip( x2 )
val z = y.map(f.tupled)
z
}
}
tupled automagically transforms your (Double, Double) => Double function into a Tuple2[Double, Double] => Double function.
Keep in mind however that the conversion will be done on each call to TestObject.map

There is a subtle difference between
f: (Double, Double) => Double // two Double arguments -> Double
and
f: ((Double, Double)) => Double // one Tuple2[Double, Double] argument -> Double
y is an Array[(Double, Double)], so it expects a method that takes a tuple and returns something, but the first f defined above doesn't match that.
You can do y.map(f.tupled) to go from the first to the second, or change the signature of f.

I think your issue is that f expects two Double arguments but you're attempting to pass it a single tuple: f((1, 2)) is different from f(1, 2).
Change the type of f to ((Double, Double) => Double) and it should work.

Related

Using a mutli parameter function as generic type of another function scala

I have the following code
object Test {
def bar: String => Double = {
foo[String](_.toDouble)
}
def baz: (Double, Double) => Double = {
foo[(Double, Double)] {
case (d1, d2) => d1 + d2
}
}
def foo[T](f: T => Double): T => Double = {
f
}
}
bar works with no trouble, as expected. I am trying to get a similar thing working with mutli parameter function as one of the inputs, but this doesn't work, because scala sees the foo[(Double, Double)] as a tuple type rather than as a function parameter. Is there any way to tell scala this is a function parameter, rather than a tuple?
the code: https://scastie.scala-lang.org/sCYyU6ziT3mKOhkBiofAaQ
I think the reason this didn't work for you is that you don't access the two separate arguments to the baz method, which need to be packaged into a tuple before calling foo. (I think there's some discussion about being able to convert parameter lists to/from tuples, but that's not currently possible.) Try this definition instead:
object Test {
def bar: String => Double = {
foo[String](_.toDouble)
}
def baz: (Double, Double) => Double = {(p1, p2) =>
foo[(Double, Double)] {
case(d1, d2) => d1 + d2
}((p1, p2))
}
def foo[T](f: T => Double): T => Double = f
}
If I understand your intent correctly, this would be used like this (in the Scala REPL):
scala> Test.bar("5.0")
val res0: Double = 5.0
scala> Test.baz(3.0, 5.0)
val res1: Double = 8.0
However, this seems a little muddled. If bar and baz store method references, then they should be declared val, instead of def:
object Test {
val bar: String => Double = {
foo[String](_.toDouble)
}
val baz: (Double, Double) => Double = {(p1, p2) =>
foo[(Double, Double)] {
case(d1, d2) => d1 + d2
}((p1, p2))
}
def foo[T](f: T => Double): T => Double = f
}
Which has the same usage syntax and produces the same output:
scala> Test.bar("5.0")
val res2: Double = 5.0
scala> Test.baz(3.0, 5.0)
val res3: Double = 8.0
But even that is still fairly clumsy. bar is a reference to a function that takes a String and returns a Double, while baz is a reference to a function that takes two Doubles and returns a Double. So why not just make bar and baz methods in their own right, instead of method references? This would produce:
object Test {
def bar(s: String): Double = foo[String](_.toDouble)(s)
def baz(p1: Double, p2: Double): Double = {
foo[(Double, Double)] {
case(d1, d2) => d1 + d2
}((p1, p2))
}
def foo[T](f: T => Double): T => Double = f
}
which again is used in the same way:
scala> Test.bar("5.0")
val res4: Double = 5.0
scala> Test.baz(3.0, 5.0)
val res5: Double = 8.0
And, of course, foo itself is redundant, since it is identical to its argument. So this could all be written far more simply as just:
object Test {
def bar(s: String): Double = s.toDouble
def baz(p1: Double, p2: Double): Double = p1 + p2
}

Partially applied function from first-class function

val divide = (num: Double, den: Double) => {
num / den
}
//type of pafv1 is () => (Double,Double) => Double
val pafv1 = divide _
//type of pafv2 is Double => Double
val pafv2 = divide(_:Double,2)
Why type of pafv1 is not (Double,Double) => Double?
When divide is a simple method, type of pafv1 is (Double,Double) => Double.
I think the explanation comes from eta expansion.
Scala makes getters and setters of vals, which means divide is in fact a method def divide = (num: Double, den: Double) => { num / den }
When you do val pafv1 = divide _, this expands it into the eta expanded version of divide, namely () => (num: Double, den: Double) => { num / den }
Why is it doing eta expansion? Because you are trying to use a method as a value (you are partially evaluating _, forcing the result to be a function value).
That's weird... If you compile this piece of code:
class C {
val f = (n: Double, d: Double) => n / d
val pf = f _
}
with the -print flag, the desugared code is:
package <empty> {
class C extends Object {
private[this] val f: Function2 = _;
<stable> <accessor> def f(): Function2 = C.this.f;
private[this] val pf: Function0 = _;
<stable> <accessor> def pf(): Function0 = C.this.pf;
final <artifact> private[this] def $anonfun$f$1(n: Double, d: Double): Double = n./(d);
final <artifact> private[this] def $anonfun$pf$1(): Function2 = C.this.f();
def <init>(): C = {
C.super.<init>();
C.this.f = {
((n: Double, d: Double) => C.this.$anonfun$f$1(n, d))
};
C.this.pf = {
(() => C.this.$anonfun$pf$1())
};
()
}
}
}
Some observations:
The val f declaration is split into a private this val f: Function2 and into an <stable> <accessor> def f(): Function2.
The stable accessor method is wrapped into an anonymous function $anonfun$pf$1() that simply redirects all calls to C.this.f().
The pf eta-expands the parameterless $anonfun$pf$1() method into a function that takes no arguments and returns a Function2.
If I had to write down an equivalent piece of code that demonstrates "what actually happens", I'd probably write something like this:
class C2 {
var f: Function2[Double, Double, Double] = _
def fAccessor(): Function2[Double, Double, Double] = this.f
f = (n: Double, d: Double) => n / d
val pf = fAccessor _
}
Here you see that:
fAccessor is a method without arguments that returns a Function2
pf is eta-expansion of the accessor method fAccessor, which also takes zero arguments, and returns a Function2.
So, to conclude: for some weird reason, f _ is the eta-expansion of the otherwise invisible accessor method. I think this should not compile at all, looks like an abstraction leak (some synthetic implementation dependent method symbols appearing out of nowhere).
What you might have wanted:
val pf: Double => Double => Double = n => f(n, _)
I usually "wrap" the function in a case expression:
val divide = (num: Double, den: Double) => num / den
val partialDivide: PartialFunction[(Double, Double), Double] = {
case (num: Double, den: Double) if den != 0 => divide(num, den)
}
partialDivide(4, 2)
partialDivide(4, 0) // throws a `MatchError`
You can play around with this code on Scastie.
You can find a very thorough explanation of the topic here.
From the scala language specification one can read:
If e is a parameterless method … , e _ represents the function of type () => T, which evaluates e when it is applied to the empty parameterlist ().
This is what we see happening.

Signature of a function that takes an unkown number of inputs

Try:
def big[T1, T2](func: T1 => T2) = func
def small(t1: Double, t2: Double) = (t1, t2)
big(small)
Error:
Type mismatch: Expected (NotInfered1) => NotInferedT2, actual: (Double, Double) => (Double, Double)
Same with:
def big[T1, T2](func: (T1*) => T2) = func
I believe the parameter signature for "big" should be something else that accepts a function that takes an unknown number of arguments.
Here are couple options:
1) Using tupled - converts that function to Function1 so compiler is happy (not the user though :)):
scala> def big[T1, T2](func: T1 => T2) = func
big: [T1, T2](func: T1 => T2)T1 => T2
scala> def small(t1: Double, t2: Double) = (t1, t2)
small: (t1: Double, t2: Double)(Double, Double)
scala> big(small)
<console>:10: error: type mismatch;
found : (Double, Double) => (Double, Double)
required: ? => ?
big(small)
^
scala> big(small _ tupled)
warning: there were 1 feature warning(s); re-run with -feature for details
res1: ((Double, Double)) => (Double, Double) = <function1>
2) Change the type of big to take anything that produces T:
scala> def big[T](func: => T) = func
big: [T](func: => T)T
scala> big(small _)
res3: (Double, Double) => (Double, Double) = <function2>
scala> def verysmall(t1: Int) = t1
verysmall: (t1: Int)Int
scala> big(verysmall _)
res4: Int => Int = <function1>
Note that in the first case it's a Function1 that takes a tuple and in the second case it's a Function2 that takes 2 params.
Looks like you vere looking for ( => T) syntax.
Scala does not have functions that take any arbitrary number of arguments. Methods can be variadic, e.g. def x(x: Int*), but functions must inherit from one of the Function traits, e.g. Function1, Function2, which forces them to have a definite number of parameters.
However, you can instead use functions that take a tuple:
val small = (tuple: (Double, Double)) => tuple

Why doesn't Function2 have an andThen method?

Why does andThen only exist for single argument functions in Scala?
The following code works:
val double = (x: Int) => x * 2
val timesFour = double andThen double
But why is there no andThen method for multi argument functions?
val multiply = (x: Int, y: Int) => x * y
val multiplyAndDouble = multiply andThen double
<console>:10: error: value andThen is not a member of (Int, Int) => Int
Surely it is trivial to add this method. Is there a reason it been omitted from the standard library?
I have just noticed it is easy to work around with the following:
val multiplyAndDouble = multiply.tupled andThen double
val res = multiplyAndDouble(1, 3) // res = 6
I can't speak as to why Function2 doesn't supply and andThen, but Scalaz defines Functor instances for functions of various arities where map is equivalent to andThen, meaning you could write
val multiplyAndDouble = multiply map double
There is a similar question here:
Scala API 2.10.*: Function2.andThen what happened to?, but there is also no answer. In my opinion it is possible. Here is working example for Scala 2.11.1:
object TestFunction2 {
def main(args: Array[String]): Unit = {
val double = (x: Int) => x * 2
val timesFour = double andThen double
println(timesFour(2)) // prints 8
val multiply = (x: Int, y: Int) => x * y
val multiplyAndDouble = multiply andThen double
println(multiplyAndDouble(1, 3)) // prints 6
}
implicit def toFunc2(function2: Function2[Int, Int, Int]): Func2[Int, Int, Int] = {
new Func2[Int, Int, Int] {
def apply(v1: Int, v2: Int): Int = function2(v1, v2)
}
}
}
trait Func2[-T1, -T2, +R] extends Function2[T1, T2, R] {
def andThen[A](g: R => A): (T1, T2) => A = { (x, y) => g(apply(x, y)) }
}
Another way to write theons's answer is to use:
val multiplyAndDouble = double compose multiply.tupled
val result = multiplyAndDouble(2, 6) // res 24

Generic scala function whose input is a function of variable arity

I want to define a function f that takes another function g. We require g to take take n Doubles (for some fixed n) and return a Double. The function call f(g) should return the specific value of n.
For example, f(Math.max) = 2 since Math.sin has type (Double, Double) => Double, and f(Math.sin) = 1 since Math.sin has type Double => Double.
How can I define f using Scala generics?
I've tried several forms without success. For example:
def f[A <: Product](g: Product => Double) = {...}
This doesn't work since we cannot extract the value of n at compile time, and cannot constrain the A to contain only Double values.
There is a pattern called Magnet Pattern, created by the Spray team. It does exectly what you want
This was a good excuse for me to look into Shapeless, something I always wanted to do at some point :)
$ git clone git#github.com:milessabin/shapeless.git
...
$ cd shapeless
(1)
Shapeless provides some abstractions over arity, and especially the representation as heterogeneous list (HList). A function of arbitrary arity can be seen as FnHList (a function that takes an HList as argument).
$ sbt shapeless-core/console
scala> import shapeless._
import shapeless._
scala> def isFunction[A](fun: A)(implicit fnh: FnHLister[A]) {}
isFunction: [A](fun: A)(implicit fnh: shapeless.FnHLister[A])Unit
scala> isFunction(math.sqrt _)
scala> isFunction(math.random _)
(2)
Now let's require that the function returns a Double:
scala> def isFunReturningDouble[A](fun: A)(implicit fnh: FnHLister[A] { type Result = Double }) {}
isFunReturningDouble: [A](fun: A)(implicit fnh: shapeless.FnHLister[A]{type Result = Double})Unit
scala> isFunReturningDouble(math.sqrt _)
scala> isFunReturningDouble(math.signum _)
<console>:12: error: could not find implicit value for parameter fnh: shapeless.FnHLister[Int => Int]{type Result = Double}
isFunReturningDouble(math.signum _)
^
(3)
The LUBConstraint type class can witness the upper bound of the argument list:
scala> def isValidFun[A, B <: HList](fun: A)(implicit fnh: FnHLister[A] { type Result = Double; type Args = B }, lub: LUBConstraint[B, Double]) {}
isValidFun: [A, B <: shapeless.HList](fun: A)(implicit fnh: shapeless.FnHLister[A]{type Result = Double; type Args = B}, implicit lub: shapeless.LUBConstraint[B,Double])Unit
scala> isValidFun(math.random _)
scala> isValidFun((i: Int) => i.toDouble)
<console>:12: error: could not find implicit value for parameter lub: shapeless.LUBConstraint[B,Double]
isValidFun((i: Int) => i.toDouble)
^
(4)
Now we still need to extract the arity somehow. On the type level this would be Length which is provided for HList. To get a runtime value, another type class ToInt is needed.
Here is the final function:
import shapeless._
def doubleFunArity[A, B <: HList, C <: Nat](fun: A)(implicit
fnh: FnHLister[A] { type Result = Double; type Args = B },
lub: LUBConstraint[B, Double],
len: Length[B] { type Out = C },
res: ToInt[C]
): Int = res()
Test:
scala> doubleFunArity(math.sqrt _)
res15: Int = 1
scala> doubleFunArity(math.random _)
res16: Int = 0
scala> val g: (Double, Double) => Double = math.max _
g: (Double, Double) => Double = <function2>
scala> doubleFunArity(g)
res17: Int = 2
Note that unfortunately many math operations are overloaded, and without strong type constraint, Scala will not give you the Double version automatically, but will use the Int version for some reason:
scala> math.max _
res18: (Int, Int) => Int = <function2>
So I need the indirection math.max _: ((Double, Double) => Double) to make this work.
Not saying that this is the best way to do it in your concrete case, but I think it was a fun exploration.
Probably the easiest solution is to use overloading as
def f(g: () => Double) = 0;
def f(g: (Double) => Double) = 1;
def f(g: (Double, Double) => Double) = 2;
def f(g: (Double, Double, Double) => Double) = 2;
// ...
println(f(Math.pow _));
println(f(Math.sin _));
(You can't check function argument/return types at run time due to type erasure, so I believe you can't create a fully generic function that would satisfy your requirements.)