Skip to content

Instantly share code, notes, and snippets.

@phyllisstein
Last active December 2, 2025 00:18
Show Gist options
  • Select an option

  • Save phyllisstein/c254d86818c7919b36d193b606cf1205 to your computer and use it in GitHub Desktop.

Select an option

Save phyllisstein/c254d86818c7919b36d193b606cf1205 to your computer and use it in GitHub Desktop.
Go go gadget idempotence

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:

How Lens Composition Works

When you compose lenses with R.compose, they execute in left-to-right order (the order written):

  1. colorsLens - focus on theme.colors
  2. semanticLens - within that, focus on semantic
  3. statesLens - within that, focus on states
  4. errorLens - within that, focus on error
  5. hoverLens - within that, focus on hover

This is the intuitive order - you're drilling down through nested properties.

Alternative: Use R.pipe for Clarity

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.

Why This Works

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment