Hi Luciano,
that’s a very interesting problem. The solution mostly involves sprinkling a few more types across your code. Despite that, you will still need to enable the AllowAmbiguousTypes language extension because the type parameter f only appears within the type class constraints.
First of all, you need to tell the compiler that you want to access the x field in updateInner's setField and getField:
updateInner : forall x f. (Functor f, HasField x Outer (f Inner)) => (Inner -> Inner) -> Outer -> Outer
updateInner fi o = setField @x (fmap fi (getField @x o)) o
Notice how we added @x type applications to setField and getField. For x to be in scope at these places, we need to explicitly introduce it (and also f) using the forall x f. abstraction in the type signature of updateInner. Having the x as the first type parameter makes call sites more convenient since you only have to provide the field name, as in updateInner @"a", and don’t need to provide the functor, for field a it would be Optional here. Thus, if we assume type Inner = Int, we can use updateInner like
incrementA : Outer -> Outer
incrementA outer = updateInner @"a" (\i -> i + 1) outer
I hope that solves your problem,
Martin.