Skip to content

Comments

Add deriveOrd for Plinth similar to deriving stock Ord#7580

Open
Unisay wants to merge 12 commits intomasterfrom
yura/derive_ord
Open

Add deriveOrd for Plinth similar to deriving stock Ord#7580
Unisay wants to merge 12 commits intomasterfrom
yura/derive_ord

Conversation

@Unisay
Copy link
Contributor

@Unisay Unisay commented Feb 9, 2026

Closes #7566
Depends on #7433

Recent Changes

  • CI fixes (46f5c32, 81e78de): Resolved nix hydra build failures by removing unused imports, fixing test warnings, adding Windows buildability guard for golden tests, and HLint suppressions

Problem

Writing PlutusTx.Ord instances by hand is tedious and error-prone. Unlike Haskell's deriving stock Ord, there's no automatic way to derive ordering for Plutus types.

Solution

Add PlutusTx.deriveOrd, a Template Haskell function that generates PlutusTx.Ord instances matching GHC's stock deriving behavior.

Implementation

  • PlutusTx.Ord.TH: TH splice that generates compare clauses:
    • Same-constructor: field-by-field comparison using (<>) on Ordering (left-to-right, short-circuit)
    • Cross-constructor: O(n) wildcard-based LT/GT clauses (constructors ordered by declaration)
    • INLINEABLE pragma for on-chain optimization
  • Standard library instances: deriveOrd for Bool, Maybe, Either, Ordering, [], tuples up to 26-arity
  • Ledger API replacements: Manual Ord instances replaced for V1.Extended and V3.ProtocolVersion

What's NOT replaced (custom semantics)

  • UpperBound/LowerBound — use inclusiveUpperBound/inclusiveLowerBound transformations
  • Rational — uses cross-multiplication comparison
  • asData types (e.g., V1D.Extended) — deriveOrd cannot see through BuiltinData wrappers

Tests

  • Unit tests: enum ordering, product comparison, newtype, large ADT (same/different constructors), recursive tree, void type
  • Golden tests (plutus-tx): SomeVeryLargeEnum, SomeProduct, PhantomADT, MyNewtype, SomeLargeADT, Tree, These
  • Golden tests (plutus-ledger-api): V1.Extended, V3.ProtocolVersion

@github-actions
Copy link
Contributor

github-actions bot commented Feb 9, 2026

Execution Budget Golden Diff

eb17481 (master) vs 98bca66

output

plutus-benchmark/coop/test/9.6/certMpBurning.golden.eval

Metric Old New Δ%
CPU 1_842_390_144 1_840_950_144 -0.08%
Memory 10_767_518 10_758_518 -0.08%
Flat Size 8_031 7_999 -0.40%

plutus-benchmark/coop/test/9.6/certMpMinting.golden.eval

Metric Old New Δ%
Flat Size 8_554 8_522 -0.37%

plutus-benchmark/coop/test/9.6/fsMpBurning.golden.eval

Metric Old New Δ%
CPU 221_742_924 220_142_924 -0.72%
Memory 1_160_875 1_150_875 -0.86%
Flat Size 7_395 7_362 -0.45%

plutus-benchmark/coop/test/9.6/fsMpMinting.golden.eval

Metric Old New Δ%
CPU 568_678_641 562_518_641 -1.08%
Memory 3_050_867 3_012_367 -1.26%
Flat Size 9_213 9_180 -0.36%

plutus-benchmark/nofib/test/9.6/clausify-F5.golden.eval

Metric Old New Δ%
Flat Size 1_477 1_653 +11.92%

plutus-benchmark/nofib/test/9.6/knights10-4x4.golden.eval

Metric Old New Δ%
CPU 1_023_470_754 1_032_496_114 +0.88%
Memory 5_395_058 5_446_674 +0.96%
Flat Size 1_674 1_833 +9.50%

This comment will get updated when changes are made.

@Unisay Unisay self-assigned this Feb 9, 2026
@Unisay Unisay force-pushed the bezirg/derive_eq branch 2 times, most recently from 3b9aaed to f1817ba Compare February 20, 2026 09:25
Base automatically changed from bezirg/derive_eq to master February 20, 2026 10:30
bezirg and others added 9 commits February 20, 2026 13:55
Add deriveOrd tests

Make deriving Ord phantom types work

Fixes
Add MyNewtype, SomeLargeADT, Tree, and These golden tests to match
deriveEq coverage. Add unit tests for new types including newtype,
large ADT, and recursive tree comparisons.
Add Spec.Ord.Golden module with golden tests for V1.Extended and
V3.ProtocolVersion types that use deriveOrd. Wire into test suite.
…ration

Use wildcard patterns for cross-constructor comparisons instead of
generating explicit clauses for every pair. This reduces generated
clauses from O(n^2) to O(n) for types with n constructors.
Remove unused import of PlutusTx.Either from Ord.Class, prefix
unused record fields with underscore in test ADT to satisfy
-Werror, and disable plutus-ledger-api-test on Windows where
the diff command is unavailable for golden tests.
Apply fourmolu formatting to Ord.Class module header and imports.
Add HLint suppressions for deliberately inefficient max/min/compare
implementations that match GHC's default definitions for consistency.
Add missing import of PlutusTx.Eq to bring Eq instances into scope,
which are required as superclass constraints for deriveOrd.

This fixes build failures where deriveOrd couldn't deduce Eq instances
for types like [], Bool, Maybe, etc.

Fixes Hydra CI build failures on both darwin and linux platforms.
@Unisay Unisay marked this pull request as ready for review February 20, 2026 13:00
GHC 9.12 resolves TH-quoted '(<>) to GHC.Internal.Base.<> instead of
GHC.Base.<>, causing golden test mismatches across GHC versions. Replace
with a named thenCmp helper in PlutusTx.Ord.Class for stable output.

Also replace HS.tail with HS.drop 1 in tests to fix -Wx-partial error
on GHC 9.12.
The switch from (<>) to thenCmp in deriveOrd-generated code changes
the compiled PIR/UPLC output for clausify and knights benchmarks.
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.

Add TH deriving for Plinth's Ord

2 participants