Export inclusiveLowerBound / inclusiveUpperBound from PlutusLedgerApi.V1.Interval (and the Data variant)
Both PlutusLedgerApi.V1.Interval and PlutusLedgerApi.V1.Data.Interval define a pair of helpers that normalise LowerBound / UpperBound values into an equivalent inclusive Extended a:
inclusiveLowerBound :: Enum a => LowerBound a -> Extended a
inclusiveUpperBound :: Enum a => UpperBound a -> Extended a
They are used internally by the Eq/Ord instances for the bound types and by isEmpty, but they are not in the export list, so downstream validator code cannot reach them. Meanwhile, the symmetric constructors (lowerBound, upperBound, strictLowerBound, strictUpperBound) are all exported.
Writing a spending validator that treats the lower bound of txInfoValidRange as "current time" is a common pattern. Without the helper, every validator ends up reinventing the same normalisation by pattern-matching on the Closure flag:
lowerBoundTime :: POSIXTimeRange -> POSIXTime
lowerBoundTime (Interval (LowerBound (Finite t) True) _) = t
lowerBoundTime (Interval (LowerBound (Finite (POSIXTime t)) False) _) = POSIXTime (t + 1)
lowerBoundTime _ = traceError "Time range not Finite"
Exporting inclusiveLowerBound / inclusiveUpperBound would let the same code read:
lowerBoundTime :: POSIXTimeRange -> POSIXTime
lowerBoundTime (Interval lb _) = case inclusiveLowerBound lb of
Finite t -> t
_ -> traceError "Time range not Finite"
Proposal
Add inclusiveLowerBound and inclusiveUpperBound to the export lists of:
PlutusLedgerApi.V1.Interval
PlutusLedgerApi.V1.Data.Interval
and, by extension, to whatever re-export chains the module participates in (PlutusLedgerApi.V1, V2, V3, and the Data counterparts).
Rationale
- Public API parity with
lowerBound / strictLowerBound / upperBound / strictUpperBound, which are exported.
- Removes a small copy-pasta burden from validator authors and keeps the normalisation behaviour consistent with the library's internal definition.
- Pure addition — no existing code breaks.
Context
Ran into this while writing a reference HTLC validator for UPLC-CAPE; ended up open-coding the helper. Happy to open the PR if the proposal sounds reasonable.
Export
inclusiveLowerBound/inclusiveUpperBoundfromPlutusLedgerApi.V1.Interval(and theDatavariant)Both
PlutusLedgerApi.V1.IntervalandPlutusLedgerApi.V1.Data.Intervaldefine a pair of helpers that normaliseLowerBound/UpperBoundvalues into an equivalent inclusiveExtended a:inclusiveLowerBound :: Enum a => LowerBound a -> Extended ainclusiveUpperBound :: Enum a => UpperBound a -> Extended aThey are used internally by the
Eq/Ordinstances for the bound types and byisEmpty, but they are not in the export list, so downstream validator code cannot reach them. Meanwhile, the symmetric constructors (lowerBound,upperBound,strictLowerBound,strictUpperBound) are all exported.Writing a spending validator that treats the lower bound of
txInfoValidRangeas "current time" is a common pattern. Without the helper, every validator ends up reinventing the same normalisation by pattern-matching on theClosureflag:Exporting
inclusiveLowerBound/inclusiveUpperBoundwould let the same code read:Proposal
Add
inclusiveLowerBoundandinclusiveUpperBoundto the export lists of:PlutusLedgerApi.V1.IntervalPlutusLedgerApi.V1.Data.Intervaland, by extension, to whatever re-export chains the module participates in (
PlutusLedgerApi.V1,V2,V3, and theDatacounterparts).Rationale
lowerBound/strictLowerBound/upperBound/strictUpperBound, which are exported.Context
Ran into this while writing a reference HTLC validator for UPLC-CAPE; ended up open-coding the helper. Happy to open the PR if the proposal sounds reasonable.