Letrec

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

An example of encoding letrec, i.e. let-binding a bundle of mutually recursive expressions

nat	: type.

z	: nat.
s	: nat -> nat. 

tp	: type. 

natt	: tp.
arrow	: tp -> tp -> tp.

tplist	: nat -> type.

tplist/z	: tplist z.
tplist/s	: tp -> tplist N -> tplist (s N). 

exp	: type. 
oexp	: nat -> type. 
explist	: nat -> type.

oexplist N M, is a list of M expressions with N bound variables

oexplist: nat -> nat -> type. 


zero	: exp.
succ	: exp -> exp. 
case	: exp -> exp -> (exp -> exp) -> exp. 
let	: exp -> (exp -> exp) -> exp. 
letrec	: oexplist N N -> oexp N -> exp.
bproj	: oexplist N N -> nat -> exp. % projecting from a bundle
lam	: (exp -> exp) -> exp. 
app	: exp -> exp -> exp. 



oexp/z	: exp -> oexp z.
oexp/s	: (exp -> oexp N) -> oexp (s N).



explist/z	: explist z.
explist/s	: exp -> explist N -> explist (s N).



oexplist/z	: explist N -> oexplist z N.
oexplist/s	: (exp -> oexplist N M) -> oexplist (s N) M. 



tplist-get	: nat -> tplist N -> tp -> type. 

tplist-get/hit	: tplist-get z (tplist/s T TL) T.
tplist-get/miss	: tplist-get (s N) (tplist/s T TL) T'
		   <- tplist-get N TL T'. 



of-exp		: exp -> tp -> type. 
of-oexp		: tplist N -> oexp N -> tp -> type. 
of-explist	: explist N -> tplist N -> type.
of-oexplist	: tplist N -> oexplist N M -> tplist M -> type. 



of-exp/zero	: of-exp zero natt.

of-exp/succ	: of-exp (succ E) natt
		   <- of-exp E natt. 

of-exp/case	: of-exp (case E1 E2 E3) T
		   <- of-exp E1 natt
		   <- of-exp E2 T
		   <- ({x} of-exp x natt
			 -> of-exp (E3 x) T).

of-exp/let	: of-exp (let E1 E2) T'
		   <- of-exp E1 T
		   <- ({x} of-exp x T
			 -> of-exp (E2 x) T'). 

of-exp/letrec	: of-exp (letrec OEL OE) T
		   <- of-oexplist TL OEL TL
		   <- of-oexp TL OE T.

of-exp/bproj	: of-exp (bproj OE N) T
		   <- of-oexplist TL OE TL
		   <- tplist-get N TL T. 

of-exp/lam	: of-exp (lam E) (arrow T1 T2)
		   <- ({x} of-exp x T1
			 -> of-exp (E x) T2).

of-exp/app	: of-exp (app E1 E2) T2
		   <- of-exp E1 (arrow T1 T2)
		   <- of-exp E2 T1. 



of-oexp/z	: of-oexp tplist/z (oexp/z E) T
		   <- of-exp E T. 
of-oexp/s	: of-oexp (tplist/s T TL) (oexp/s ([x] EL x)) T'
		   <- ({x} of-exp x T
			 -> of-oexp TL (EL x) T').



of-explist	: explist N -> tplist N -> type. 

of-explist/z	: of-explist explist/z tplist/z.
of-explist/s	: of-explist (explist/s E EL) (tplist/s T TL)
		   <- of-exp E T
		   <- of-explist EL TL. 



of-oexplist/z	: of-oexplist tplist/z (oexplist/z EL) TL
		   <- of-explist EL TL.
of-oexplist/s	: of-oexplist (tplist/s T TL) (oexplist/s OEL) TL'
		   <- ({x} of-exp x T
			 -> of-oexplist TL (OEL x) TL').


value	: exp -> type.

value/zero	: value zero.

value/succ	: value (succ E)
		   <- value E. 

value/lam	: value (lam E).



subst-oexp	: explist N -> oexp N -> exp -> type. 

subst-oexp/z	: subst-oexp explist/z (oexp/z E) E. 
subst-oexp/s	: subst-oexp (explist/s E EL) (oexp/s ([x] OE x)) E'
		   <- subst-oexp EL (OE E) E'.


expand-oexplist	: nat -> oexplist M M -> oexplist N M -> explist M -> type. 

expand-oexplist/z	: expand-oexplist _ _ (oexplist/z EL) EL. 
expand-oexplist/s	: expand-oexplist N OEL (oexplist/s OEL') EL
			   <- expand-oexplist (s N) OEL (OEL' (bproj OEL N)) EL.





explist-get	: nat -> explist N -> exp -> type. 

explist-get/hit	: explist-get z (explist/s E EL) E.
explist-get/miss: explist-get (s N) (explist/s E EL) E'
		   <- explist-get N EL E'.



step	: exp -> exp -> type. 

step/succ	: step (succ E) (succ E')
		   <- step E E'.

step/case	: step (case E1 E2 E3) (case E1' E2 E3)
		   <- step E1 E1'.

step/case-beta-1: step (case zero E2 E3) E2.

step/case-beta-2: step (case (succ E1) E2 E3) (E3 E1)
		   <- value E1. 

step/let	: step (let E1 E2) (let E1' E2)
		   <- step E1 E1'.

step/let-beta	: step (let E1 E2) (E2 E1)
		   <- value E1. 

step/letrec	: step (letrec OEL OE) E
		   <- expand-oexplist z OEL OEL EL
		   <- subst-oexp EL OE E.

step/bproj	: step (bproj OEL N) E
		   <- expand-oexplist z OEL OEL EL
		   <- explist-get N EL E. 

step/app-1	: step (app E1 E2) (app E1' E2)
		   <- step E1 E1'.

step/app-2	: step (app E1 E2) (app E1 E2')
		   <- value E1
		   <- step E2 E2'. 

step/app-beta	: step (app (lam E) E2) (E E2)
		   <- value E2. 



nat-plus	: nat -> nat -> nat -> type.

nat-plus/z	: nat-plus z N N.
nat-plus/s	: nat-plus (s N1) N2 (s N3)
		   <- nat-plus N1 N2 N3. 



nat-plus-move-s	: nat-plus (s N1) N2 N3
		   -> nat-plus N1 (s N2) N3
		   -> type. 
%mode nat-plus-move-s +D1 -D2.

-	: nat-plus-move-s (nat-plus/s nat-plus/z) nat-plus/z.

-	: nat-plus-move-s (nat-plus/s D1) (nat-plus/s D2)
	   <- nat-plus-move-s D1 D2.

%worlds () (nat-plus-move-s _ _).
%total (D1) (nat-plus-move-s D1 _). 



can-expand-oexplist	: {N} {OEL : oexplist NN NN} 
			   {OEL' : oexplist N NN}
			   nat-plus N N' NN
			   -> expand-oexplist N' OEL OEL' EL
			   -> type. 
%mode can-expand-oexplist +D1 +D2 +D3 +D4 -D5.

-	: can-expand-oexplist z OEL (oexplist/z EL) nat-plus/z expand-oexplist/z.

-	: can-expand-oexplist (s N) _ _ NP (expand-oexplist/s DEO)
	   <- nat-plus-move-s NP NP'
	   <- can-expand-oexplist N _ _ NP' DEO.

%worlds () (can-expand-oexplist _ _ _ _ _).
%total (D1) (can-expand-oexplist D1 _ _ _ _).



nat-plus-z	: {N}
		   nat-plus N z N
		   -> type. 
%mode nat-plus-z +D1 -D2.

-	: nat-plus-z _ nat-plus/z.

-	: nat-plus-z _ (nat-plus/s D1)
	   <- nat-plus-z _ D1.

%worlds () (nat-plus-z _ _).
%total (D1) (nat-plus-z D1 _).



notstuck	: exp -> type.

notstuck/value	: notstuck E
		   <- value E. 
notstuck/step	: notstuck E
		   <- step E E'. 



can-subst-oexp	: {EL : explist N}
		   {OE : oexp N}
		   subst-oexp EL OE E
		   -> type. 
%mode can-subst-oexp +D1 +D2 -D3.

-	: can-subst-oexp _ _ subst-oexp/z.

-	: can-subst-oexp (explist/s E EL) _ (subst-oexp/s D1)
	   <- can-subst-oexp EL _ D1. 

%worlds () (can-subst-oexp _ _ _).
%total (D1) (can-subst-oexp D1 _ _).






can-explist-get	: {EL : explist N'}
		   tplist-get N (TL : tplist N') T
		   -> explist-get N EL E
		   -> type.
%mode can-explist-get +D1 +D2 -D3.

-	: can-explist-get _ tplist-get/hit 
	   explist-get/hit.

-	: can-explist-get _ (tplist-get/miss D2) 
	   (explist-get/miss D')
	   <- can-explist-get _ D2 D'.

%worlds () (can-explist-get _ _ _).
%total (D2) (can-explist-get _ D2 _). 



progress-case	: {E1}{E2}
		   of-exp E natt
		   -> notstuck E 
		   -> notstuck (case E E1 E2)
		   -> type. 
%mode progress-case +D1 +D2 +D3 +D4 -D5.

-	: progress-case _ _ _ (notstuck/step S)
	   (notstuck/step (step/case S)).

-	: progress-case _ _ of-exp/zero (notstuck/value _)
	   (notstuck/step step/case-beta-1).

-	: progress-case _ _ (of-exp/succ _) (notstuck/value (value/succ DV))
	   (notstuck/step (step/case-beta-2 DV)).

%worlds () (progress-case _ _ _ _ _). 
%total {} (progress-case _ _ _ _ _).



progress-succ	: notstuck E1
		   -> notstuck (succ E1)
		   -> type. 
%mode progress-succ +D1 -D2.

-	: progress-succ (notstuck/step DS)
	   (notstuck/step (step/succ DS)).

-	: progress-succ (notstuck/value DV1)
	   (notstuck/value (value/succ DV1)).

%worlds () (progress-succ _ _).
%total {} (progress-succ _ _).



progress-app	: of-exp E1 (arrow T1 T2)
		   -> of-exp E2 T1
		   -> notstuck E1
		   -> notstuck E2
		   -> notstuck (app E1 E2)
		   -> type. 
%mode progress-app +D1 +D2 +D3 +D4 -D5.

-	: progress-app _ _ (notstuck/step DS) _
	   (notstuck/step (step/app-1 DS)).

-	: progress-app _ _ (notstuck/value V) (notstuck/step DS)
	   (notstuck/step (step/app-2 DS V)).

-	: progress-app (of-exp/lam DM) D2 (notstuck/value value/lam)
	   (notstuck/value DV) (notstuck/step (step/app-beta DV)).
%worlds () (progress-app _ _ _ _ _).
%total {} (progress-app _ _ _ _ _).



progress-let	: {E2}
		   notstuck E1
		   -> notstuck (let E1 E2)
		   -> type. 
%mode progress-let +D1 +D2 -D3.

-	: progress-let _ (notstuck/step S) (notstuck/step (step/let S)).

-	: progress-let _ (notstuck/value V) (notstuck/step (step/let-beta V)).

%worlds () (progress-let _ _ _).
%total {} (progress-let _ _ _). 



progress	: of-exp E T
		   -> notstuck E
		   -> type.
%mode progress +D1 -D2.

-	: progress (of-exp/lam _) (notstuck/value value/lam).

-	: progress (of-exp/app D2 D1) NS3
	   <- progress D1 NS1
	   <- progress D2 NS2
	   <- progress-app D1 D2 NS1 NS2 NS3.

-	: progress of-exp/zero (notstuck/value value/zero).

-	: progress (of-exp/succ D1) NS
	   <- progress D1 NS1
	   <- progress-succ NS1 NS.

-	: progress (of-exp/case _ _ D1) NS
	   <- progress D1 NS1
	   <- progress-case _ _ D1 NS1 NS.

-	: progress (of-exp/let _ D1) NS
	   <- progress D1 NS1
	   <- progress-let _ NS1 NS.

-	: progress (of-exp/letrec D2 D1)
	   (notstuck/step (step/letrec DS DX))
	   <- nat-plus-z _ DNP
	   <- can-expand-oexplist _ _ _ DNP DX
	   <- can-subst-oexp _ _ DS.

-	: progress (of-exp/bproj D2 D1)
	   (notstuck/step (step/bproj DS DX))
	   <- nat-plus-z _ DNP
	   <- can-expand-oexplist _ _ _ DNP DX
	   <- can-explist-get _ D2 DS.

%worlds () (progress _ _).
%total (D1) (progress D1 _).



tplist-prefix	: nat -> tplist N -> tplist N' -> type. 

tplist-prefix/z	: tplist-prefix z TL TL.
tplist-prefix/s	: tplist-prefix (s N) (tplist/s T TL) TL'
		   <- tplist-prefix N TL TL'.



tplist-prefix-get	: tplist-prefix N TL'' (tplist/s T TL')
			   -> tplist-get N TL'' T
			   -> type.
%mode tplist-prefix-get +D1 -D2.

-	: tplist-prefix-get tplist-prefix/z tplist-get/hit.

-	: tplist-prefix-get (tplist-prefix/s D1) (tplist-get/miss D2)
	   <- tplist-prefix-get D1 D2.

%worlds () (tplist-prefix-get _ _). 
%total (D1) (tplist-prefix-get D1 _). 



tplist-prefix-s	: tplist-prefix N TL (tplist/s T TL')
		   -> tplist-prefix (s N) TL TL'
		   -> type.
%mode tplist-prefix-s +D1 -D2.

-	: tplist-prefix-s tplist-prefix/z (tplist-prefix/s tplist-prefix/z). 

-	: tplist-prefix-s (tplist-prefix/s D1) (tplist-prefix/s D2)
	   <- tplist-prefix-s D1 D2.

%worlds () (tplist-prefix-s _ _).
%total (D1) (tplist-prefix-s D1 _).



preservation-expand-oexplist	: tplist-prefix N' TL TL'
				   -> of-oexplist TL (OEL : oexplist M M) 
				      (TL : tplist M)
				   -> of-oexplist TL' OEL' TL
				   -> expand-oexplist N' OEL OEL' EL
				   -> of-explist EL TL
				   -> type. 
%mode preservation-expand-oexplist +D1 +D2 +D3 +D4 -D5.

-	: preservation-expand-oexplist _
	   DOE (of-oexplist/z DEL) expand-oexplist/z 
	   DEL. 

-	: preservation-expand-oexplist 
	   DO
	   DOE
	   (of-oexplist/s DOE')
	   (expand-oexplist/s DOX)
	   DEL
	   <- tplist-prefix-s DO DO'
	   <- tplist-prefix-get DO DG
	   <- preservation-expand-oexplist DO' DOE 
	      (DOE' _ (of-exp/bproj DG DOE))
	      DOX DEL. 

%worlds () (preservation-expand-oexplist _ _ _ _ _).
%total (D1) (preservation-expand-oexplist  _ _ _ D1 _).



preservation-subst-oexp	: of-explist EL TL
			   -> of-oexp TL OE T
			   -> subst-oexp EL OE E
			   -> of-exp E T
			   -> type.
%mode preservation-subst-oexp +D1 +D2 +D3 -D4.

-	: preservation-subst-oexp _ (of-oexp/z D1) subst-oexp/z D1.

-	: preservation-subst-oexp (of-explist/s D1 D) (of-oexp/s D2)
	   (subst-oexp/s D3) D4
	   <- preservation-subst-oexp D1 (D2 _ D) D3 D4.

%worlds () (preservation-subst-oexp _ _ _ _).
%total (D1) (preservation-subst-oexp _ _ D1 _).




preservation-get	: of-explist EL TL
			   -> explist-get M EL E
			   -> tplist-get M TL T
			   -> of-exp E T
			   -> type.
%mode preservation-get +D1 +D2 +D3 -D4.

-	: preservation-get (of-explist/s _ D) explist-get/hit tplist-get/hit D.

-	: preservation-get (of-explist/s DL _) (explist-get/miss D') 
	   (tplist-get/miss D'') D
	   <- preservation-get DL D' D'' D.

%worlds () (preservation-get _ _ _ _).
%total (D1) (preservation-get _ _ D1 _).



preservation	: of-exp E T
		   -> step E E'
		   -> of-exp E' T
		   -> type.
%mode preservation +D1 +D2 -D3.

-	: preservation (of-exp/app D2 D1) (step/app-1 DS)
	   (of-exp/app D2 D1')
	   <- preservation D1 DS D1'.

-	: preservation (of-exp/app D2 D1) (step/app-2 DS V)
	   (of-exp/app D2' D1)
	   <- preservation D2 DS D2'.

-	: preservation (of-exp/app D2 (of-exp/lam D1)) (step/app-beta V)
	   (D1 _ D2).


-	: preservation (of-exp/succ D1) (step/succ DS)
	   (of-exp/succ D1')
	   <- preservation D1 DS D1'.

-	: preservation (of-exp/case D3 D2 D1) (step/case DS)
	   (of-exp/case D3 D2 D1')
	   <- preservation D1 DS D1'.

-	: preservation (of-exp/case D3 D2 _) step/case-beta-1
	   D2.

-	: preservation (of-exp/case D3 _ (of-exp/succ D1)) (step/case-beta-2 _)
	   (D3 _ D1).

-	: preservation (of-exp/let D2 D1) (step/let DS)
	   (of-exp/let D2 D1')
	   <- preservation D1 DS D1'.

-	: preservation (of-exp/let D2 D1) (step/let-beta _)
	   (D2 _ D1).

-	: preservation (of-exp/letrec D2 D1) (step/letrec DOS DOX)
	   D
	   <- preservation-expand-oexplist tplist-prefix/z D1 D1 DOX D1'
	   <- preservation-subst-oexp D1' D2 DOS D.

-	: preservation (of-exp/bproj D2 D1) (step/bproj DOS DOX)
	   D
	   <- preservation-expand-oexplist tplist-prefix/z D1 D1 DOX D1'
	   <- preservation-get D1' DOS D2 D.

%worlds () (preservation _ _ _).
%total (D1) (preservation _ D1 _).

TODO: commentary.


This page is incomplete. We should expand it.