The basic problem is one of time travel. Context variables work because you set them up before you ever call the function, because statement boundaries provide a sequence point.
my $FD is context = open($file);
So both sooner
see the value of $*FD
in the dynamic context. However, the type context of sooner
is not known when it is called, because it it provided by the binding in the later
call. (MMD only makes this worse, not just because you have multiple possible type contexts, but because the use of the actual return type for MMD introduces a chicken and egg problem.)
It would be possible to define a form of laziness that would at least let sooner() see the possibilities, and perhaps even negotiate a unification between the two lists of possibilities (the return possibilities and the binding possibilities). One could imagine that the want function actually takes a continuation, and returns that to be bound lazily, and then continues executing once it knows how it will be bound.
That could work directly for dispatch to an "only" version of later (assuming
you don't depend on side effects in sooner happening before the call to later).
For multiple dispatch we would presumably have to return (along with the continuation) some kind of list of possible return types for MMD to work with, or perhaps just the most general type, if we decide all coercion is to be managed by MMD rather than by want. Or we could take the approach you suggested and do the unification in sooner's switch statement, but then the call to sooner would be driven by the dispatcher, not by the actual binding.
But this is all conjectural, since at least for 6.0.0 we're aiming to create something implementable on platforms that have difficulty with time travel. There's nothing in the current design that exactly requires continuation support; even resumable exceptions are designed to work on systems without first class support for continuations (that is, we don't unwind the stack till after exception handlers are run, so resuming from an exception is just a return). Lazy lists can be emulated with closures and iterators.
So for now, we put our thumb on the scales in favor of multiple dispatch using a set of already-computed values of known type, and leave the door open for time travel in the future. We don't exactly know how to install a time-travel booth, but we're saving a spot for someone clever from the future to come back and install one for us, sooner or later. :-)