insertEffects: cache non-destructive mapEff/Sym instances for correct sharing

We had correctness issues due to the fact that each mapEff/Sym was
generating new symbols/effects. Now, a stack of caches is used to make
sure that for each map instance, we repeat all modifications to the same
symbol/effect ids. This is only relevant for non-destructive updates to
the tree which duplicate symbols/effects ie. lambda applications and
collection self substitution.

BTW, in order to apply lambdas throughout the AST correctly, we have to
cache those applications as well and replay them from cache as we go up
the tree. This is currently not implemented since we don't apply lambdas
globally anymore anyway, except for debugging.