`1 + 1` where `(+)` is `GHC.TypeNats.+`, the viewer will stop at
`+` rather than producing `2`.
-- **`UndecidableInstances` / cyclic reduction.** The reducer is
- iterative, not fixed-point: each call visits the structure once and
- then bails. We don't loop forever on a divergent chain. In practice
- this means a circular family like `type instance F a = G a` /
- `type instance G a = F a` shows up as two separate fam-instance
- nodes pointing at each other via `fiRhs` references, but no edge in
- the resolution-chain layer.
+- **`UndecidableInstances` / cyclic reduction.** `reduceTypeArg`
+ recurses on `applySubst(fi.fiRhs, subst)` after a matching
+ fam-instance is found, so a `type instance F a = G a` / `type
+ instance G a = F a` pair *would* loop forever if it weren't for
+ the fact that each step requires structural progress (the RHS
+ isn't structurally equal to the LHS). In practice such a circular
+ pair shows up as two separate fam-instance nodes pointing at each
+ other via `fiRhs` references, with no resolution-chain edge.
+
+- **Data fam-instances are skipped by `reduceTypeArg` entirely.**
+ After the data-family R: rewrite at extraction time (see
+ `Classgraph.Extract`'s `typeArg`), a data fam-instance's `fiRhs`
+ is structurally equal to its LHS — for `data instance Crate Int`,
+ `fiRhs = FamilyApp Crate [Int]`. Reducing `FamilyApp Crate [Int]`
+ through that fam-instance just produces `FamilyApp Crate [Int]`
+ again, so naïvely recursing through it loops forever. The reducer
+ guards against this by skipping any fam-instance with
+ `fiIsData = true`; data-family use sites then fall through
+ unchanged and are surfaced by the predicate-node + chain machinery
+ as the use sites they actually are. The synthetic R: TyCon (the
+ pre-rewrite form) was opaque for the same reason — we just never
+ hit the loop because the rewriter wasn't yet circular.
So: *the data is deterministic and faithful, the chains are an honest
best-effort visualization*. When in doubt, the chain edges in the