Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing functions for all applicable types around

Tags:

scala

I followed the advice found here to define a function called square, and then tried to pass it to a function called twice. The functions are defined like this:

 def square[T](n: T)(implicit numeric: Numeric[T]): T = numeric.times(n, n)
 def twice[T](f: (T) => T, a: T): T = f(f(a)) 

When calling twice(square, 2), the REPL spits out an error message:

scala> twice(square, 2)
<console>:8: error: could not find implicit value for parameter numeric: Numeric[T]
       twice(square, 2)
         ^

Anyone?

like image 588
Wilfred Springer Avatar asked Jan 04 '11 08:01

Wilfred Springer


People also ask

Is it possible to pass a function to another function?

Functions can be passed into other functions Functions, like any other object, can be passed as an argument to another function.

How to pass function argument in other function in c?

We cannot pass the function as an argument to another function. But we can pass the reference of a function as a parameter by using a function pointer. This process is known as call by reference as the function parameter is passed as a pointer that holds the address of arguments.

Can you pass a function as an argument to another function in Python?

Because functions are objects we can pass them as arguments to other functions. Functions that can accept other functions as arguments are also called higher-order functions.

Why do we pass parameters in function?

Parameters are essential to functions, because otherwise you can't give the function-machine an input.


2 Answers

I disagree with everyone here except Andrew Phillips. Well, everyone so far. :-) The problem is here:

def twice[T](f: (T) => T, a: T): T = f(f(a))

You expect, like newcomers to Scala often do, for Scala's compiler to take into account both parameters to twice to infer the correct types. Scala doesn't do that, though -- it only uses information from one parameter list to the next, but not from one parameter to the next. That mean the parameters f and a are analyzed independently, without having the advantage of knowing what the other is.

That means, for instance, that this works:

twice(square[Int], 2)

Now, if you break it down into two parameter lists, then it also works:

def twice[T](a: T)(f: (T) => T): T = f(f(a))
twice(2)(square)

So, basically, everything you were trying to do was correct and should work, except for the part that you expected one parameter to help figuring out the type of the other parameter (as you wrote it).

like image 131
Daniel C. Sobral Avatar answered Oct 05 '22 04:10

Daniel C. Sobral


Here's a session from the Scala REPL.

Welcome to Scala version 2.8.0.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_20).
Type in expressions to have them evaluated.
Type :help for more information.

scala> def square[T : Numeric](n: T) = implicitly[Numeric[T]].times(n, n)
square: [T](n: T)(implicit evidence$1: Numeric[T])T

scala> def twice2[T](f: T => T)(a: T) = f(f(a))
twice2: [T](f: (T) => T)(a: T)T

scala> twice2(square)(3)
<console>:8: error: could not find implicit value for evidence parameter of type
 Numeric[T]
       twice2(square)(3)
              ^

scala> def twice3[T](a: T, f: T => T) = f(f(a))
twice3: [T](a: T,f: (T) => T)T

scala> twice3(3, square)
<console>:8: error: could not find implicit value for evidence parameter of type
 Numeric[T]
       twice3(3, square)

scala> def twice[T](a: T)(f: T => T) = f(f(a))
twice: [T](a: T)(f: (T) => T)T

scala> twice(3)(square)
res0: Int = 81

So evidently the type of "twice(3)" needs to be known before the implicit can be resolved. I guess that makes sense, but I'd still be glad if a Scala guru could comment on this one...

like image 23
Andrew Phillips Avatar answered Oct 05 '22 03:10

Andrew Phillips