Skip to content

Replace Ord instance with helper#24

Open
ninioArtillero wants to merge 1 commit intoseereason:masterfrom
tweag:na/ord-instance
Open

Replace Ord instance with helper#24
ninioArtillero wants to merge 1 commit intoseereason:masterfrom
tweag:na/ord-instance

Conversation

@ninioArtillero
Copy link
Copy Markdown
Contributor

@ninioArtillero ninioArtillero commented May 5, 2026

Fixes #22

In Data.Algorithm.Diff, the internal type DL (D-path Location) carries the coordinates (poi, poj) of a wave-front node in the Myers edit graph and the edit trace accumulated so far. An Ord instance is defined solely to support a single call to max inside pairMaxes (within dstep), where two candidate D-paths competing for the same k-diagonal must be resolved in favour of the furthest-reaching one.

This PR removes this unlawful Ord instance in favor of a furthestReaching helper, documented with its call site preconditions, and renames pairMaxes to resolveCandidates.

A look into the algorithm

Disclaimer: abuse of notation ahead.

In the Myers algorithm, on any given k-diagonal k = i - j where i and j are coordinates, the furthest-reaching endpoint is the one with the largest i (equivalently, the largest j, since j = i - k). The else branch (poi x <= poi y) in the Ord instance definition implements exactly that. The argument is that this is the only relevant comparison when choosing a "better candidate" within this implementation, so that max x y effectively returns whichever has the larger poi.

As used within ses by calling dstep on single node list, pairMaxes always pairs exactly two candidates that target the same k-diagonal: one arriving via an F-move from diagonal k - 1, the other via an S-move from diagonal k + 1 (cf section 3 lemma 2 in the paper). After addsnake extends both along their (shared) diagonal, if they end up with the same poi, they necessarily also have the same poj (again, because both sit on the same diagonal: poj = poi - k). So when poi x == poi y the instance evaluates poj x > poj y, resulting always in False (which does not matter as max x y can equally return either value in this scenario). The reversed poj comparison can be understood as an ad-hoc tie-breaker that is only exercised in case of equality of both coordinates. Put bluntly, the equal-poi branch in the instance definition is a confusing artifact, and AFAICT not a deliberate encoding of any algorithmic property.

Rationale on the proposed change

Changing poj x > poj y to poj x >= poj y restores reflexivity (and lawfulness of the instance) with a one-character edit, nevertheless I propose removing it in favor of a helper because

  1. The resulting ordering is still semantically confusing. The Ord instance reverses poj within each poi-equivalence class, which is not a natural lexicographic ordering on coordinates. Anyone reading the code later must puzzle out why the ordering is inverted in one component.
  2. Having a degraded (purposeless) case in a typeclass instance definition is misleading as it carries expectations of lawfulness and generality.
  3. A named helper is self-documenting. A function called furthestReaching makes the algorithmic intent obvious.

@ninioArtillero ninioArtillero marked this pull request as ready for review May 6, 2026 15:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fix unlawful instance Ord DL

1 participant