Deprecated: The each() function is deprecated. This message will be suppressed on further calls in /home/zhenxiangba/zhenxiangba.com/public_html/phproxy-improved-master/index.php on line 456
// A proof of strong normalization for System F based on Girard's
// notion of reducibility candidates.
// Kevin Donnelly and Hongwei Xi (May 2006)
// This is a proof based on Girard's method of reducibility candidates
// definition of sort 'tm' of HOAS terms
datasort tm =
| TMcst
| TMlam of (tm -> tm)
| TMapp of (tm, tm)
// neutral terms
dataprop NEU (tm) =
| NEUcst (TMcst)
| {t1:tm, t2:tm} NEUapp (TMapp (t1, t2))
// small-step reduction
dataprop RED (tm, tm, int) =
| {f:tm->tm, f':tm->tm, n:nat}
REDlam (TMlam f, TMlam f', n+1) of {x:tm} RED (f x, f' x, n)
| {t1:tm,t2:tm,t1':tm, s:nat}
REDapp1 (TMapp (t1, t2), TMapp (t1', t2), s+1) of RED (t1, t1', s)
| {t1:tm,t2:tm,t2':tm, s:nat}
REDapp2 (TMapp (t1, t2), TMapp (t1, t2'), s+1) of (RED (t2, t2', s))
| {f:tm->tm,t:tm} REDapp3 (TMapp (TMlam f, t), f t, 0)
propdef RED0 (t:tm, t':tm) = [s:nat] RED (t, t', s)
(* Strong Normalization *)
dataprop SN(tm, int) =
| {t:tm, n:nat} SN(t,n) of
{t':tm} (RED0(t, t') -> [n':nat | n' < n] SN(t',n'))
propdef SN0 (t:tm) = [n:nat] SN(t, n)
// SN is closed under reduction
prfun forwardSN {t:tm, t':tm, n:nat} .< >.
(sn:SN(t, n), red:RED0(t, t')) : [n':nat | n' < n] SN(t', n') =
let prval SN fsn = sn in fsn red end
// sort for predicates on terms
sortdef rc = tm -> prop
(* Reducibility Candidates *)
propdef CR1 (R: rc) = {t:tm} R t -> SN0 t
propdef CR2 (R: rc) = {t:tm, t':tm} (R t, RED0 (t, t')) -> R t'
propdef CR3 (R: rc) = {t:tm} (NEU t, {t':tm} RED0 (t, t') -> R t') -> R t
propdef RC (R: rc) = '(CR1 R, CR2 R, CR3 R)
prfn sn_is_cr1 (): CR1 (SN0) = lam sn => sn
prfn sn_is_cr2 (): CR2 (SN0) = lam (sn, rd) => let prval SN fsn = sn in fsn rd end
// this follows from the fact that any term has a finite number of reductions
// easy to see this is true, but complicated to formally prove
dynprf backwardSN: {t:tm} ({t':tm} RED0 (t, t') -> SN0 t') -> SN0 t
prfn sn_is_cr3 (): CR3 (SN0) = lam (_, fsn) => backwardSN fsn
prval sn_is_rc: RC (SN0) = '(sn_is_cr1 (), sn_is_cr2 (), sn_is_cr3 ())
//
prfn cr_cst {R:tm->prop} (rc:RC(R)) : R(TMcst) =
let
prval '(_, _, cr3) = rc
prfn redsR {t':tm} (red:RED0(TMcst, t')) : R(t') =
(case* red of REDapp3() => '())
in
cr3(NEUcst, redsR)
end
//
// lifting of -> to candidates
dataprop RCFUN (rc, rc, tm) =
{R1:rc, R2:rc, t:tm}
RCFUN (R1, R2, t) of {t1: tm} R1 t1 -> R2 (TMapp (t, t1))
propdef RCFUN0 (R1: rc, R2: rc) (t:tm) = RCFUN (R1, R2, t)
prfun appSNlemma {t:tm, t1:tm, n:nat} ..
(sn:SN(TMapp(t, t1), n)) : [n':nat | n' <= n] SN(t, n') =
let
prval SN(redsSNapp) = sn
prfn redsSNt {t':tm} (red:RED0(t, t')) : [n':nat | n' < n] SN(t', n') =
appSNlemma(redsSNapp (REDapp1 red))
in
SN{t,n}(redsSNt)
end
// R1 -> R2 is a candidate if R1 and R2 is
prfn rcfun_is_rc {R1:rc, R2:rc} (rc1:RC R1, rc2:RC R2): RC (RCFUN0 (R1, R2)) =
let
prval '(cr11, cr21, cr31) = rc1
prval '(cr12, cr22, cr32) = rc2
prfn rcfun_is_cr1 {t:tm} (rcfun : RCFUN0(R1, R2)(t))
: SN0(t) =
let
prval RCFUN(rcf) = rcfun
prval r2 = rcf (cr_cst rc1)
prval sn2 = cr12 r2
prval sn = appSNlemma(sn2)
in
sn
end
prfn rcfun_is_cr2 {t:tm, t':tm}
(rcfun : RCFUN0(R1, R2)(t),
red : RED0(t, t'))
: RCFUN0(R1,R2)(t') =
let
prval RCFUN(rcf) = rcfun
prfn rcf' {t1:tm} (r1:R1(t1)) : R2(TMapp(t', t1)) =
cr22(rcf r1, REDapp1(red))
in
RCFUN(rcf')
end
prfn rcfun_is_cr3 {t:tm}
(neu : NEU t,
rcfunf : {t':tm} (RED0(t, t') -> RCFUN0(R1, R2)(t')))
: RCFUN0(R1, R2)(t) =
let
// cr1 holds for R1 so we can argue by induction on SN bound (mu)
prfun rcfsn {t1:tm, n:nat} ..
(r1 : R1(t1),
sn1 : SN(t1, n))
: R2(TMapp(t, t1)) =
let
prfn rcf' {t':tm} (red:RED0(TMapp(t, t1), t'))
: R2(t') = case* red of
| REDapp1(red1) =>
let
prval RCFUN(rcf1) = rcfunf(red1)
in
rcf1 r1
end
| REDapp2(red2) =>
let
prval r1' = cr21 (r1, red2)
prval sn1' = forwardSN(sn1, red2)
in
rcfsn(r1', sn1')
end
| REDapp3() =>
(case* neu of NEUcst() => '())
in
cr32(NEUapp, rcf')
end
prfn rcf {t1:tm} (r1:R1(t1)) : R2(TMapp(t, t1)) =
let
prval sn1 = cr11 r1
in
rcfsn (r1, sn1)
end
in
RCFUN(rcf)
end
in
'(rcfun_is_cr1, rcfun_is_cr2, rcfun_is_cr3)
end
//
// lifting of forall to candidates
dataprop RCALL (rc -> rc, tm) =
{RF: rc -> rc, t:tm}
RCALL (RF, t) of {R: rc} RC R -> RF R t
propdef RCALL0 (RF: rc -> rc) (t:tm) = RCALL (RF, t)
// forall RF is a candidate if RF R is a candidate whenever R is
prfn rcall_is_rc {RF:rc -> rc} (rcrfrf: {R : rc} RC R -> RC (RF R)) : RC (RCALL0 RF) =
let
prfn rcall_is_cr1 {t:tm} (rcall : RCALL0(RF)(t))
: SN0(t) =
let
prval RCALL(rfrf) = rcall
prval rfsn = rfrf{SN0}(sn_is_rc)
prval rcrfsn = rcrfrf{SN0}(sn_is_rc)
prval '(cr1, _, _) = rcrfsn
in
cr1 rfsn
end
prfn rcall_is_cr2 {t:tm, t':tm}
(rcall : RCALL0(RF)(t),
red : RED0(t, t'))
: RCALL0(RF)(t') =
let
prfn rcf {R : rc} (rc : RC R) : RF(R)(t') =
let
prval RCALL(rfrf) = rcall
prval rfr = rfrf{R}(rc)
prval rc' = rcrfrf{R}(rc)
prval '(_, cr2, _) = rc'
in
cr2(rfr,red)
end
in
RCALL(rcf)
end
prfn rcall_is_cr3 {t:tm}
(neu : NEU t,
rcallf : {t':tm} (RED0(t, t') -> RCALL0(RF)(t')))
: RCALL0(RF)(t) =
let
prfn rcf {R : rc} (rc : RC R) : (RF R)(t) =
let
prfn rcf' {t':tm} (red:RED0(t, t'))
: (RF R)(t') =
let
prval RCALL(rfrf) = rcallf red
prval rfr = rfrf{R}(rc)
in
rfr
end
prval rc' = rcrfrf{R}(rc)
prval '(_, _, cr3) = rc'
in
cr3 (neu, rcf')
end
in
RCALL(rcf)
end
in
'(rcall_is_cr1, rcall_is_cr2, rcall_is_cr3)
end
// lam f : R1 -> R2 if R1, R2 are candidates and
// for all terms t, R1 t implies R2 (f t)
prfn abs_lemma {R1:rc, R2:rc, f:tm->tm}
(rc1 : RC R1,
rc2 : RC R2,
rcf : ({t:tm} R1 t -> R2 (f t)))
: RCFUN0 (R1, R2) (TMlam f) =
let
prval '(cr11, cr21, cr31) = rc1
prval '(cr12, cr22, cr32) = rc2
// since R1, R2 are candidates, we can argue by induction on the sum
// of the SN bounds
prfun rfr_aux {t1:tm, n:nat, m:nat, f:tm->tm} ..
(r1 : R1(t1),
sn1 : SN(t1, n),
sn2 : SN(f TMcst, m),
rcf : ({t:tm} R1 t -> R2 (f t)))
: R2(TMapp(TMlam f, t1)) =
let
// each reduction of (lam f) t1 results in t' such that R2 t'
prfn fr2 {t':tm} (red:RED0(TMapp(TMlam f, t1), t'))
: R2(t') = case* red of
| REDapp1(REDlam{f, f', _}(redf)) =>
let
prfn rcf' {t:tm} (r1 : R1(t)) : R2(f' t) =
cr22(rcf(r1), redf{t})
in
rfr_aux(r1, sn1, forwardSN(sn2, redf{TMcst}), rcf')
end
| REDapp2(red2) =>
rfr_aux (cr21(r1, red2), forwardSN(sn1, red2), sn2, rcf)
| REDapp3() => rcf(r1)
in
// since cr3 holds of R2, we know R2 ((lam f) t1)
cr32 (NEUapp, fr2)
end
prfn rfr {t1:tm} (r1:R1(t1)) : R2(TMapp(TMlam f, t1)) =
rfr_aux(r1, cr11(r1), cr12(rcf(cr_cst(rc1))), rcf)
in
RCFUN(rfr)
end
// definition of sort 'tp' of FOAS types
datasort tp =
| TPvar of int // type variable
| TPfun of (tp, tp) // T1 -> T2
| TPall of (tp) // forall X. T
// sequence of candidates (this plays double duty as a candidate context for
// type interpretation and as a bound on the deBruijn indices in derivations)
datasort rcs = RCSnil
| RCScons of (rc, rcs)
// type context lookup
dataprop RCSI(rcs, rc, int) =
| {R:rc, C:rcs}
RCSIone(RCScons(R, C), R, 0)
| {R:rc, R':rc, C:rcs, n:nat}
RCSIshi(RCScons(R', C), R, n + 1) of RCSI(C, R, n)
propdef RCSI0(C:rcs, R:rc) = [n:nat] RCSI(C, R, n)
// typing interpretations
dataprop TPI(rcs, tp, rc, int) =
| {C:rcs, T:tp, R:rc, n:nat}
TPIvar(C, TPvar n, R, 0) of (RCSI(C, R, n))
| {C:rcs, T1:tp, T2:tp, R1:rc, R2:rc, n1:nat, n2:nat}
TPIfun(C, TPfun(T1, T2), RCFUN0(R1,R2), n1+n2+1) of
(TPI(C, T1, R1, n1), TPI(C, T2, R2, n2))
| {C:rcs, T:tp, RF:rc->rc, n:nat}
TPIall(C, TPall(T), RCALL0(RF), n+1) of
({R:rc} TPI(RCScons(R, C), T, RF R, n))
propdef TPI0(C:rcs, T:tp, R:rc) = [n:nat] TPI(C, T, R, n)
// prop for equality of predicates on terms
dataprop RCEQ(rc, rc) =
{R:rc} RCEQ(R, R)
// prop for proofs that a sequence of predicates is a sequence of candidates
dataprop RCS(rcs, int) =
| RCSnil(RCSnil, 0)
| {R:rc, C:rcs, n:nat}
RCScons(RCScons(R, C), n+1) of (RC R, RCS(C, n))
propdef RCS0 (C: rcs) = [n:nat] RCS (C, n)
// lookup proof that a predicate is a candidate
prfun getRC {R:rc, C:rcs, n:nat} ..
(rcsi : RCSI(C, R, n), rcs : RCS0 C) : RC R = case* rcsi of
| RCSIone() =>
(case* rcs of
| RCScons(rc, rcs') => rc)
| RCSIshi(rcsi') =>
(case* rcs of
| RCScons(rc, rcs') => getRC(rcsi', rcs'))
// the interpretation of a type, under an assignment of candidates to type
// variables, is a candidate
prfun tpi_is_rc {C:rcs, T:tp, R:rc, n:nat} ..
(rcs: RCS0 C, tpi: TPI(C, T, R, n)): RC(R) = case* tpi of
| TPIvar(inr) => getRC(inr, rcs)
| TPIfun(tpi1, tpi2) =>
rcfun_is_rc(tpi_is_rc(rcs, tpi1), tpi_is_rc(rcs, tpi2))
| TPIall{_, F, RF, _}(tpif) =>
let
prfn rcf {R1:rc} (rc:RC(R1)) : RC(RF R1) =
tpi_is_rc(RCScons(rc, rcs), tpif)
in
rcall_is_rc(rcf)
end
// contexts/typed-substitutions
datasort ctx = CTXnil
| CTXcons of (tm, tp, ctx)
// dynamic representation for types, the index rcs is used only as a bound
// on deBruijn indices, note that R in the var case is arbitrary
dataprop TP(rcs, tp, int) =
| {C:rcs, T:tp, R:rc, n:nat}
TPvar(C, TPvar n, 0) of RCSI(C, R, n)
| {T1:tp, T2:tp, n1:nat, n2:nat, C:rcs}
TPfun(C, TPfun(T1, T2), n1+n2+1) of
(TP(C, T1, n1), TP(C, T2, n2))
| {T:tp, n:nat, C:rcs}
TPall(C, TPall T, n+1) of
({R:rc} TP(RCScons(R, C), T, n))
propdef TP0(C:rcs, T:tp) = [n:nat] TP(C, T, n)
// INCTX(t, T, G, n) encodes (t : T) in G at position n
dataprop INCTX(tm, tp, ctx, int) =
| {t:tm, T:tp, G:ctx}
INCTXone(t, T, CTXcons(t, T, G), 0)
| {t:tm, t':tm, T:tp, T':tp, G:ctx, n:nat}
INCTXshi(t, T, CTXcons(t', T', G), n+1) of
INCTX(t, T, G, n)
// (t : T) in G
propdef INCTX0(t:tm, T:tp, G:ctx) = [n:nat] INCTX(t, T, G, n)
// list of types, serves as a substitution for deBruijn indices
datasort tps = TPSnil | TPScons of (tp, tps)
// TPSHI(T, T', i) means T' is T with deBruijn indices >= i shifted up one
dataprop TPSHI (tp, tp, int) =
| {i:nat, l:nat | i >= l} TPSHIvargte (TPvar i, TPvar (i+1), l)
| {i:nat, l:nat | i < l} TPSHIvarlt (TPvar i, TPvar i, l)
| {T:tp, T':tp, l:nat}
TPSHIall (TPall T, TPall T', l) of TPSHI (T, T', l+1)
| {T1:tp, T2:tp, T1':tp, T2':tp, l:nat}
TPSHIfun (TPfun(T1, T2), TPfun(T1', T2'), l) of
(TPSHI(T1, T1', l), TPSHI(T2, T2', l))
// shift all terms in a context
dataprop SHICTX(ctx, ctx, int) =
| SHICTXnil(CTXnil, CTXnil, 0)
| {t:tm, T:tp, T':tp, G:ctx, G':ctx, n:nat}
SHICTXcons(CTXcons(t, T, G), CTXcons(t, T', G'), n+1) of
(TPSHI(T, T', 0), SHICTX(G, G', n))
propdef SHICTX0(G:ctx, G':ctx) = [n:nat] SHICTX(G, G', n)
// shift all indices in the types in a substitution
dataprop SUBSTSHI (tps, tps) =
| SUBSTSHInil (TPSnil, TPSnil)
| {S:tps, S':tps, T:tp, T':tp}
SUBSTSHImore (TPScons (T, S), TPScons (T', S')) of
(SUBSTSHI (S, S'), TPSHI (T, T', 0))
// INTPS(T, S, i) means T is at index i in substitution S
dataprop INTPS(tp, tps, int) =
| {T:tp, S:tps}
INTPSone(T, TPScons(T, S), 0)
| {T:tp, T':tp, S:tps, n:nat}
INTPSshi(T, TPScons(T', S), n+1) of INTPS(T, S, n)
// dynamic representation of substitutions
dataprop TPS(rcs, tps, int) =
| {C:rcs}
TPSnil(C, TPSnil, 0)
| {C:rcs, T:tp, S:tps, n:nat, m:nat}
TPScons(C, TPScons(T, S), n+1) of (TP(C, T, m), TPS(C, S, n))
// sequence of type interpretations
dataprop TPIS(rcs, tps, rcs, int) =
| {C:rcs}
TPISnil(C, TPSnil, RCSnil, 0)
| {C:rcs, T:tp, S:tps, RS:rcs, R:rc, n:nat}
TPIScons(C, TPScons(T, S), RCScons(R, RS), n+1) of
(TPI0(C, T, R), TPIS(C, S, RS, n))
// substitution on types
dataprop SUBST(tp, int, tp, tp, int) =
| {T:tp, n:nat}
SUBSTvar_eq(T, n, TPvar n, T, 0)
| {T:tp, n:nat, m:nat | m < n}
SUBSTvar_gt(T, m, TPvar n, TPvar (n-1), 0)
| {T:tp, n:nat, m:nat | m > n}
SUBSTvar_lt(T, m, TPvar n, TPvar n, 0)
| {T:tp, T1:tp, T2:tp, T1':tp, T2':tp, n1:nat, n2:nat, m:nat}
SUBSTfun(T, m, TPfun(T1, T2), TPfun(T1', T2'), n1+n2+1) of
(SUBST(T, m, T1, T1', n1), SUBST(T, m, T2, T2', n2))
| {T:tp, T':tp, T1:tp, T1':tp, m:nat}
SUBSTall(T, m, TPall(T1), TPall(T1'), m+1) of
(SUBST(T', m+1, T1, T1', m), TPSHI(T, T', 0))
// substitute into first index
propdef SUBST0(T2:tp, T1:tp, T1':tp) = [n:nat] SUBST(T2, 0, T1, T1', n)
// typing derivations
dataprop DER(rcs, ctx, tm, tp, int) =
| {C:rcs, G:ctx, t:tm, T:tp, n:nat}
DERvar(C, G, t, T, 0) of (INCTX(t, T, G, n), TP0(C, T))
| {C:rcs, G:ctx, t1:tm, t2:tm, T1:tp, T2:tp, n1:nat, n2:nat}
DERapp(C, G, TMapp(t1, t2), T2, n1+n2+1) of
(DER(C, G, t1, TPfun(T1, T2), n1), DER(C, G, t2, T1, n2))
| {C:rcs, G:ctx, f:tm->tm, T1:tp, T2:tp, n:nat}
DERlam(C, G, TMlam(f), TPfun(T1, T2), n+1) of
(TP0(C, T1), {x:tm} DER(C, CTXcons(x, T1, G), f x, T2, n))
| {C:rcs, G:ctx, G':ctx, t:tm, T:tp, n:nat, m:nat}
DERtabs(C, G, t, TPall(T), n+1) of
({R:rc} DER(RCScons(R, C), G', t, T, n), SHICTX(G, G', m))
| {C:rcs, G:ctx, t:tm, T1:tp, T2:tp, T:tp, n:nat}
DERtapp(C, G, t, T, n+1) of
(DER(C, G, t, TPall(T1), n), TP0(C, T2), SUBST0(T2, T1, T))
propdef DER0(C:rcs, G:ctx, t:tm, T:tp) = [n:nat] DER(C, G, t, T, n)
// insert a predicate into a list of predicates at a given position
dataprop RCSINS(rcs, rc, rcs, int) =
| {C:rcs, C':rcs, R:rc}
RCSINSone(C, R, RCScons(R, C), 0)
| {C:rcs, C':rcs, R:rc, R':rc, n:nat}
RCSINSshi(RCScons(R, C), R', RCScons(R, C'), n+1) of
RCSINS(C, R', C', n)
// environments, which interpret contexts, provide proofs that each term
// in a context is in the candidate that interprets its given type
dataprop ETA(rcs, ctx, int) =
| {C:rcs}
ETAnil(C, CTXnil, 0)
| {C:rcs, t:tm, T:tp, G:ctx, R:rc, n:nat, m:nat}
ETAcons(C, CTXcons(t, T, G), n+1) of
(TPI(C, T, R, m), R(t), ETA(C, G, n))
// lookup a term in an environment, getting a proof that the term is in the
// appropriate candidate
prfun getR {C:rcs, G:ctx, n:nat, t:tm, T:tp, m:nat} ..
(eta : ETA(C, G, n),
inc : INCTX(t, T, G, m))
: [R:rc] '(TPI0(C, T, R), R(t)) = case* eta of
| ETAnil() =/=> (case* inc of INCTXone() => '(eta, inc))
| ETAcons(tpi, r, eta') =>
(case* inc of
| INCTXone() => '(tpi, r)
| INCTXshi(inc') => getR(eta', inc'))
(* weakening on type interpretations *)
// shift a variable after the insertion point
prfun rcsi_gte {C:rcs, C':rcs, R:rc, R':rc, n:nat, m:nat | n >= m} ..
(rcsi : RCSI(C, R, n), rcsins : RCSINS(C, R', C', m))
: RCSI(C', R, n+1) = case* rcsins of
| RCSINSone() => RCSIshi(rcsi)
| RCSINSshi(rcsins') =>
let
prval RCSIshi(rcsi') = rcsi
in
RCSIshi(rcsi_gte(rcsi', rcsins'))
end
// don't shift a variable before the insertion point
prfun rcsi_lt {C:rcs, C':rcs, R:rc, R':rc, n:nat, m:nat | n < m} ..
(rcsi : RCSI(C, R, n), rcsins : RCSINS(C, R', C', m))
: RCSI(C', R, n) = case* rcsins of
| RCSINSshi(rcsins') =>
(case* rcsi of
| RCSIone() => RCSIone()
| RCSIshi(rcsi') => RCSIshi(rcsi_lt(rcsi', rcsins')))
// shift a type at an insertion point
prfun shi_tpi {C:rcs, C':rcs, T:tp, T':tp, R:rc, R':rc, n:nat, m:nat} ..
(tpi : TPI(C, T, R, n),
tpshi : TPSHI(T, T', m),
rcsins : RCSINS(C, R', C', m))
: TPI(C', T', R, n) = case* tpi of
| TPIvar(rcsi) =>
(case* tpshi of
| TPSHIvargte() => TPIvar(rcsi_gte(rcsi, rcsins))
| TPSHIvarlt() => TPIvar(rcsi_lt(rcsi, rcsins)))
| TPIfun(tpi1, tpi2) =>
let
prval TPSHIfun(tpshi1, tpshi2) = tpshi
prval tpi1' = shi_tpi(tpi1, tpshi1, rcsins)
prval tpi2' = shi_tpi(tpi2, tpshi2, rcsins)
in
TPIfun(tpi1', tpi2')
end
| TPIall(tpif) =>
let
prval TPSHIall(tpshi') = tpshi
in
TPIall(lam {R:rc} => shi_tpi(tpif{R}, tpshi', RCSINSshi(rcsins)))
end
// unshift a variable after the insertion point
prfun rcsi_unshi_gt {C:rcs, C':rcs, R:rc, R':rc, n:nat, m:nat | n > m} ..
(rcsi : RCSI(C', R, n), rcsins : RCSINS(C, R', C', m))
: RCSI(C, R, n-1) = case* rcsins of
| RCSINSone() =>
let
prval RCSIshi(rcsi') = rcsi
in
rcsi'
end
| RCSINSshi(rcsins') =>
let
prval RCSIshi(rcsi') = rcsi
in
RCSIshi(rcsi_unshi_gt(rcsi', rcsins'))
end
// unshift context of a variable before the insertion point
prfun rcsi_unshi_lt {C:rcs, C':rcs, R:rc, R':rc, n:nat, m:nat | n < m} ..
(rcsi : RCSI(C', R, n), rcsins : RCSINS(C, R', C', m))
: RCSI(C, R, n) = case* rcsins of
| RCSINSshi(rcsins') =>
(case* rcsi of
| RCSIone() => RCSIone()
| RCSIshi(rcsi') => RCSIshi(rcsi_unshi_lt(rcsi', rcsins')))
prfun tpi_insert {C:rcs, C':rcs, n:nat, R:rc, R':rc} ..
(tpi : TPI0(C', TPvar n, R),
ins : RCSINS(C, R', C', n)) : RCEQ(R, R') = case* ins of
| RCSINSone() =>
let
prval TPIvar(RCSIone()) = tpi
in
RCEQ()
end
| RCSINSshi(ins') =>
let
prval TPIvar(RCSIshi(rcsi)) = tpi
in
tpi_insert(TPIvar(rcsi), ins')
end
// substitution on type interpretations
prfun tpi_subst {C:rcs, S:tps, T:tp, T1:tp, T2:tp, R:rc,
R':rc, RS:rcs, C':rcs, m:nat, n1:nat, n2:nat, l:nat} ..
(sub : SUBST(T2, n1, T1, T, n2),
tpi2 : TPI(C, T2, R, l),
ins : RCSINS(C, R, C', n1),
tpi1 : TPI(C', T1, R', m))
: TPI0(C, T, R') = case* tpi1 of
| TPIvar(rcsi) =>
(case* sub of
| SUBSTvar_eq() =>
let
prval RCEQ() = tpi_insert(tpi1, ins)
in
tpi2
end
| SUBSTvar_lt() => TPIvar(rcsi_unshi_lt(rcsi, ins))
| SUBSTvar_gt() => TPIvar(rcsi_unshi_gt(rcsi, ins)))
| TPIfun(tpi1', tpi2') =>
let
prval SUBSTfun(sub1, sub2) = sub
prval tpi1'' = tpi_subst(sub1, tpi2, ins, tpi1')
prval tpi2'' = tpi_subst(sub2, tpi2, ins, tpi2')
in
TPIfun(tpi1'', tpi2'')
end
| TPIall(tpf) =>
let
prval SUBSTall(sub', tpshi) = sub
in
TPIall(lam {R:rc} =>
tpi_subst(sub', shi_tpi(tpi2, tpshi,
RCSINSone()), RCSINSshi ins, tpf{R}))
end
// we will prove substitution on types using substitution on type
// interpretations, first we show that TP(C, T, n) only needs the length of C
dataprop RCSALTER(rcs, rc, rc, rcs, int) =
| {R:rc, C:rcs, R':rc}
RCSALTERone(RCScons(R, C), R, R', RCScons(R',C), 0)
| {R:rc, C:rcs, R1:rc, R1':rc, C':rcs, n:nat}
RCSALTERshi(RCScons(R, C), R1, R1', RCScons(R, C'), n+1) of
RCSALTER(C, R1, R1', C', n)
// the exact identity of the R's is irrelevent to TP
prfun tp_rcs_arbitrary {R:rc, R':rc, C:rcs, C':rcs, T:tp, m:nat, n:nat} ..
(tp : TP(C, T, m),
alt : RCSALTER(C, R, R', C', n))
: TP(C', T, m) = case* tp of
| TPvar(rcsi) =>
let
prfun var_aux {C:rcs, R:rc, C':rcs, R1:rc, R1':rc, n:nat, m:nat} ..
(rcsi : RCSI(C, R, n),
alt : RCSALTER(C, R1, R1', C', m)) : [R:rc] RCSI(C', R, n) =
case* alt of
| RCSALTERone() =>
(case* rcsi of
| RCSIone() => RCSIone()
| RCSIshi(rcsi) => RCSIshi(rcsi))
| RCSALTERshi(alt') =>
(case* rcsi of
| RCSIone() => RCSIone()
| RCSIshi(rcsi') => RCSIshi(var_aux(rcsi', alt')))
prval #[R:rc] rcsi' = var_aux(rcsi, alt)
in
TPvar(rcsi')
end
| TPfun(tp1, tp2) =>
TPfun(tp_rcs_arbitrary (tp1, alt), tp_rcs_arbitrary (tp2, alt))
| TPall(tpf) =>
TPall(lam {R:rc} => tp_rcs_arbitrary(tpf{R}, RCSALTERshi(alt)))
// need higher-order pattern matching for this
dynprf hopat_lift : {C:rcs, m:nat, T:tp}
({R:rc} [R':rc] TPI(RCScons(R, C), T, R', m))
-> [RF:rc->rc] {R:rc} TPI(RCScons(R, C), T, RF R, m)
prfun tp_to_tpi {C:rcs, T:tp, n:nat} ..
(tp : TP(C, T, n))
: [R:rc] TPI(C, T, R, n) = case* tp of
| TPvar(inr) => TPIvar(inr)
| TPfun(tp1, tp2) => TPIfun(tp_to_tpi(tp1), tp_to_tpi(tp2))
| TPall(tpf) =>
let
prval tpif = hopat_lift(lam {R:rc} => tp_to_tpi(tpf{R}))
in
TPIall(tpif)
end
// the structure of TPI is the same as TPI
prfun tpi_to_tp {C:rcs, T:tp, R:rc, n:nat} ..
(tpi : TPI(C, T, R, n)) : TP(C, T, n) = case* tpi of
| TPIvar(rcsi) => TPvar(rcsi)
| TPIfun(tpi1, tpi2) => TPfun(tpi_to_tp tpi1, tpi_to_tp tpi2)
| TPIall(tpif) => TPall(lam {R:rc} => tpi_to_tp(tpif{R}))
// substitution on TPI subsumes substitution on TP
prfn tp_subst {C:rcs, T:tp, T1:tp, T2:tp, R:rc, m:nat}
(sub : SUBST0(T2, T1, T),
tp2 : TP0(C, T2),
tp1 : TP(RCScons(R, C), T1, m))
: TP0(C, T) =
let
prval #[R':rc] tpi2 = tp_to_tpi(tp2)
prval tp1' = tp_rcs_arbitrary(tp1, RCSALTERone{R, C, R'}())
prval tpi1 = tp_to_tpi(tp1')
in
tpi_to_tp (tpi_subst (sub, tpi2, RCSINSone(), tpi1))
end
// derivations determine the type in the typing judgment
prfun der_to_tp {C:rcs, G:ctx, t:tm, T:tp, n:nat} ..
(der : DER(C, G, t, T, n)) : [m:nat] TP(C, T, m) = case* der of
| DERvar(inc, tp) => tp
| DERapp(der1, der2) =>
let
prval TPfun(tp1, tp2) = der_to_tp(der1)
in
tp2
end
| DERlam(tp, derf) => TPfun(tp, der_to_tp(derf))
| DERtabs(dertf, ctxshi) => TPall(lam {R:rc} => der_to_tp(dertf{R}))
| DERtapp(der', tp, sub) =>
let
prval TPall(dertf) = der_to_tp(der')
in
tp_subst(sub, tp, dertf)
end
// shift an environment
prfun shi_eta {R:rc, C:rcs, C':rcs, G:ctx, G':ctx, m:nat, n:nat} ..
(eta: ETA(C, G, m), shi: SHICTX(G, G', n))
: ETA(RCScons(R, C), G', m) = case* eta of
| ETAnil() =>
let
prval SHICTXnil() = shi
in
ETAnil()
end
| ETAcons(tpi, r, eta') =>
let
prval SHICTXcons(shitp, shi') = shi
in
ETAcons(shi_tpi(tpi, shitp, RCSINSone()), r, shi_eta(eta', shi'))
end
// we need higher-order pattern matching to prove this
dynprf rceq_eta_contract : {RF:rc->rc, RF':rc->rc, n:nat, m:nat}
({X:rc} RCEQ(RF X, RF' X)) -> RCEQ(RCALL0(RF), RCALL0(RF'))
// RCSI is a partial function from the first and third index to the second
prfun rcsi_functional {C:rcs, R:rc, R':rc, n:nat} ..
(rcsi1 : RCSI(C, R, n),
rcsi2 : RCSI(C, R', n))
: RCEQ(R, R') = case* (rcsi1,rcsi2) of
| (RCSIone(), RCSIone()) => RCEQ()
| (RCSIshi(rcsi1'), RCSIshi(rcsi2')) => rcsi_functional(rcsi1', rcsi2')
// TPI is a partial function from the first 2 indices to the second 2
prfun tpi_functional {C:rcs, T:tp, R:rc, R':rc, n:nat, m:nat} ..
(tpi1 : TPI(C, T, R, n),
tpi2 : TPI(C, T, R', m))
: [n == m] RCEQ(R, R') = case* tpi1 of
| TPIvar(rcsi1) =>
let
prval TPIvar(rcsi2) = tpi2
in
rcsi_functional(rcsi1, rcsi2)
end
| TPIfun(tpi11, tpi12) =>
let
prval TPIfun(tpi21, tpi22) = tpi2
prval RCEQ() = tpi_functional(tpi11, tpi21)
prval RCEQ() = tpi_functional(tpi12, tpi22)
in
RCEQ()
end
| TPIall{_, _, RF, n1}(ftpi1) =>
let
prval TPIall{_, _, RF', n2}(ftpi2) = tpi2
prval frceq = lam {X:rc} => tpi_functional(ftpi1{X}, ftpi2{X})
prval rceq = rceq_eta_contract{RF, RF', n1, n2}(frceq)
in
rceq
end
// main lemma for reducibility candidates
prfun der_rc_lemma {G:ctx, t:tm, T:tp, n:nat, C:rcs, m:nat} ..
(der : DER(C, G, t, T, n),
eta : ETA(C, G, m),
rcs : RCS0 C)
: [R:rc] '(TPI0(C, T, R), R(t)) = case* der of
| DERvar(inctx, tp) => getR(eta, inctx)
| DERapp(der1, der2) =>
let
prval '(tpif, r1) = der_rc_lemma(der1, eta, rcs)
prval '(tpi, r2) = der_rc_lemma(der2, eta, rcs)
prval TPIfun(tpi1, tpi2) = tpif
prval RCFUN(rcf) = r1
prval RCEQ() = tpi_functional(tpi, tpi1)
in
'(tpi2, rcf r2)
end
| DERlam{_, _, f, _, _, _}(tp, derf) =>
let
prval tpi = tp_to_tpi(der_to_tp(der))
prval TPIfun{_, _, _, R1, R2, _, _}(tpi1, tpi2) = tpi
prval rc1 = tpi_is_rc(rcs, tpi1)
prval rc2 = tpi_is_rc(rcs, tpi2)
prfn rcimp {t:tm} (r1:R1(t)) : R2(f t) =
let
prval '(tpi2', r2) = der_rc_lemma(derf{t},
ETAcons(tpi1, r1, eta),
rcs)
prval RCEQ() = tpi_functional(tpi2, tpi2')
in
r2
end
in
'(tpi, abs_lemma(rc1, rc2, rcimp))
end
| DERtabs(dertf, ctxshi) =>
let
prval tpi = tp_to_tpi(der_to_tp(der))
prval TPIall{_, _, RF, _}(tpif) = tpi
prfn rcf {R:rc} (rc: RC R) : (RF R t) =
let
prval rcs' = RCScons(rc, rcs)
prval eta' = shi_eta(eta, ctxshi)
prval '(tpi1, rfr) = der_rc_lemma(dertf{R}, eta', rcs')
prval RCEQ() = tpi_functional(tpi1, tpif{R})
in
rfr
end
in
'(tpi, RCALL(rcf))
end
| DERtapp{C, G, t, T1, T2, T, n}(derall, tp, subst) =>
let
prval #[R:rc] tpi = tp_to_tpi(tp)
prval '(tpiall, rcall) = der_rc_lemma(derall, eta, rcs)
prval TPIall(tpif) = tpiall
prval RCALL(rcf) = rcall
prval rc = tpi_is_rc(rcs, tpi)
prval tpi' = tpi_subst(subst, tpi, RCSINSone(), tpif{R})
in
'(tpi', rcf rc)
end
// all terms with a type in the empty context are in the interpretation of
// the type assigned given
prfn der_rc {t:tm, T:tp} (der : DER0(RCSnil, CTXnil, t, T))
: [R:rc] '(TPI0(RCSnil, T, R), R(t)) =
der_rc_lemma (der, ETAnil(), RCSnil())
// all terms with a type in the empty context are SN
prfn der_sn {t:tm, T:tp} (der : DER0(RCSnil, CTXnil, t, T)) : SN0(t) =
let
prval '(tpi, r) = der_rc(der)
prval '(cr1, cr2, cr3) = tpi_is_rc(RCSnil, tpi)
in
cr1 r
end