Skip to content

Commit d7036ae

Browse files
claudehyperpolymath
authored andcommitted
proof(solo-core): coherent additive product & (TWith) — F1.4 phase 3a
Replaces the incoherent `TPair` with the genuine additive product `TWith` (a & b). The old `Pair` split usage at introduction (the (X) multiplicative cost) yet eliminated by projection (the & additive payoff), making it neither product and strictly weaker than both — sound under the affine kernel but the wrong product. `TWith` introduces under SHARED usage (both components typed with the SAME D, no uadd): only one component survives Fst/Snd elimination, so reusing a linear resource across the two components is safe. The multiplicative product (X) (TTensor + let-pair) is deferred to a follow-up (user steer: "additive & first"). * Syntax.v TPair->TWith, Pair->With (shift/subst updated). * Typing.v T_With shares D (drops D1/D2/uadd); T_Fst/T_Snd retargeted to TWith. * Soundness.v VWith / S_With1 / S_With2 / S_Fst / S_Snd / canon_with; progress With-intro case simplified (no split to clear). Verification: full chain compiles under Coq 8.18; `progress` remains "Closed under the global context" (zero axioms, zero admits). NOTE: the Idris twin keeps `Pair`/`TPair` for now — Coq/Idris product naming diverges until the dual-track parity pass (phase 5). The Rust checker's product handling should follow the &/(X) split too.
1 parent 47303fa commit d7036ae

3 files changed

Lines changed: 45 additions & 34 deletions

File tree

proofs/verification/coq/solo-core/Soundness.v

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ Require Import Typing.
3535
Inductive value : tm -> Prop :=
3636
| VUnit : value UnitT
3737
| VLam : forall q a t, value (Lam q a t)
38-
| VPair : forall t1 t2, value t1 -> value t2 -> value (Pair t1 t2)
38+
| VWith : forall t1 t2, value t1 -> value t2 -> value (With t1 t2)
3939
| VInl : forall b t, value t -> value (Inl b t)
4040
| VInr : forall a t, value t -> value (Inr a t)
4141
(* an echo with a fully-evaluated residue is a value; [Weaken] is
@@ -54,9 +54,9 @@ Inductive step : tm -> tm -> Prop :=
5454
| S_App : forall q a t v,
5555
value v -> step (App (Lam q a t) v) (subst0 v t)
5656
| S_Fst : forall v1 v2,
57-
value v1 -> value v2 -> step (Fst (Pair v1 v2)) v1
57+
value v1 -> value v2 -> step (Fst (With v1 v2)) v1
5858
| S_Snd : forall v1 v2,
59-
value v1 -> value v2 -> step (Snd (Pair v1 v2)) v2
59+
value v1 -> value v2 -> step (Snd (With v1 v2)) v2
6060
| S_CaseL : forall b v tL tR,
6161
value v -> step (Case (Inl b v) tL tR) (subst0 v tL)
6262
| S_CaseR : forall a v tL tR,
@@ -68,10 +68,10 @@ Inductive step : tm -> tm -> Prop :=
6868
step t1 t1' -> step (App t1 t2) (App t1' t2)
6969
| S_App2 : forall v1 t2 t2',
7070
value v1 -> step t2 t2' -> step (App v1 t2) (App v1 t2')
71-
| S_Pair1 : forall t1 t1' t2,
72-
step t1 t1' -> step (Pair t1 t2) (Pair t1' t2)
73-
| S_Pair2 : forall v1 t2 t2',
74-
value v1 -> step t2 t2' -> step (Pair v1 t2) (Pair v1 t2')
71+
| S_With1 : forall t1 t1' t2,
72+
step t1 t1' -> step (With t1 t2) (With t1' t2)
73+
| S_With2 : forall v1 t2 t2',
74+
value v1 -> step t2 t2' -> step (With v1 t2) (With v1 t2')
7575
| S_Fst1 : forall t t',
7676
step t t' -> step (Fst t) (Fst t')
7777
| S_Snd1 : forall t t',
@@ -164,9 +164,9 @@ Proof.
164164
- inversion Ht.
165165
Qed.
166166

167-
Lemma canon_pair : forall a b v,
168-
value v -> has_type TEmpty UEmpty v (TPair a b) ->
169-
exists v1 v2, v = Pair v1 v2 /\ value v1 /\ value v2.
167+
Lemma canon_with : forall a b v,
168+
value v -> has_type TEmpty UEmpty v (TWith a b) ->
169+
exists v1 v2, v = With v1 v2 /\ value v1 /\ value v2.
170170
Proof.
171171
intros a b v Hv Ht.
172172
destruct Hv as [ | q0 a0 tb | u1 u2 Hu1 Hu2 | b0 u0 Hu0 | a0 u0 Hu0
@@ -223,7 +223,7 @@ Proof.
223223
| (* UnitT *)
224224
| q tyL t1 IHt1 (* Lam *)
225225
| t1 IHt1 t2 IHt2 (* App *)
226-
| t1 IHt1 t2 IHt2 (* Pair *)
226+
| t1 IHt1 t2 IHt2 (* With *)
227227
| t1 IHt1 (* Fst *)
228228
| t1 IHt1 (* Snd *)
229229
| bAnn t1 IHt1 (* Inl *)
@@ -257,32 +257,33 @@ Proof.
257257
end
258258
end.
259259

260-
- (* Pair t1 t2 *)
261-
inversion Ht; subst; empty_uvec.
260+
- (* With t1 t2 : additive pair — a value once both components are.
261+
T_With shares usage (no split), so nothing to clear here. *)
262+
inversion Ht; subst.
262263
match goal with HT1 : has_type TEmpty UEmpty t1 _ |- _ =>
263264
match goal with HT2 : has_type TEmpty UEmpty t2 _ |- _ =>
264265
destruct (IHt1 _ HT1) as [Hv1 | [t1' Hs1]];
265266
[ destruct (IHt2 _ HT2) as [Hv2 | [t2' Hs2]];
266-
[ left; apply VPair; assumption
267-
| right; exists (Pair t1 t2'); apply S_Pair2; [exact Hv1 | exact Hs2] ]
268-
| right; exists (Pair t1' t2); apply S_Pair1; exact Hs1 ]
267+
[ left; apply VWith; assumption
268+
| right; exists (With t1 t2'); apply S_With2; [exact Hv1 | exact Hs2] ]
269+
| right; exists (With t1' t2); apply S_With1; exact Hs1 ]
269270
end
270271
end.
271272

272273
- (* Fst t1 *)
273-
inversion Ht; subst; empty_uvec.
274-
match goal with HT : has_type TEmpty UEmpty t1 (TPair _ _) |- _ =>
274+
inversion Ht; subst.
275+
match goal with HT : has_type TEmpty UEmpty t1 (TWith _ _) |- _ =>
275276
destruct (IHt1 _ HT) as [Hv | [t1' Hs]];
276-
[ destruct (canon_pair _ _ _ Hv HT) as [v1 [v2 [Heqv [Hv1 Hv2]]]]; subst t1;
277+
[ destruct (canon_with _ _ _ Hv HT) as [v1 [v2 [Heqv [Hv1 Hv2]]]]; subst t1;
277278
right; exists v1; apply S_Fst; [exact Hv1 | exact Hv2]
278279
| right; exists (Fst t1'); apply S_Fst1; exact Hs ]
279280
end.
280281

281282
- (* Snd t1 *)
282-
inversion Ht; subst; empty_uvec.
283-
match goal with HT : has_type TEmpty UEmpty t1 (TPair _ _) |- _ =>
283+
inversion Ht; subst.
284+
match goal with HT : has_type TEmpty UEmpty t1 (TWith _ _) |- _ =>
284285
destruct (IHt1 _ HT) as [Hv | [t1' Hs]];
285-
[ destruct (canon_pair _ _ _ Hv HT) as [v1 [v2 [Heqv [Hv1 Hv2]]]]; subst t1;
286+
[ destruct (canon_with _ _ _ Hv HT) as [v1 [v2 [Heqv [Hv1 Hv2]]]]; subst t1;
286287
right; exists v2; apply S_Snd; [exact Hv1 | exact Hv2]
287288
| right; exists (Snd t1'); apply S_Snd1; exact Hs ]
288289
end.

proofs/verification/coq/solo-core/Syntax.v

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
(* ========================================================== *)
55
(* my-lang Solo core: syntax (Coq twin of Syntax.idr) *)
66
(* *)
7-
(* Simply-typed lambda calculus + Unit + pairs + sums + let, *)
7+
(* Simply-typed lambda calculus + Unit + additive pairs (&) + *)
8+
(* sums + let, *)
89
(* every binder annotated by a QTT quantity. de Bruijn terms. *)
910
(* ========================================================== *)
1011

@@ -16,7 +17,10 @@ Require Import EchoMode.
1617

1718
Inductive ty : Type :=
1819
| TUnit : ty
19-
| TPair : ty -> ty -> ty
20+
| TWith : ty -> ty -> ty (* additive product a & b (shared usage,
21+
projected by Fst/Snd). The multiplicative
22+
product a (X) b is deferred to a
23+
follow-up (TTensor + let-pair). *)
2024
| TSum : ty -> ty -> ty
2125
| TArr : Q -> ty -> ty -> ty (* (q x : a) -> b *)
2226
| TEcho : Mode -> ty -> ty -> ty. (* echo residue: [m] Echo<a => b> *)
@@ -28,7 +32,7 @@ Inductive tm : Type :=
2832
| UnitT : tm
2933
| Lam : Q -> ty -> tm -> tm
3034
| App : tm -> tm -> tm
31-
| Pair : tm -> tm -> tm
35+
| With : tm -> tm -> tm (* additive pair <t1, t2> : a & b *)
3236
| Fst : tm -> tm
3337
| Snd : tm -> tm
3438
| Inl : ty -> tm -> tm (* annotation = the other summand *)
@@ -64,7 +68,7 @@ Fixpoint shift (c : nat) (t : tm) : tm :=
6468
| UnitT => UnitT
6569
| Lam q a t1 => Lam q a (shift (S c) t1)
6670
| App t1 t2 => App (shift c t1) (shift c t2)
67-
| Pair t1 t2 => Pair (shift c t1) (shift c t2)
71+
| With t1 t2 => With (shift c t1) (shift c t2)
6872
| Fst t1 => Fst (shift c t1)
6973
| Snd t1 => Snd (shift c t1)
7074
| Inl b t1 => Inl b (shift c t1)
@@ -90,7 +94,7 @@ Fixpoint subst_at (j : nat) (u : tm) (t : tm) : tm :=
9094
| UnitT => UnitT
9195
| Lam q a t1 => Lam q a (subst_at (S j) (shift 0 u) t1)
9296
| App t1 t2 => App (subst_at j u t1) (subst_at j u t2)
93-
| Pair t1 t2 => Pair (subst_at j u t1) (subst_at j u t2)
97+
| With t1 t2 => With (subst_at j u t1) (subst_at j u t2)
9498
| Fst t1 => Fst (subst_at j u t1)
9599
| Snd t1 => Snd (subst_at j u t1)
96100
| Inl b t1 => Inl b (subst_at j u t1)

proofs/verification/coq/solo-core/Typing.v

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -63,18 +63,24 @@ Inductive has_type : tctx -> uvec -> tm -> ty -> Prop :=
6363
uadd D1 (uscale q D2) = Some D ->
6464
has_type G D (App t1 t2) b
6565

66-
| T_Pair : forall G D D1 D2 a b t1 t2,
67-
has_type G D1 t1 a ->
68-
has_type G D2 t2 b ->
69-
uadd D1 D2 = Some D ->
70-
has_type G D (Pair t1 t2) (TPair a b)
66+
(* Additive product a & b (the coherent additive pair). Both
67+
components are typed under the SAME usage [D] — NOT split — because
68+
only one component ever survives elimination (Fst / Snd), so reusing
69+
a linear resource across the two components is safe. This is the
70+
genuine `&`; the earlier conflated `Pair` split usage at intro yet
71+
projected at elim, making it neither `&` nor `(X)` and strictly
72+
weaker than both. *)
73+
| T_With : forall G D a b t1 t2,
74+
has_type G D t1 a ->
75+
has_type G D t2 b ->
76+
has_type G D (With t1 t2) (TWith a b)
7177

7278
| T_Fst : forall G D a b t,
73-
has_type G D t (TPair a b) ->
79+
has_type G D t (TWith a b) ->
7480
has_type G D (Fst t) a
7581

7682
| T_Snd : forall G D a b t,
77-
has_type G D t (TPair a b) ->
83+
has_type G D t (TWith a b) ->
7884
has_type G D (Snd t) b
7985

8086
| T_Inl : forall G D a b t,

0 commit comments

Comments
 (0)