Double-negation translation

From The Twelf Project
Jump to: navigation, search
This is Literate Twelf
Code: here
Status: %% OK %%
Output: here.

Intuitionistic logic

iprop : type.  %name iprop A'.

itop : iprop.
iand : iprop -> iprop -> iprop.
ibot : iprop.
ior  : iprop -> iprop -> iprop.
iimp : iprop -> iprop -> iprop.

%block ipb : block {X : iprop}.
%worlds (ipb) (iprop).

itrue : iprop -> type.

imt : itrue itop.
ipair : itrue A -> itrue B -> itrue (iand A B).
ifst : itrue (iand A B) -> itrue A.
isnd : itrue (iand A B) -> itrue B.
iabort : itrue ibot -> itrue C.
iinl  : itrue A -> itrue (ior A B). 
iinr  : itrue B -> itrue (ior A B). 
icase : itrue (ior A B) -> (itrue A -> itrue C) ->  (itrue B -> itrue C) -> itrue C.
ilam  : (itrue A -> itrue B) -> itrue (iimp A B).
iapp  : itrue (iimp A B) -> itrue A -> itrue B.

inot : iprop -> iprop = [A] iimp A ibot.
idn : iprop -> iprop = [A] (inot (inot A)).

dni : itrue A -> itrue (idn A) =
 [x : itrue A] (ilam [y : itrue (inot A)] (iapp y x)).

tne : itrue (idn (inot A)) -> itrue (inot A) =
 [x3 : itrue (inot (inot (inot A)))] 
   ilam [x : itrue A] 
     iapp x3 (ilam [y : itrue (inot A)] (iapp y x)).

distdnand : itrue (idn (iand A B)) -> itrue (iand (idn A) (idn B)) =
 [f] (ipair 
	(ilam [x : itrue (inot A)] iapp f (ilam [p] iapp x (ifst p)))
	(ilam [x : itrue (inot B)] iapp f (ilam [p] iapp x (isnd p)))
	).

dnebot : itrue (idn ibot) -> itrue ibot = [x] iapp x (ilam [x] x).
%abbrev dnetop : itrue (idn itop) -> itrue itop = [x] imt.

distdnimp : itrue (idn (iimp A B)) -> itrue (iimp (idn A) (idn B)) =
 [f] (ilam [x : itrue (idn A)] 
	(ilam [y : itrue (inot B)] 
	   iapp f 
	   (ilam [g : itrue (iimp A B)]
	      iapp x (ilam [z : itrue A] iapp y (iapp g z))))). 

%block itb : some {A : iprop} block {D : itrue A}.
%worlds (ipb | itb) (itrue _).

Classical logic

prop : type.  %name prop A.

top : prop.
and : prop -> prop -> prop.
bot : prop.
or  : prop -> prop -> prop.
imp : prop -> prop -> prop.
nbot : prop.
not : prop -> prop.

%block pb : block {X : prop}.
%worlds (pb) (prop).

conc : type.
true  : prop -> conc. %prefix 2 true.
false : prop -> conc. %prefix 2 false.
contra : conc. 

>> : conc -> type.  %prefix 3 >>.

mt : >> true top.
pair : >> true A -> >> true B -> >> true (and A B).
fst : >> true (and A B) -> >> true A.
snd : >> true (and A B) -> >> true B.
abort : >> true bot -> >> J.
inl  : >> true A -> >> true (or A B). 
inr  : >> true B -> >> true (or A B). 
case : >> true (or A B) -> (>> true A -> >> J) ->  (>> true B -> >> J) -> >> J.
lam  : (>> true A -> >> true B) -> >> true (imp A B).
app  : >> true (imp A B) -> >> true A -> >> true B.

%% anything follows from contradiction
cabort : >> contra -> >> J.

%% negative bottom
nboti : >> contra -> >> true nbot.
nbote : >> true nbot -> >> contra.

%% falsehood
cont  : (>> true A -> >> contra) -> >> false A.
throw : >> false A -> >> true A -> >> contra.

%% negation
noti    : >> false A -> >> true (not A).
notcase : >> true (not A) -> (>> false A -> >> J) -> >> J.                                       %% because not should be positive

%% letcc
letcc : (>> false A -> >> contra) -> >> true A.

%block tb : some {A : prop} block {D : >> true A}.
%block fb : some {A : prop} block {D : >> false A}.
%worlds (pb | tb | fb) (>> _).

iff  : prop -> prop -> prop = [A] [B] (and (imp A B) (imp B A)).
iffi : (>> true A -> >> true B) -> (>> true B -> >> true A) -> (>> true (iff A B)) 
 = [E1] [E2] (pair (lam E1) (lam E2)).
iffel : (>> true (iff A B)) -> (>> true A -> >> true B) 
 = [E1] [E2] (app (fst E1) E2).
iffer : (>> true (iff A B)) -> (>> true B -> >> true A) 
 = [E1] [E2] (app (snd E1) E2).

cdni : >> true A -> >> true (not (not A)) =
[x] (noti (cont [nx] (notcase nx [f] throw f x))).

cdne : >> true (not (not A)) -> >> true A =
[x] notcase x ([f] letcc [u] throw f (noti u)).

notimpbot : >> true (iff A B) -> >> true (iff (not A) (imp B bot)) =
[c] (iffi 
       ([x] notcase x ([f] (lam [y] (cabort (throw f (iffer c y))))))
       ([x] noti (cont [y] abort (app x (iffel c y))))).

notimpbot2 : >> true (iff (not (not A)) (imp (imp A bot) bot)) =
notimpbot (notimpbot (iffi ([x] x) ([x] x))).

Double-negation translation

This is essentially the Godel-Gentzen Negtive Translation. It differs only by De Morgan laws that are provable intuitionistically.

* : prop -> iprop -> type.
%mode * +A -A'.

*/top : * top itop.
*/and : * (and A B) (iand A' B')
	 <- * A A'
	 <- * B B'.
*/bot : * bot ibot.
*/or : * (or A B) (inot (inot (ior A' B')))
	 <- * A A'
	 <- * B B'.
*/imp : * (imp A B) (iimp A' B')
	 <- * A A'
	 <- * B B'.
*/nbot : * nbot ibot.
*/not  : * (not A) (inot A')
	  <- * A A'.

%block *b : block {X : prop} {X' : iprop} {_ : * X (inot (inot X'))}.
%worlds (*b) (* _ _).
%total A (* A _).
%unique * +A -1A'.

*tot : {A} * A A' -> type.
%mode *tot +A -D*.

%block *totb : block {X : prop} {X' : iprop} {D* : * X (idn X')} {_ : *tot X D*}.
%worlds (*totb) (*tot _ _).
%trustme %total {} (*tot _ _).  %% verified by %total above

id-iprop : iprop -> iprop -> type.
id-iprop/refl : id-iprop A A.

id-iprop-not-cong : id-iprop A' B' -> id-iprop (inot A') (inot B') -> type.
%mode id-iprop-not-cong +X1 -X2.
- : id-iprop-not-cong _ id-iprop/refl.
%worlds (ipb) (id-iprop-not-cong _ _).
%total {} (id-iprop-not-cong _ _).

*unique : * A A' -> * A B' -> id-iprop A' B' -> type.
%mode *unique +X1 +X2 -X3.
%worlds (*b) (*unique _ _ _).
%trustme %total {} (*unique _ _ _). %% verified by %unique above

itrue-respects-id : itrue A -> id-iprop A' A -> itrue A' -> type.
%mode itrue-respects-id +X1 +X2 -X3.
- : itrue-respects-id D _ D.
%worlds (itb | ipb) (itrue-respects-id _ _ _).
%total {} (itrue-respects-id _ _ _).

Double-negation elimination for the target of the translation

dne : * A A' -> (itrue (inot (inot A')) -> itrue A') -> type.
%mode dne +X1 -X2.

- : dne (*/and D*2 D*1) ([x] ipair (E1 (ifst (distdnand x))) (E2 (isnd (distdnand x))))
     <- dne D*1 E1
     <- dne D*2 E2.
- : dne */top ([x] imt).
- : dne (*/or _ _) [x] (tne x).
- : dne */bot  ([x] (dnebot x)).
- : dne */nbot  ([x] (dnebot x)).
- : dne (*/imp D*2 D*1) 
     ([x] (ilam [y] E2 (iapp (distdnimp x) (dni y))))
     <- dne D*2 E2.
- : dne (*/not D*) tne 
     <- dne D* E.

%block dneb : block {X : prop} {X' : iprop} {dx : * X (idn X')}
	       {_ : dne dx tne}.

%worlds (dneb | itb) (dne _ _).
%total D (dne D _).

Soundness

sound/true : >> true A -> * A A' -> itrue A' -> type.
%mode sound/true +X1 +X2 -X3.

sound/false : >> false A -> * A A' -> itrue (iimp A' ibot) -> type.
%mode sound/false +X1 +X2 -X3.

sound/contra : >> contra -> itrue ibot -> type.
%mode sound/contra +X1 -X3.

%% true

- : sound/true mt */top imt.
- : sound/true (pair E1 E2) (*/and D*2 D*1) (ipair E1' E2')
     <- sound/true E1 D*1 E1'
     <- sound/true E2 D*2 E2'.
- : sound/true (fst (E : >> true (and A1 A2))) D*1 (ifst E')
     <- *tot A2 D*2
     <- sound/true E (*/and D*2 D*1) E'.
- : sound/true (snd (E : >> true (and A1 A2))) D*2 (isnd E')
     <- *tot A1 D*1
     <- sound/true E (*/and D*2 D*1) E'.
- : sound/true ((abort E) : >> true C) D* (iabort E')
     <- sound/true E */bot E'.
- : sound/true ((inl E) : >> true (or A1 A2)) (*/or D*2 D*1) (dni (iinl E'))
     <- sound/true E D*1 E'.
- : sound/true ((inr E) : >> true (or A1 A2)) (*/or D*2 D*1) (dni (iinr E'))
     <- sound/true E D*2 E'.
- : sound/true (case (E : >> true (or A B)) E1 E2) D* 
     (Edne (ilam [f : itrue (inot C')] 
	      iapp E' (ilam [x : itrue (ior A' B')]
			 (icase x 
			    ([x1] iapp f (E1' x1)) 
			    ([x2] iapp f (E2' x2))))))
     <- *tot A D*A
     <- *tot B D*B
     <- sound/true E (*/or D*B D*A) E'
     <- ({x : >> true A} {x' : itrue A'} 
	   {_ : {A''} {D* : * A A''} {Did} {E''}
		 sound/true x D* E''
		 <- *unique D* D*A Did
		 <- itrue-respects-id x' Did E''}
	   sound/true (E1 x) D* (E1' x'))
     <- ({x : >> true B} {x' : itrue B'} 
	   {_ : {A''} {D* : * B A''} {Did} {E''}
		 sound/true x D* E''
		 <- *unique D* D*B Did
		 <- itrue-respects-id x' Did E''}
	   sound/true (E2 x) D* (E2' x'))
     <- dne D* Edne.
- : sound/true ((lam E) : >> true (imp A B)) (*/imp D* D*A) (ilam E')
     <- ({x : >> true A} {x' : itrue A'} 
	   {_ : {A''} {D* : * A A''} {Did} {E''}
		 sound/true x D* E''
		 <- *unique D* D*A Did
		 <- itrue-respects-id x' Did E''}
	   sound/true (E x) D* (E' x')).
- : sound/true (app E1 E2) D*B (iapp E1' E2')
     <- *tot A D*A
     <- sound/true E1 (*/imp D*B D*A) E1'
     <- sound/true  E2 D*A E2'.
- : sound/true ((cabort E) : >> true C) D* (iabort E')
     <- sound/contra E E'.
- : sound/true ((nboti E) : >> true nbot) */nbot (iabort E')
     <- sound/contra E E'.
- : sound/true ((noti E) : >> true (not A)) (*/not D*) E'
     <- sound/false E D* E'.
- : sound/true (notcase E1 E2) D*C (E2' E1')
     <- *tot A D*A 
     <- sound/true E1 (*/not (D*A : * A A')) E1'
     <- ({x : >> false A} {x' : itrue (inot A')} 
	   {_ : {A'' : iprop} {D* : * A A''} 
		 {Did : id-iprop A'' A'}
		 {Did' : id-iprop (inot A'') (inot A')}
		 {E'' : itrue (inot A'')}
		 sound/false x D* E''
		 <- *unique D* D*A Did
		 <- id-iprop-not-cong Did Did'
		 <- itrue-respects-id x' Did' E''}
	   sound/true (E2 x) D*C (E2' x')).
- : sound/true ((letcc E) : >> true A) D*A (Edne (ilam E'))
     <- ({x : >> false A} {x' : itrue (inot A')}  
	   {_ : {A'' : iprop} {D* : * A A''} 
		 {Did : id-iprop A'' A'}
		 {Did' : id-iprop (inot A'') (inot A')}
		 {E'' : itrue (inot A'')}
		 sound/false x D* E''
		 <- *unique D* D*A Did
		 <- id-iprop-not-cong Did Did'
		 <- itrue-respects-id x' Did' E''}
	   sound/contra (E x) (E' x'))
     <- dne D*A Edne.

%% false

- : sound/false ((cont E) : >> false A) D*A (ilam E')
     <-  ({x : >> true A} {x' : itrue A'} 
	    {_ : {A''} {D* : * A A''} {Did} {E''}
		  sound/true x D* E''
		  <- *unique D* D*A Did
		  <- itrue-respects-id x' Did E''}
	    sound/contra (E x) (E' x')).
- : sound/false (cabort E) D* (iabort E')
     <- sound/contra E E'.
- : sound/false (case (E : >> true (or A B)) E1 E2) D* 
     (ilam [c : itrue C]
	iapp E' (ilam [x]
		   (icase x 
		      ([x1] iapp (E1' x1) c) 
		      ([x2] iapp (E2' x2) c))))
     <- *tot _ D*A
     <- *tot _ D*B
     <- sound/true E (*/or D*B D*A) E'
     <- ({x : >> true A} {x' : itrue A'} 
	   {_ : {A''} {D* : * A A''} {Did} {E''}
		 sound/true x D* E''
		 <- *unique D* D*A Did
		 <- itrue-respects-id x' Did E''}
	   sound/false (E1 x) D* (E1' x'))
     <- ({x : >> true B} {x' : itrue B'} 
	   {_ : {A''} {D* : * B A''} {Did} {E''}
		 sound/true x D* E''
		 <- *unique D* D*B Did
		 <- itrue-respects-id x' Did E''}
	   sound/false (E2 x) D* (E2' x')).
- : sound/false ((abort E) : >> false C) D* (iabort E')
     <- sound/true E */bot E'.
- : sound/false (notcase E1 E2) D*C (E2' E1')
     <- *tot _ D*A
     <- sound/true E1 (*/not (D*A : * A A')) E1'
     <- ({x : >> false A} {x' : itrue (inot A')}  
	   {_ : {A'' : iprop} {D* : * A A''} 
		 {Did : id-iprop A'' A'}
		 {Did' : id-iprop (inot A'') (inot A')}
		 {E'' : itrue (inot A'')}
		 sound/false x D* E''
		 <- *unique D* D*A Did
		 <- id-iprop-not-cong Did Did'
		 <- itrue-respects-id x' Did' E''}
	   sound/false (E2 x) D*C (E2' x')).

%% contra 

- : sound/contra (throw E1 E2) (iapp E1' E2')
     <- *tot _ D*
     <- sound/true E2 D* E2'
     <- sound/false E1 D* E1'.
- : sound/contra (nbote E) E'
     <- sound/true E */nbot E'.
- : sound/contra (case E E1 E2) 
     (iapp E' (ilam [x] (icase x E1' E2')))
     <- *tot _ D*A
     <- *tot _ D*B
     <- sound/true E (*/or D*B D*A) E'
     <- ({x : >> true A} {x' : itrue A'} 
	   {_ : {A''} {D* : * A A''} {Did} {E''}
		 sound/true x D* E''
		 <- *unique D* D*A Did
		 <- itrue-respects-id x' Did E''}
	   sound/contra (E1 x) (E1' x'))
     <- ({x : >> true B} {x' : itrue B'}
	   {_ : {A''} {D* : * B A''} {Did} {E''}
		 sound/true x D* E''
		 <- *unique D* D*B Did
		 <- itrue-respects-id x' Did E''}
	   sound/contra (E2 x) (E2' x')).
- : sound/contra (abort E) (iabort E')
     <- sound/true E */bot E'.
- : sound/contra (cabort E) E'
     <- sound/contra E E'.
- : sound/contra (notcase E1 E2) (E2' E1')
     <- *tot _ D*A
     <- sound/true E1 (*/not (D*A : * A A')) E1'
     <- ({x : >> false A} {x' : itrue (inot A')}
	   {_ : {A'' : iprop} {D* : * A A''} 
		 {Did : id-iprop A'' A'}
		 {Did' : id-iprop (inot A'') (inot A')}
		 {E'' : itrue (inot A'')}
		 sound/false x D* E''
		 <- *unique D* D*A Did
		 <- id-iprop-not-cong Did Did'
		 <- itrue-respects-id x' Did' E''}
	   sound/contra (E2 x) (E2' x')).

%% uses a fancy variable case:
%block soundtb : some {A : prop} {A' : iprop} {Dx : * A A'}
		 block {x : >> true A} {x' : itrue A'} 
		  {_ : {A''} {D* : * A A''} {Did} {E''}
			sound/true x D* E''
			<- *unique D* Dx Did
			<- itrue-respects-id x' Did E''}.
%block soundfb : some {A : prop} {A' : iprop} {Dx : * A A'}
		 block {x : >> false A} {x' : itrue (inot A')} 
		  {_ : {A'' : iprop} {D* : * A A''} 
			{Did : id-iprop A'' A'}
			{Did' : id-iprop (inot A'') (inot A')}
			{E'' : itrue (inot A'')}
			sound/false x D* E''
			<- *unique D* Dx Did
			<- id-iprop-not-cong Did Did'
			<- itrue-respects-id x' Did' E''}.
%block soundpb : block {X : prop} {X' : iprop} {dx : * X (idn X')}
		  {_ : dne dx tne}
		  {_ : *tot X dx}.

%worlds (soundpb | soundtb | soundfb) (sound/true _ _ _) (sound/true _ _ _) (sound/false _ _ _) (sound/false _ _ _) (sound/contra _ _).
%total (D1 D4 D2 D5 D3) (sound/true D4 _ _) (sound/true D1 _ _) (sound/false D5 _ _) (sound/false D2 _ _) (sound/contra D3 _).

Completeness

Inclusion

Include intuitionistic props into classical. We need to define another translation because * is not total with the reverse mode (it doesn't translate atoms).

*i : prop -> iprop -> type.
%mode *i -A +A'.

*i/top : *i top itop.
*i/and : *i (and A B) (iand A' B')
	 <- *i A A'
	 <- *i B B'.
*i/bot : *i bot ibot.
*i/or : *i (or A B) (ior A' B')
	 <- *i A A'
	 <- *i B B'.
*i/imp : *i (imp A B) (iimp A' B')
	 <- *i A A'
	 <- *i B B'.

%block *ib : block {X : prop} {X' : iprop} {_ : *i X X'}.
%worlds (*ib) (*i _ _).
%total A (*i _ A).
%unique *i -1A +A'. 

*itot : {A'} *i A A' -> type.
%mode *itot +A -D*i.

%block *itotb : block {X : prop} {X' : iprop} 
		 {D*i : *i X X'} {_ : *itot X' D*i}.
%worlds (*itotb | fb | pb) (*itot _ _).
%trustme %total {} (*itot _ _).  %% verified by %total above

id-prop : prop -> prop -> type.
id-prop/refl : id-prop A A.

*iunique : *i A A' -> *i B A' -> id-prop A B -> type.
%mode *iunique +X1 +X2 -X3.
%worlds (*ib | fb | pb) (*iunique _ _ _).
%trustme %total {} (*iunique _ _ _). %% verified by %unique above

true-respects-id : >> true A -> id-prop A' A -> >> true A' -> type.
%mode true-respects-id +X1 +X2 -X3.
- : true-respects-id D _ D.
%worlds (tb | fb | pb) (true-respects-id _ _ _).
%total {} (true-respects-id _ _ _).

Intuitionistic truth implies classical truth

The arguments are in a funny order because I copied from soundness. =)

incl :  >> true A -> *i A A' -> itrue A' -> type.
%mode incl -X1 +X2 +X3.

- : incl mt *i/top imt.
- : incl (pair E1 E2) (*i/and D*2 D*1) (ipair E1' E2')
     <- incl E1 D*1 E1'
     <- incl E2 D*2 E2'.
- : incl (fst E) D*1 (ifst (E' : itrue (iand A1 A2)))
     <- *itot A2 D*2
     <- incl E (*i/and D*2 D*1) E'.
- : incl (snd (E : >> true (and A1 A2))) D*2 (isnd E')
     <- *itot _ D*1
     <- incl E (*i/and D*2 D*1) E'.
- : incl ((abort E) : >> true C) D* (iabort E')
     <- incl E *i/bot E'.
- : incl ((inl E) : >> true (or A1 A2)) (*i/or D*2 D*1) (iinl E')
     <- incl E D*1 E'.
- : incl ((inr E) : >> true (or A1 A2)) (*i/or D*2 D*1) (iinr E')
     <- incl E D*2 E'.
- : incl (case (E : >> true (or A B)) E1 E2) D* (icase E' E1' E2')
     <- *itot _ D*A
     <- *itot _ D*B
     <- incl E (*i/or D*B D*A) E'
     <- ({x : >> true A} {x' : itrue A'} 
	   {_ : {A-2} {D*' : *i A-2 A'} {Did : id-prop A-2 A} {E : >> true A-2}
		      incl E D*' x'
		      <- *iunique D*' D*A Did
		      <- true-respects-id x Did E
		       }
	   incl (E1 x) D* (E1' x'))
     <- ({x : >> true B} {x' : itrue B'} 
	   {_ : {B-2} {D*' : *i B-2 B'} {Did : id-prop B-2 B} {E : >> true B-2}
		      incl E D*' x'
		      <- *iunique D*' D*B Did
		      <- true-respects-id x Did E
		      }
	   incl (E2 x) D* (E2' x')).
- : incl ((lam E) : >> true (imp A B)) (*i/imp D* D*A) (ilam E')
     <- ({x : >> true A} {x' : itrue A'} 
	   {_ : {A-2} {D*' : *i A-2 A'} {Did : id-prop A-2 A} {E : >> true A-2}
		      incl E D*' x'
		      <- *iunique D*' D*A Did
		      <- true-respects-id x Did E
			}
	   incl (E x) D* (E' x')).
- : incl (app E1 E2) D*B (iapp E1' E2')
     <- *itot A D*A
     <- incl E1 (*i/imp D*B D*A) E1'
     <- incl  E2 D*A E2'.

%block inclb : some {A} {A'} {D* : *i A A'}
		block {x : >> true A} {x' : itrue A'} 
		{_ : {A-2} {D*' : *i A-2 A'} {Did : id-prop A-2 A} {E : >> true A-2}
		      incl E D*' x'
		      <- *iunique D*' D* Did
		      <- true-respects-id x Did E
		      }.
%worlds (inclb | fb | *itotb) (incl _ _ _). 
%total D (incl _ _ D).

Round-tripping the two translations is classically equivalent

equiv : * A A' -> *i A'' A' -> >> true (iff A A'') -> type.
%mode equiv +X1 +X2 -X3.

- : equiv D D' (iffi ([x] x) ([x] x)).
- : equiv (*/and D*2 D*1) (*i/and D*2' D*1') 
     (iffi 
	([x] (pair (iffel E1 (fst x)) (iffel E2 (snd x))))
	([x] (pair (iffer E1 (fst x)) (iffer E2 (snd x)))))
     <- equiv D*1 D*1' E1
     <- equiv D*2 D*2' E2.
- : equiv (*/or D*2 D*1) (*i/imp *i/bot (*i/imp *i/bot (*i/or D*2' D*1')))
     (iffi
	([x] (iffel notimpbot2
		(cdni 
		   (case x 
		      ([x1] (inl (iffel E1 x1)))
		      ([x2] (inr (iffel E2 x2)))))))
 	([x] (case (cdne (iffer notimpbot2 x))
		([x1] (inl (iffer E1 x1))) ([x2] (inr (iffer E2 x2))))))
     <- equiv D*1 D*1' E1
     <- equiv D*2 D*2' E2.
- : equiv (*/imp D*2 D*1) (*i/imp D*2' D*1') 
     (iffi 
	([f : >> true (imp A1 A2)] (lam [x : >> true B1] (iffel E2 (app f (iffer E1 x)))))
	([f : >> true (imp B1 B2)] (lam [x : >> true A1] (iffer E2 (app f (iffel E1 x))))))
     <- equiv D*1 D*1' (E1 : >> true (iff A1 B1))
     <- equiv D*2 D*2' (E2 : >> true (iff A2 B2)).
- : equiv */nbot *i/bot (iffi ([x] (cabort (nbote x))) ([x] abort x)).
- : equiv (*/not D*) (*i/imp *i/bot D*') 
     (iffi
	([x] (lam [y] (cabort (notcase x [u] throw u (iffer E y)))))
	([x] (noti (cont [y] (abort (app x (iffel E y)))))))
     <- equiv D* D*' E.

%block equivb : block {X : prop} {X' : iprop} 
		 {d*i : *i X X'}
		 {d*  : * X (inot (inot X'))}
		 {_   : equiv d* (*i/imp *i/bot (*i/imp *i/bot d*i)) 
			 (iffi 
			    ([x : >> true X] (iffel notimpbot2 (cdni x)))
			    ([x : >> true (imp (imp X bot) bot)]
			       (cdne (iffer notimpbot2 x))))
			    }.

%worlds (equivb | tb | fb) (equiv _ _ _).
%total D (equiv D _ _).

If A* is intuitionistically true, then A is classically true

comp : itrue A' -> * A A' -> >> true A -> type.
%mode comp +X1 +X2 -X3. 

- : comp (E' : itrue A') D* (iffer Eiff E)
     <- *itot A' D*i
     <- incl E D*i E'
     <- equiv D* D*i Eiff.

%block comp-pb : block {X : prop} {X' : iprop} 
		 {d*i : *i X X'}
		 {d*  : * X (inot (inot X'))}
		 {_   : equiv d* (*i/imp *i/bot (*i/imp *i/bot d*i)) 
			 (iffi 
			    ([x : >> true X] (iffel notimpbot2 (cdni x)))
			    ([x : >> true (imp (imp X bot) bot)]
			       (cdne (iffer notimpbot2 x))))
			    }
		  {_ : *itot X' d*i}.

%worlds (comp-pb | inclb | fb) (comp _ _ _).
%total E1 (comp E1 _ _).

comp/false : itrue (iimp A' ibot) -> * A A' -> >> false A -> type.
%mode comp/false +X1 +X2 -X3.

- : comp/false E D* (cont [x] (notcase E' [u] throw u x))
     <- comp E (*/not D*)  E'.

%worlds (comp-pb | inclb | fb) (comp/false _ _ _).
%total {} (comp/false _ _ _).

comp/contra : itrue ibot -> >> contra -> type.
%mode comp/contra +X1 -X3.

- : comp/contra E (nbote E')
     <- comp E */nbot  E'.

%worlds (comp-pb | inclb | fb) (comp/contra _ _).
%total {} (comp/contra _ _).