Which brings me back to my original question - is there any way that the
type system could be enhanced, so that the compiler "understands" that Bar f
=> Foo f without being told so explicitly every time?
No. The point is, it's not simply a type annotation; it's a *value* (a dictionary) that must be carried along with the rest of the value somehow. The compiler can't always work out statically which instances need to be used with the affected value, so it has to be available at run time; the context is effectively declaring that the run-time dictionary is a required extra parameter. And it wouldn't really be workable for some types to secretly imply that extra parameter and others not.