Reputation: 3771
Is it possible to do something like the following?
def takeCurriedFnAsArg(f: (Int)(implicit MyClass) => Result)
Upvotes: 7
Views: 2627
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