You're right to be confused! The lens composition actually does work in the order you expected - colorsLens first, then semanticLens, etc., ending with hoverLens.
The reason it looks backwards is that R.compose reads right-to-left for regular functions, but with lenses it's different:
When you compose lenses with R.compose, they execute in left-to-right order (the order written):
colorsLens- focus ontheme.colorssemanticLens- within that, focus onsemanticstatesLens- within that, focus onstateserrorLens- within that, focus onerrorhoverLens- within that, focus onhover
This is the intuitive order - you're drilling down through nested properties.
If you want the visual order to match the execution order more clearly, you can use R.pipe instead:
const errorHoverLens = R.pipe(
colorsLens,
semanticLens,
statesLens,
errorLens,
hoverLens
);Both work identically for lenses! R.pipe just makes it more obvious that you're going left-to-right.
Lenses have a special property: their composition works the same in both directions because they're bidirectional (get and set). The getter travels down the path, and the setter travels back up.