Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala: Pass curried function as parameter

Is it possible to do something like the following?

def takeCurriedFnAsArg(f: (Int)(implicit MyClass) => Result)
like image 680
Prasanna Avatar asked Oct 26 '13 17:10

Prasanna


People also ask

How do you pass parameters to a Scala function?

Scala - Functions with Named Arguments Named arguments allow you to pass arguments to a function in a different order. The syntax is simply that each argument is preceded by a parameter name and an equals sign. Try the following program, it is a simple example to show the functions with named arguments.

What is curried function in Scala?

Currying is the process of converting a function with multiple arguments into a sequence of functions that take one argument. Each function returns another function that consumes the following argument.

What is the meaning of => in Scala?

=> is syntactic sugar for creating instances of functions. Recall that every function in scala is an instance of a class. For example, the type Int => String , is equivalent to the type Function1[Int,String] i.e. a function that takes an argument of type Int and returns a String .

What is benefit of currying in Scala?

Advantages of Currying Function in Scala One benefit is that Scala currying makes creating anonymous functions easier. Scala Currying also makes it easier to pass around a function as a first-class object. You can keep applying parameters when you find them.


1 Answers

Yes, it is possible.

When you have the second curried parameter marked as implicit, the function seems to be not of type

Int => (MyClass => Result) => ResultOfFunction 

which it would be if the curried higher order function parameter was a regular parameter; instead, it looks like this:

Int => ResultOfFunction

Here's a quick example:

scala> def curriedFn(i : Int)(implicit func : String => Int) : Boolean = (i + func("test!")) % 2 == 0
curriedFn: (i: Int)(implicit func: String => Int)Boolean

scala> implicit val fn : String => Int = s => s.length
fn: String => Int = <function1>

scala> curriedFn _
res4: Int => Boolean = <function1>

As you can see, the implicit parameter got 'eliminated'. Why and how? That's a question for someone more knowledgeable than me. If I had to guess, I'd say the compiler directly substitutes the parameter with the implicit value, but that might very well be false.

Anyway, digressions aside, here's an example very relevant to your situation:

scala> def foo(func : Int => Boolean) = if(func(3)) "True!" else "False!"
foo: (func: Int => Boolean)String

scala> foo(curriedFn)
res2: String = True!

Now if the second function parameter wasn't implicit:

scala> def curriedNonImplicit(i : Int)(fn : String => Int) : Boolean = (i + fn("test!")) % 2 == 0
curriedNonImplicit: (i: Int)(fn: String => Int)Boolean

scala> curriedNonImplicit _
res5: Int => ((String => Int) => Boolean) = <function1>

As you can see, the type of the function is a bit different. That means that the solution will look different too:

scala> def baz(func : Int => (String => Int) => Boolean) = if(func(3)(s => s.length)) "True!" else "False!"
baz: (func: Int => ((String => Int) => Boolean))String

scala> baz(curriedNonImplicit)
res6: String = True!

You have to specify the function directly inside the method, as it wasn't implicitly provided before.

like image 190
Patryk Ćwiek Avatar answered Nov 04 '22 05:11

Patryk Ćwiek