Prasanna
Prasanna

Reputation: 3771

Scala: Pass curried function as parameter

Is it possible to do something like the following?

def takeCurriedFnAsArg(f: (Int)(implicit MyClass) => Result)

Upvotes: 7

Views: 2627

Answers (1)

Patryk Ćwiek
Patryk Ćwiek

Reputation: 14318

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.

Upvotes: 12

Related Questions