module arith1 where
open import Agda.Primitive renaming (Set to Type)
data Exp : Set where
true : Exp
false : Exp
zero : Exp
suc : Exp -> Exp
if : Exp -> Exp -> Exp -> Exp
pred : Exp -> Exp
isZ : Exp -> Exp
exp0 : Exp
exp0 = if (isZ zero) zero (pred zero)
data _=>_ : Exp -> Exp -> Set where
=>true : {e0 e1 : Exp} ->
if true e0 e1 => e0
=>false : {e0 e1 : Exp} ->
if false e0 e1 => e1
=>isZ0 :
isZ zero => true
=>isZS : {e : Exp} ->
isZ (suc e) => false
=>pred0 :
pred zero => zero
=>predS : {e : Exp} ->
pred (suc e) => e
=>if : {e e' e0 e1 : Exp} -> e => e' ->
if e e0 e1 => if e' e0 e1
=>suc : {e e' : Exp} -> e => e' ->
suc e => suc e'
=>isZ : {e e' : Exp} -> e => e' ->
isZ e => isZ e'
=>pred : {e e' : Exp} -> e => e' ->
pred e => pred e'
test=> : exp0 => if true zero (pred zero)
test=> = =>if =>isZ0
data _=>*_ : Exp -> Exp -> Set where
nil : {e : Exp} -> e =>* e
cons : {e0 e1 e2 : Exp} -> e0 => e1 -> e1 =>* e2 -> e0 =>* e2
isTrans : {e0 e1 e2 : Exp} -> e0 =>* e1 -> e1 =>* e2 -> e0 =>* e2
isTrans nil q = q
isTrans (cons x p) q = cons x (isTrans p q)
oneStep : {e0 e1 : Exp} -> e0 => e1 -> e0 =>* e1
oneStep x = cons x nil
test=>* : exp0 =>* zero
test=>* = cons (=>if =>isZ0) (cons =>true nil)
data isValnat : Exp -> Set where
isValnat0 : isValnat zero
isValnatS : {e : Exp} -> isValnat e -> isValnat (suc e)
data isVal : Exp -> Set where
Valtrue : isVal true
Valfalse : isVal false
Valnat : {e : Exp} -> isValnat e -> isVal e
data Nat : Set where
zero : Nat
suc : Nat -> Nat
encodeN : Nat -> Exp
encodeN zero = zero
encodeN (suc n) = suc (encodeN n)
encodeVal : (n : Nat) -> isValnat (encodeN n)
encodeVal zero = isValnat0
encodeVal (suc n) = isValnatS (encodeVal n)
decodeN : {e : Exp} -> isValnat e -> Nat
decodeN isValnat0 = zero
decodeN (isValnatS v) = suc (decodeN v)
record Σ (A : Type) (B : A -> Type) : Type where
constructor _,_
field
fst : A
snd : B fst
open Σ
infixr 5 _,_
_×_ : Type -> Type -> Type
A × B = Σ A (λ _ -> B)
infixr 5 _×_
data _+_ (A B : Type) : Type where
inl : A -> A + B
inr : B -> A + B
progress : Exp -> Set
progress e = isVal e + Σ Exp (λ e1 -> e => e1)
data ⊥ : Set where
¬ : Set -> Set
¬ A = A -> ⊥
explosion : {A : Set} -> ⊥ -> A
explosion ()
isStuck : Exp -> Set
isStuck e = ¬ (progress e)
remark : isStuck (isZ true)
remark (inl (Valnat ()))
remark (inr (_ , =>isZ ()))
data Typ : Set where
nat : Typ
bool : Typ
data _::_ : Exp -> Typ -> Set where
typet :
true :: bool
typef :
false :: bool
type0 :
zero :: nat
typeS : {e : Exp} -> e :: nat ->
suc e :: nat
typep : {e : Exp} -> e :: nat ->
pred e :: nat
typeZ : {e : Exp} -> e :: nat ->
isZ e :: bool
typeif : {T : Typ} -> {e e0 e1 : Exp} ->
e :: bool -> e0 :: T -> e1 :: T ->
if e e0 e1 :: T
exp0N : exp0 :: nat
exp0N = typeif (typeZ type0) type0 (typep type0)
data _≡_ {A : Set} (x : A) : A -> Set where
refl : x ≡ x
uniqueness : (e : Exp) -> {T T' : Typ} -> e :: T -> e :: T' -> T ≡ T'
uniqueness true typet typet = refl
uniqueness false typef typef = refl
uniqueness zero type0 type0 = refl
uniqueness (suc _) (typeS _) (typeS _) = refl
uniqueness (pred _) (typep _) (typep _) = refl
uniqueness (isZ _) (typeZ _) (typeZ _) = refl
uniqueness (if _ e0 _) (typeif _ T0 _) (typeif _ T0' _) = uniqueness e0 T0 T0'
preservation : {e e' : Exp} -> {T : Typ} -> e :: T -> e => e' -> e' :: T
preservation (typeif typet eT0 eT1) =>true = eT0
preservation (typeif typef eT0 eT1) =>false = eT1
preservation (typeZ type0) =>isZ0 = typet
preservation (typeZ (typeS eT)) =>isZS = typef
preservation (typep type0) =>pred0 = type0
preservation (typep (typeS eT)) =>predS = eT
preservation (typeif eT eT0 eT1) (=>if ee') = typeif (preservation eT ee') eT0 eT1
preservation (typeS eT) (=>suc ee') = typeS (preservation eT ee')
preservation (typeZ eT) (=>isZ ee') = typeZ (preservation eT ee')
preservation (typep eT) (=>pred ee') = typep (preservation eT ee')
exp1 : Exp
exp1 = if true zero false
remark7 : exp1 => zero
remark7 = =>true
remark8 : ¬ (exp1 :: nat)
remark8 (typeif typet type0 ())
data isBoolVal : Exp -> Set where
isTrue : isBoolVal true
isFalse : isBoolVal false
canon-bool : {e : Exp} -> e :: bool -> isVal e -> isBoolVal e
canon-bool _ Valtrue = isTrue
canon-bool _ Valfalse = isFalse
canon-bool () (Valnat isValnat0)
canon-bool () (Valnat (isValnatS _))
canon-nat : {e : Exp} -> e :: nat -> isVal e -> isValnat e
canon-nat () Valtrue
canon-nat () Valfalse
canon-nat _ (Valnat v) = v
if-val : {u e0 e1 : Exp} -> isBoolVal u -> progress (if u e0 e1)
if-val {e0 = e0} isTrue = inr (e0 , =>true)
if-val {e1 = e1} isFalse = inr (e1 , =>false)
pred-val : {u : Exp} -> isValnat u -> progress (pred u)
pred-val isValnat0 = inr (zero , =>pred0)
pred-val (isValnatS {e} _) = inr (e , =>predS)
isZ-val : {u : Exp} -> isValnat u -> progress (isZ u)
isZ-val isValnat0 = inr (true , =>isZ0)
isZ-val (isValnatS _) = inr (false , =>isZS)
typeprog-if : {u e0 e1 : Exp} -> u :: bool -> progress u -> progress (if u e0 e1)
typeprog-if uT (inl v) = if-val (canon-bool uT v)
typeprog-if {e0 = e0} {e1} uT (inr (u' , x)) = inr (if u' e0 e1 , =>if x)
typeprog-suc : {u : Exp} -> u :: nat -> progress u -> progress (suc u)
typeprog-suc uT (inl v) = inl (Valnat (isValnatS (canon-nat uT v)))
typeprog-suc uT (inr (u' , x)) = inr (suc u' , =>suc x)
typeprog-pred : {u : Exp} -> u :: nat -> progress u -> progress (pred u)
typeprog-pred uT (inl v) = pred-val (canon-nat uT v)
typeprog-pred uT (inr (u' , x)) = inr (pred u' , =>pred x)
typeprog-isZ : {u : Exp} -> u :: nat -> progress u -> progress (isZ u)
typeprog-isZ uT (inl v) = isZ-val (canon-nat uT v)
typeprog-isZ uT (inr (u' , x)) = inr (isZ u' , =>isZ x)
typeprog : {e : Exp} -> {T : Typ} -> e :: T -> progress e
typeprog typet = inl Valtrue
typeprog typef = inl Valfalse
typeprog type0 = inl (Valnat isValnat0)
typeprog (typeS eT) = typeprog-suc eT (typeprog eT)
typeprog (typep eT) = typeprog-pred eT (typeprog eT)
typeprog (typeZ eT) = typeprog-isZ eT (typeprog eT)
typeprog (typeif eT eT0 eT1) = typeprog-if eT (typeprog eT)
theorem : {e e' : Exp} -> {T : Typ} -> e :: T -> e =>* e' -> progress e'
theorem eT nil = typeprog eT
theorem eT (cons x q) = theorem (preservation eT x) q
=>normal : Exp -> Set
=>normal e = {e1 : Exp} -> ¬ (e => e1)
lem0 : {e : Exp} -> isValnat e -> =>normal e
lem0 isValnat0 ()
lem0 (isValnatS ie) (=>suc h) = lem0 ie h
lem1 : {e : Exp} -> isVal e -> =>normal e
lem1 Valtrue ()
lem1 Valfalse ()
lem1 (Valnat x) = lem0 x