I have several generic functions with the same signature:
def f1[A, B](v: A, f: (A, B) => B): B = ...
def f2[A, B](v: A, f: (A, B) => B): B = ...
And I need to define a function g
that can accept any of these functions (f1
f2
):
def g(f: ????) = ...
g
internally uses multiple argument types, so I can not parameterize it like that:
def g[A, B](f: (A, (A, B) => B) => B) = ...
There isn't really a much better way to do it in Scala 2. Although your solution is a bit strange because FunctionHolder
's apply
method will return a function object and doesn't accept any arguments itself – that's a bit more complicated than it needs to be. So you can do this instead:
trait FunctionHolder {
def apply[A, B](v: A, f: (A, B) => B): B
}
def g(f: FunctionHolder) = …
But this isn't really all that much better.
In Scala 3, there are polymorphic function types to do this in a cleaner way:
def g(f: [A, B] => (A, (A, B) => B) => B) = …
That said, I'm not convinced that that type signature is really what you want. Remember, when you define a function with type parameters, it needs to work for all possible type parameters that the user might supply. This can't be done for this signature…
def f1[A, B](v: A, f: (A, B) => B): B
… because when I have a function like that, I can easily write an expression of type Nothing
:
f1[Unit, Nothing]((), (a: Unit, b: Nothing) => b)
and it's not possible to write an expression of type Nothing
unless you cheat (e. g. throw an exception or enter an infinite loop or something like that). So the type signature tells me you're cheating 😉
If you want to know more about this kind of reasoning, search for “Theorems for free!”
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With