To illustrate my point, here an example:
abstract class Wrapper[A](wrapped: A) {
protected def someCondition: Boolean
def fold[B](whenTrue: => B)(whenFalse: => B): B =
if (someCondition) whenTrue else whenFalse
}
I’m trying to add a fold method based on an arbitrary condition defined on a wrapped type A. The problem with the code above is that this wouldn’t compile, although it could conceivably return Any:
wrapper.fold("hi")(42)
because by the time the compiler reaches the second parameter list, B has already been inferred to be String. Suppose we don’t want to have to write the type annotation. We can try changing fold to this:
def fold[B, B0 >: B](whenTrue: => B)(whenFalse: => B0): B0
but this also doesn’t work, since B0 has already been resolved as String at the end of the first parameter list, although it doesn’t appear in it at all! The simple solution, of course, is to have a single parameter list, but f the sake of the example, let’s say I want to keep the two parameter lists and try to make it work… Ideally, we should be able to delay the resolution of B0. It would be great if we could write something like this:
def fold[B](whenTrue: => B)[B0 >: B](whenFalse: => B0): B0
But unfortunately this doesn’t work. Are there any workarounds?
(I’m providing a first answer, but I’m of course looking for other workarounds as well.)
One solution is to create a temporary instance of a class that defines an
applymethod simulating the second parameter list, which has itself theB0type parameter:Then everything works correctly. Could we even imagine that
def fold[B](whenTrue: => B)[B0 >: B](whenFalse: => B0): B0could be interpreted as syntactic sugar for this?…