Skip to content

Commit 40c702f

Browse files
hyperpolymathclaude
andcommitted
proof(SafeEmail): DISCHARGE combineValidValid via constructor pattern + Refl premise (proven#90 #107)
The OWED comment for `combineValidValid` accurately diagnosed the blocker (record-field projection of `(MkValidationResult ...).isValid` doesn't reduce when r1, r2 are universally quantified) AND suggested the discharge (case-split on r1, r2 to expose `MkValidationResult`). This PR applies that suggestion. DISCHARGE (one line): ```idris combineValidValid (MkValidationResult True _) (MkValidationResult True _) Refl Refl = Refl ``` The pattern `MkValidationResult True _` plus the `Refl` premise binds the `isValid` field to `True` at type-check time. With both fields True, `(combineResults r1 r2).isValid` reduces to `True && True = True` definitionally. The proof becomes `Refl`. Empirically verified at `/tmp/charrefl/src/TestEmail.idr` (isolated) and `/tmp/SafeEmailMinimal.idr` (against the actual proven ValidationResult / combineResults definitions). Note on local-vs-CI: the pre-existing `validResultIsValid` in the same module fails to compile locally (record-field projection through a `public export` top-level constant — same blocker family as the SafeCSV `defaultDelimiterIsComma` issue). This error does NOT reproduce in CI (PR #100 merged green with that proof). My change is purely additive and verifies in isolation against the same Idris2 0.8.0 toolchain. Zero `believe_me`/`postulate`/`idris_crash`. Refs proven#90 (Phase 3 OWED triage), proven#107 (overly-cautious OWED meta-issue). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 40b127f commit 40c702f

1 file changed

Lines changed: 10 additions & 15 deletions

File tree

src/Proven/SafeEmail/Proofs.idr

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -103,22 +103,17 @@ validResultIsValid = Refl
103103
issue.severity = Warning ->
104104
(addIssue issue validResult).isValid = True
105105

106-
||| OWED: combining two valid results yields a valid result. By the
107-
||| definition `combineResults r1 r2 = MkValidationResult
108-
||| (r1.isValid && r2.isValid) (r1.issues ++ r2.issues)`
109-
||| (Validation.idr L78-80), with `r1.isValid = True` and
110-
||| `r2.isValid = True` we get `True && True = True`. Held back by
111-
||| Idris2 0.8.0 not reducing the record-field projection
112-
||| `(MkValidationResult (r1.isValid && r2.isValid) _).isValid` to
113-
||| `r1.isValid && r2.isValid` by Refl when `r1`, `r2` are
114-
||| universally quantified (no constructor in normal form to fire
115-
||| the projector). Discharge by case-split on `r1`, `r2` to expose
116-
||| the `MkValidationResult` constructor, then `Refl` after the
117-
||| `True && True = True` rewrite.
106+
||| DISCHARGED: combining two valid results yields a valid result.
107+
||| The OWED comment suggested the discharge pattern: case-split on
108+
||| `r1`, `r2` to expose the `MkValidationResult` constructor, then
109+
||| pattern-match the `True` field through the premise's `Refl` to
110+
||| collapse `True && True` to `True` directly. Empirically verified
111+
||| at `/tmp/charrefl/src/TestEmail.idr`.
118112
public export
119-
0 combineValidValid : (r1, r2 : ValidationResult) ->
120-
r1.isValid = True -> r2.isValid = True ->
121-
(combineResults r1 r2).isValid = True
113+
combineValidValid : (r1, r2 : ValidationResult) ->
114+
r1.isValid = True -> r2.isValid = True ->
115+
(combineResults r1 r2).isValid = True
116+
combineValidValid (MkValidationResult True _) (MkValidationResult True _) Refl Refl = Refl
122117

123118
--------------------------------------------------------------------------------
124119
-- Email Structure Properties

0 commit comments

Comments
 (0)