Skip to content
Documentation out of dateLearn more

Letrec

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

%sort nat %.
%term z nat %.
%term s %pi nat %-> nat %.
%sort tp %.
%term natt tp %.
%term arrow %pi tp %-> tp %-> tp %.
%sort tplist {_ nat} %.
%term tplist/z tplist z %.
%term tplist/s %pi tp %-> (tplist N) %-> (tplist (s N)) %.
%sort exp %.
%sort oexp {_ nat} %.
%sort explist {_ nat} %.

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

%sort oexplist {_ nat} {_ nat} %.
%term zero exp %.
%term succ %pi exp %-> exp %.
%term case %pi exp %-> exp %-> (%pi exp %-> exp) %-> exp %.
%term let %pi exp %-> (%pi exp %-> exp) %-> exp %.
%term letrec %pi (oexplist N N) %-> (oexp N) %-> exp %.
%term bproj %pi (oexplist N N) %-> nat %-> exp %.
% projecting from a bundle
%term lam %pi (%pi exp %-> exp) %-> exp %.
%term app %pi exp %-> exp %-> exp %.
%term oexp/z %pi exp %-> (oexp z) %.
%term oexp/s %pi (%pi exp %-> (oexp N)) %-> (oexp (s N)) %.
%term explist/z explist z %.
%term explist/s %pi exp %-> (explist N) %-> (explist (s N)) %.
%term oexplist/z %pi (explist N) %-> (oexplist z N) %.
%term oexplist/s %pi (%pi exp %-> (oexplist N M)) %-> (oexplist (s N) M) %.
%sort tplist-get {_ nat} {_ tplist N} {_ tp} %.
%term tplist-get/hit tplist-get z (tplist/s T TL) T %.
%term tplist-get/miss %pi (tplist-get (s N) (tplist/s T TL) T') %<- (tplist-get N TL T') %.
%sort of-exp {_ exp} {_ tp} %.
%sort of-oexp {_ tplist N} {_ oexp N} {_ tp} %.
%sort of-explist {_ explist N} {_ tplist N} %.
%sort of-oexplist {_ tplist N} {_ oexplist N M} {_ tplist M} %.
%term of-exp/zero of-exp zero natt %.
%term of-exp/succ %pi (of-exp (succ E) natt) %<- (of-exp E natt) %.
%term of-exp/case
%pi (of-exp (case E1 E2 E3) T)
%<- (of-exp E1 natt)
%<- (of-exp E2 T)
%<- ({x} %pi (of-exp x natt) %-> (of-exp (E3 x) T)) %.
%term of-exp/let
%pi (of-exp (let E1 E2) T')
%<- (of-exp E1 T)
%<- ({x} %pi (of-exp x T) %-> (of-exp (E2 x) T')) %.
%term of-exp/letrec %pi (of-exp (letrec OEL OE) T) %<- (of-oexplist TL OEL TL) %<- (of-oexp TL OE T) %.
%term of-exp/bproj %pi (of-exp (bproj OE N) T) %<- (of-oexplist TL OE TL) %<- (tplist-get N TL T) %.
%term of-exp/lam
%pi (of-exp (lam E) (arrow T1 T2))
%<- ({x} %pi (of-exp x T1) %-> (of-exp (E x) T2)) %.
%term of-exp/app %pi (of-exp (app E1 E2) T2) %<- (of-exp E1 (arrow T1 T2)) %<- (of-exp E2 T1) %.
%term of-oexp/z %pi (of-oexp tplist/z (oexp/z E) T) %<- (of-exp E T) %.
%term of-oexp/s
%pi (of-oexp (tplist/s T TL) (oexp/s ([x] EL x)) T')
%<- ({x} %pi (of-exp x T) %-> (of-oexp TL (EL x) T')) %.
%sort of-explist {_ explist N} {_ tplist N} %.
%term of-explist/z of-explist explist/z tplist/z %.
%term of-explist/s
%pi (of-explist (explist/s E EL) (tplist/s T TL))
%<- (of-exp E T)
%<- (of-explist EL TL) %.
%term of-oexplist/z %pi (of-oexplist tplist/z (oexplist/z EL) TL) %<- (of-explist EL TL) %.
%term of-oexplist/s
%pi (of-oexplist (tplist/s T TL) (oexplist/s OEL) TL')
%<- ({x} %pi (of-exp x T) %-> (of-oexplist TL (OEL x) TL')) %.
%sort value {_ exp} %.
%term value/zero value zero %.
%term value/succ %pi (value (succ E)) %<- (value E) %.
%term value/lam value (lam E) %.
%sort subst-oexp {_ explist N} {_ oexp N} {_ exp} %.
%term subst-oexp/z subst-oexp explist/z (oexp/z E) E %.
%term subst-oexp/s
%pi (subst-oexp (explist/s E EL) (oexp/s ([x] OE x)) E')
%<- (subst-oexp EL (OE E) E') %.
%sort expand-oexplist {_ nat} {_ oexplist M M} {_ oexplist N M} {_ explist M} %.
%term expand-oexplist/z expand-oexplist _ _ (oexplist/z EL) EL %.
%term expand-oexplist/s
%pi (expand-oexplist N OEL (oexplist/s OEL') EL)
%<- (expand-oexplist (s N) OEL (OEL' (bproj OEL N)) EL) %.
%sort explist-get {_ nat} {_ explist N} {_ exp} %.
%term explist-get/hit explist-get z (explist/s E EL) E %.
%term explist-get/miss %pi (explist-get (s N) (explist/s E EL) E') %<- (explist-get N EL E') %.
%sort step {_ exp} {_ exp} %.
%term step/succ %pi (step (succ E) (succ E')) %<- (step E E') %.
%term step/case %pi (step (case E1 E2 E3) (case E1' E2 E3)) %<- (step E1 E1') %.
%term step/case-beta-1 step (case zero E2 E3) E2 %.
%term step/case-beta-2 %pi (step (case (succ E1) E2 E3) (E3 E1)) %<- (value E1) %.
%term step/let %pi (step (let E1 E2) (let E1' E2)) %<- (step E1 E1') %.
%term step/let-beta %pi (step (let E1 E2) (E2 E1)) %<- (value E1) %.
%term step/letrec
%pi (step (letrec OEL OE) E)
%<- (expand-oexplist z OEL OEL EL)
%<- (subst-oexp EL OE E) %.
%term step/bproj
%pi (step (bproj OEL N) E)
%<- (expand-oexplist z OEL OEL EL)
%<- (explist-get N EL E) %.
%term step/app-1 %pi (step (app E1 E2) (app E1' E2)) %<- (step E1 E1') %.
%term step/app-2 %pi (step (app E1 E2) (app E1 E2')) %<- (value E1) %<- (step E2 E2') %.
%term step/app-beta %pi (step (app (lam E) E2) (E E2)) %<- (value E2) %.
%sort nat-plus {_ nat} {_ nat} {_ nat} %.
%term nat-plus/z nat-plus z N N %.
%term nat-plus/s %pi (nat-plus (s N1) N2 (s N3)) %<- (nat-plus N1 N2 N3) %.
%sort nat-plus-move-s {_ nat-plus (s N1) N2 N3} {_ nat-plus N1 (s N2) N3} %.
%mode nat-plus-move-s %in %out %.
%term _ nat-plus-move-s (nat-plus/s nat-plus/z) nat-plus/z %.
%term _ %pi (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 _) %.
%sort can-expand-oexplist {N} {OEL oexplist NN NN} {OEL' oexplist N NN} {_ nat-plus N N' NN} {_ expand-oexplist N' OEL OEL' EL} %.
%mode can-expand-oexplist %in %in %in %in %out %.
%term _ can-expand-oexplist z OEL (oexplist/z EL) nat-plus/z expand-oexplist/z %.
%term _
%pi (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 _ _ _ _) %.
%sort nat-plus-z {N} {_ nat-plus N z N} %.
%mode nat-plus-z %in %out %.
%term _ nat-plus-z _ nat-plus/z %.
%term _ %pi (nat-plus-z _ (nat-plus/s D1)) %<- (nat-plus-z _ D1) %.
%worlds () (nat-plus-z _ _) %.
%total (D1) (nat-plus-z D1 _) %.
%sort notstuck {_ exp} %.
%term notstuck/value %pi (notstuck E) %<- (value E) %.
%term notstuck/step %pi (notstuck E) %<- (step E E') %.
%sort can-subst-oexp {EL explist N} {OE oexp N} {_ subst-oexp EL OE E} %.
%mode can-subst-oexp %in %in %out %.
%term _ can-subst-oexp _ _ subst-oexp/z %.
%term _
%pi (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 _ _) %.
%sort can-explist-get {EL explist N'} {_ tplist-get N (%the (tplist N') TL) T} {_ explist-get N EL E} %.
%mode can-explist-get %in %in %out %.
%term _ can-explist-get _ tplist-get/hit explist-get/hit %.
%term _
%pi (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 _) %.
%sort progress-case {E1} {E2} {_ of-exp E natt} {_ notstuck E} {_ notstuck (case E E1 E2)} %.
%mode progress-case %in %in %in %in %out %.
%term _ progress-case _ _ _ (notstuck/step S) (notstuck/step (step/case S)) %.
%term _ progress-case _ _ of-exp/zero (notstuck/value _) (notstuck/step step/case-beta-1) %.
%term _ progress-case _ _ (of-exp/succ _) (notstuck/value (value/succ DV)) (notstuck/step (step/case-beta-2 DV)) %.
%worlds () (progress-case _ _ _ _ _) %.
%total {} (progress-case _ _ _ _ _) %.
%sort progress-succ {_ notstuck E1} {_ notstuck (succ E1)} %.
%mode progress-succ %in %out %.
%term _ progress-succ (notstuck/step DS) (notstuck/step (step/succ DS)) %.
%term _ progress-succ (notstuck/value DV1) (notstuck/value (value/succ DV1)) %.
%worlds () (progress-succ _ _) %.
%total {} (progress-succ _ _) %.
%sort progress-app {_ of-exp E1 (arrow T1 T2)} {_ of-exp E2 T1} {_ notstuck E1} {_ notstuck E2} {_ notstuck (app E1 E2)} %.
%mode progress-app %in %in %in %in %out %.
%term _ progress-app _ _ (notstuck/step DS) _ (notstuck/step (step/app-1 DS)) %.
%term _ progress-app _ _ (notstuck/value V) (notstuck/step DS) (notstuck/step (step/app-2 DS V)) %.
%term _ 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 _ _ _ _ _) %.
%sort progress-let {E2} {_ notstuck E1} {_ notstuck (let E1 E2)} %.
%mode progress-let %in %in %out %.
%term _ progress-let _ (notstuck/step S) (notstuck/step (step/let S)) %.
%term _ progress-let _ (notstuck/value V) (notstuck/step (step/let-beta V)) %.
%worlds () (progress-let _ _ _) %.
%total {} (progress-let _ _ _) %.
%sort progress {_ of-exp E T} {_ notstuck E} %.
%mode progress %in %out %.
%term _ progress (of-exp/lam _) (notstuck/value value/lam) %.
%term _
%pi (progress (of-exp/app D2 D1) NS3)
%<- (progress D1 NS1)
%<- (progress D2 NS2)
%<- (progress-app D1 D2 NS1 NS2 NS3) %.
%term _ progress of-exp/zero (notstuck/value value/zero) %.
%term _
%pi (progress (of-exp/succ D1) NS)
%<- (progress D1 NS1)
%<- (progress-succ NS1 NS) %.
%term _
%pi (progress (of-exp/case _ _ D1) NS)
%<- (progress D1 NS1)
%<- (progress-case _ _ D1 NS1 NS) %.
%term _
%pi (progress (of-exp/let _ D1) NS)
%<- (progress D1 NS1)
%<- (progress-let _ NS1 NS) %.
%term _
%pi (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) %.
%term _
%pi (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 _) %.
%sort tplist-prefix {_ nat} {_ tplist N} {_ tplist N'} %.
%term tplist-prefix/z tplist-prefix z TL TL %.
%term tplist-prefix/s %pi (tplist-prefix (s N) (tplist/s T TL) TL') %<- (tplist-prefix N TL TL') %.
%sort tplist-prefix-get {_ tplist-prefix N TL'' (tplist/s T TL')} {_ tplist-get N TL'' T} %.
%mode tplist-prefix-get %in %out %.
%term _ tplist-prefix-get tplist-prefix/z tplist-get/hit %.
%term _
%pi (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 _) %.
%sort tplist-prefix-s {_ tplist-prefix N TL (tplist/s T TL')} {_ tplist-prefix (s N) TL TL'} %.
%mode tplist-prefix-s %in %out %.
%term _ tplist-prefix-s tplist-prefix/z (tplist-prefix/s tplist-prefix/z) %.
%term _
%pi (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 _) %.
%sort preservation-expand-oexplist {_ tplist-prefix N' TL TL'} {_ of-oexplist TL (%the (oexplist M M) OEL) (%the (tplist M) TL)} {_ of-oexplist TL' OEL' TL} {_ expand-oexplist N' OEL OEL' EL} {_ of-explist EL TL} %.
%mode preservation-expand-oexplist %in %in %in %in %out %.
%term _ preservation-expand-oexplist _ DOE (of-oexplist/z DEL) expand-oexplist/z DEL %.
%term _
%pi (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 _) %.
%sort preservation-subst-oexp {_ of-explist EL TL} {_ of-oexp TL OE T} {_ subst-oexp EL OE E} {_ of-exp E T} %.
%mode preservation-subst-oexp %in %in %in %out %.
%term _ preservation-subst-oexp _ (of-oexp/z D1) subst-oexp/z D1 %.
%term _
%pi (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 _) %.
%sort preservation-get {_ of-explist EL TL} {_ explist-get M EL E} {_ tplist-get M TL T} {_ of-exp E T} %.
%mode preservation-get %in %in %in %out %.
%term _ preservation-get (of-explist/s _ D) explist-get/hit tplist-get/hit D %.
%term _
%pi (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 _) %.
%sort preservation {_ of-exp E T} {_ step E E'} {_ of-exp E' T} %.
%mode preservation %in %in %out %.
%term _
%pi (preservation (of-exp/app D2 D1) (step/app-1 DS) (of-exp/app D2 D1'))
%<- (preservation D1 DS D1') %.
%term _
%pi (preservation (of-exp/app D2 D1) (step/app-2 DS V) (of-exp/app D2' D1))
%<- (preservation D2 DS D2') %.
%term _ preservation (of-exp/app D2 (of-exp/lam D1)) (step/app-beta V) (D1 _ D2) %.
%term _
%pi (preservation (of-exp/succ D1) (step/succ DS) (of-exp/succ D1'))
%<- (preservation D1 DS D1') %.
%term _
%pi (preservation (of-exp/case D3 D2 D1) (step/case DS) (of-exp/case D3 D2 D1'))
%<- (preservation D1 DS D1') %.
%term _ preservation (of-exp/case D3 D2 _) step/case-beta-1 D2 %.
%term _ preservation (of-exp/case D3 _ (of-exp/succ D1)) (step/case-beta-2 _) (D3 _ D1) %.
%term _
%pi (preservation (of-exp/let D2 D1) (step/let DS) (of-exp/let D2 D1'))
%<- (preservation D1 DS D1') %.
%term _ preservation (of-exp/let D2 D1) (step/let-beta _) (D2 _ D1) %.
%term _
%pi (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) %.
%term _
%pi (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.