Summer school 2008:Typed arithmetic expressions with sums 2

From The Twelf Project
Jump to: navigation, search
This is Literate Twelf
Code: here
Status: %% OK %%
Output: here.
Summer school 2008
Previous: Typed arithmetic expressions


Arithmetic expressions with pairs and sums. (This solution involves output factoring, but no identity types. Dan posted a solution involving identity types, and Chris posted a solution that avoids output factoring.)

Numbers and strings are unchanged.

Typed expressions

Add a type for disjoint sums:

tp : type.				%name tp T.
number : tp.
string : tp.
prod   : tp -> tp -> tp.
sum    : tp -> tp -> tp.

Add injections as values, and case as an expression.

val : tp -> type.			%name val V.  %postfix 1 val.
num : nat -> number val.
lit : str -> string val.
pair : T val -> U val -> (prod T U) val.
inl : T val -> (sum T U) val.
inr : U val -> (sum T U) val.

exp : tp -> type.			%name exp E.  %postfix 1 exp.
ret : T val -> T exp.
plus : number exp -> number exp -> number exp.
append : string exp -> string exp -> string exp.
let : T exp -> (T val -> U exp) -> U exp.
fst : (prod T U) exp -> T exp.
snd : (prod T U) exp -> U exp.

For technical reasons, we bundle the branches of the case into a separate term with type cases; this makes the termination order more evident to Twelf. An element of "cases T U V" is the branches for a "sum T U" whose result has tp "V".

cases : tp -> tp -> tp -> type.
cases/i : (T val -> V exp) -> (U val -> V exp) -> cases T U V.
case : (sum T U) exp -> cases T U V -> V exp.

Add eval cases for case.

eval : T exp -> T val -> type.
%mode eval +E1 -E2.

eval/val
   : eval (ret V) V.

eval/plus
   : eval (plus E1 E2) (num N)
      <- eval E1 (num N1)
      <- eval E2 (num N2)
      <- add N1 N2 N.

eval/append
   : eval (append E1 E2) (lit S)
      <- eval E1 (lit S1)
      <- eval E2 (lit S2)
      <- cat S1 S2 S.

eval/let
   : eval (let E1 ([x] E2 x)) A
      <- eval E1 V
      <- eval (E2 V) A.

eval/fst
   : eval (fst E) A
      <- eval E (pair A _).

eval/snd
   : eval (snd E) B
      <- eval E (pair _ B).

For "case" evaluation, we need an auxiliary relation "evalcase" to branch on inl vs. inr (output factoring).

evalcase : (sum T U) val -> cases T U S -> S val -> type.
%mode evalcase +V +Cases -A.

eval/case
  : eval (case E Cases) A
      <- eval E V
      <- evalcase V Cases A.

evalcase/inl
   : evalcase (inl V1) (cases/i ([x] F1 x) ([y] F2 y)) A
      <- eval (F1 V1) A.

evalcase/inr
   : evalcase (inr V2) (cases/i ([x] F1 x) ([y] F2 y)) A
      <- eval (F2 V2) A.

Then we use mutual induction to show evaluation total.

%worlds () (eval _ _) (evalcase _ _ _).
%total (E Cases) (eval E _) (evalcase _ Cases _).
Summer school 2008
Previous: Exercises 1