Fun with Twelf
Jake Donham, Skydeck Inc.
What's Twelf?
Twelf is adependently-typedhigher-orderlogic programming languageand also aproof assistant
useful for proofs about programming languages
Outline
• Judgments, inference rules, derivations• Proof search, logic programming• Representing judgments, dependent types• Logic programs as proofs• Higher-order syntax, logic programming
What is a natural number?
N nat
____________z nat
N nat____________
s(N) nat
N is a natural number• a judgment• defined by inference rules
zero is a natural number
if N is a natural number
then N + 1 is a natural number
Inference rules
____________z nat
N nat____________
s(N) nat
axiom
premise(s)
conclusion
capital N is implicitly for all
Examples
zero is a nat
___________ z nat
2 is a nat
z nat_____________
s(z) nat_____________
s(s(z)) nat
derivations
Example?
s(s(xyzzy)) nat?
Example?
s(s(xyzzy)) nat?
nope, there is no derivation
(can we prove it?)
What is addition?
___________sum z N N
sum M N P_____________
sum s(M) N s(P)
0 + N = N
if M + N = P
then M + 1 + N = P + 1
Examples
sum 0 2 2__________sum 1 2 3__________sum 2 2 4
sum 0 3 3__________sum 1 3 4__________sum 2 3 5__________sum 3 3 6__________sum 4 3 7
Recap
o judgments are things for which we have proofo judgments are defined by inference ruleso derivations are proofs of a judgmento natural numbers and addition as judgments
next: proof search and logic programming
Searching for proof
does sum 2 3 5 hold?can we find a derivation?
__________sum z N N
sum M N P_____________
sum s(M) N s(P)
Searching for proof
does sum 2 3 5 hold?can we find a derivation?which rule(s) must the derivation end with?
__________sum z N N
sum M N P_____________
sum s(M) N s(P)
Searching for proof
does sum 2 3 5 hold?can we find a derivation?which rule(s) must the derivation end with?
sum 1 3 4________sum 2 3 5 ~ sum s(M) N s(P) [M = 1, N = 3, P = 4]
__________sum z N N
sum M N P_____________
sum s(M) N s(P)
Searching for proof
does sum 2 3 5 hold?can we find a derivation?which rule(s) must the derivation end with?
sum 0 3 3________sum 1 3 4 ~ sum s(M) N s(P) [M = 0, N = 3, P = 3]________sum 2 3 5 ~ sum s(M) N s(P) [M = 1, N = 3, P = 4]
__________sum z N N
sum M N P_____________
sum s(M) N s(P)
Searching for proof
does sum 2 3 5 hold?can we find a derivation?which rule(s) must the derivation end with?
________sum 0 3 3 ~ sum z N N [N = 3]________sum 1 3 4 ~ sum s(M) N s(P) [M = 0, N = 3, P = 3]________sum 2 3 5 ~ sum s(M) N s(P) [M = 1, N = 3, P = 4]
__________sum z N N
sum M N P_____________
sum s(M) N s(P)
Proof search with unification
does sum 2 3 P hold for any P?
__________sum z N N
sum M N P_____________
sum s(M) N s(P)
Proof search with unification
does sum 2 3 P hold for any P?
sum 1 3 P'_________sum 2 3 P ~ sum s(M) N s(P') [M=1, N=3, P=s(P')]
need to invent fresh variable P'
__________sum z N N
sum M N P_____________
sum s(M) N s(P)
Proof search with unification
does sum 2 3 P hold for any P?
sum 0 3 P''_________sum 1 3 P' ~ sum s(M) N s(P'') [M=0, N=3, P'=s(P'')]_________sum 2 3 P ~ sum s(M) N s(P') [M=1, N=3, P=s(P')]
__________sum z N N
sum M N P_____________
sum s(M) N s(P)
Proof search with unification
does sum 2 3 P hold for any P?_________sum 0 3 P'' ~ sum z N N [N = 3 = P'']_________sum 1 3 P' ~ sum s(M) N s(P'') [M=0, N=3, P'=s(P'')]_________sum 2 3 P ~ sum s(M) N s(P') [M=1, N=3, P=s(P')]
__________sum z N N
sum M N P_____________
sum s(M) N s(P)
Proof search with unification
does sum 2 3 P hold for any P?_________sum 0 3 P'' ~ sum z N N [N = 3 = P'']_________sum 1 3 P' ~ sum s(M) N s(P'') [M=0, N=3, P'=s(P'')]_________sum 2 3 P ~ sum s(M) N s(P') [M=1, N=3, P=s(P')]
now substitute to find P = s(P') = s(s(P'')) = 5
__________sum z N N
sum M N P_____________
sum s(M) N s(P)
Other modes
sum 2 N 5?
__________sum z N N
sum M N P_____________
sum s(M) N s(P)
Other modes
sum 2 N 5?_________sum 0 N 3 ~ sum z N N [N = 3]_________sum 1 N 4 ~ sum s(M) N s(P) [M=0, P=3]_________sum 2 N 5 ~ sum s(M) N s(P) [M=1, P=4]
which args are inputs vs. outputs - mode
__________sum z N N
sum M N P_____________
sum s(M) N s(P)
Branching, backtracking
sum M N 2?unifies with both rules
__________sum z N N
sum M N P_____________
sum s(M) N s(P)
Branching, backtracking
sum M N 2?unifies with both rules
[M=1, N=1]_________sum M' N 1 ~ sum z N N |
[M=0, N=2]________sum M N 2 ~ sum z N N |
[M=2, N=0]_________sum M'' N 0 ~ sum z N N________sum M' N 1 ~ sum s(M'') N s(P)
________sum M N 2 ~ sum s(M') N s(P)
__________sum z N N
sum M N P_____________
sum s(M) N s(P)
Recap
o interpret judgments as logic programso proof search gives rise to computationo unification of terms containing variableso viewing a judgment in different modeso branching, backtrackingo sum as a logic program
next: representing judgments in Twelf
Representing syntax
in OCaml:type nat = Z | S of nat
in Twelf:nat : type.z : nat.s : nat -> nat.
____________z nat
N nat____________
s(N) nat
Representing derivations
in OCaml:type sum = Sum_z of nat| Sum_s of nat * nat * nat * sum
__________sum z N N
sum M N P_____________
sum s(M) N s(P)
Representing derivations
in OCaml:type sum = Sum_z of nat| Sum_s of nat * nat * nat * sum
but what derivation doesSum_s(1, 2, 3, Sum_z 4)
represent? type sum is not adequate
__________sum z N N
sum M N P_____________
sum s(M) N s(P)
Dependent types
in Twelf:sum : nat -> nat -> nat -> type.sum_z : {N:nat} sum z N N.sum_s : {M:nat} {N:nat} {P:nat}sum M N P -> sum (s M) N (s P).
__________sum z N N
sum M N P_____________
sum s(M) N s(P)
Dependent types
in Twelf:sum : nat -> nat -> nat -> type.sum_z : {N:nat} sum z N N.sum_s : {M:nat} {N:nat} {P:nat}sum M N P -> sum (s M) N (s P).
• type sum M N P is indexed by M N P• dependent type (depends on terms)• indices let us express invariant• no inadequate terms
__________sum z N N
sum M N P_____________
sum s(M) N s(P)
Dependent types
in Twelf:sum : nat -> nat -> nat -> type.sum_z : {N:nat} sum z N N.sum_s : {M:nat} {N:nat} {P:nat}sum M N P -> sum (s M) N (s P).
or (with implicit arguments):
sum_z : sum z N N.sum_s : sum M N P -> sum (s M) N (s P).
__________sum z N N
sum M N P_____________
sum s(M) N s(P)
Twelf types as logic programs
in Twelf:
sum : nat -> nat -> nat -> type.sum_z : sum z N N.sum_s : sum s(M) N s(P)<- sum M N P.in OCaml:
let rec sum : (nat * nat) -> nat = function | Z, n -> n | S m, n -> S (sum (m, n))
Recap
o represent syntax by datatypeso represent derivations by datatypeso want adequate representationo OCaml type system is not rich enougho need dependent typeso interpret Twelf datatypes as logic programs
next: logic programs as proofs
A theorem about addition
addition is commutative M + N = N + M
A theorem about addition
addition is commutative M + N = N + M
but we have not said:o sum is a function
if sum M N P and sum M N P' then P = P'o sum is total
for all M, N there exists P where sum M N Po we haven't even defined equality
A theorem about addition
addition is commutative M + N = N + M
A theorem about addition
addition is commutative M + N = N + M
if sum M N P then sum N M P
A theorem about addition
addition is commutative M + N = N + M
if sum M N P then sum N M P
if you give me a derivation of sum M N PI will give you a derivation of sum N M P
A theorem about addition
addition is commutative M + N = N + M
if sum M N P then sum N M P
if you give me a derivation of sum M N PI will give you a derivation of sum N M P
function of type sum M N P -> sum N M PCurry-Howard correspondence
Addition is commutative
proof outline:• prove "right-handed" versions of sum rules
for all N, sum N z Nif sum M N P then sum M (s N) (s P)
• recurse down derivation of sum M N P• build it back up using right-handed rules
Addition is commutative
sum_z' : {N} sum N z N -> type.- : sum_z' z sum_z.- : sum_z' (s N') (sum_s D)<- sum_z' N' D.
sum_s' : sum M N P -> sum M (s N) (s P) -> type.- : sum_s' sum_z sum_z.- : sum_s' (sum_s D1) (sum_s D2)<- sum_s' D1 D2.
sum : nat -> nat -> nat -> type.sum_z : sum z N N.sum_s : sum M N P ->sum (s M) N (s P).
Addition is commutative
sum_z' : {N} sum N z N -> type.sum_s' : sum M N P -> sum M (s N) (s P) -> type.
sum_comm : sum M N P -> sum N M P -> type.- : sum_comm sum_z D<- sum_z' _ D.- : sum_comm (sum_s D1) D3<- sum_comm D1 D2<- sum_s' D2 D3.
sum : nat -> nat -> nat -> type.sum_z : sum z N N.sum_s : sum M N P ->sum (s M) N (s P).
Totality
only a proof if function is total - succeeds on all inputstotality = coverage + termination
sum_comm : sum M N P -> sum N M P -> type.%mode sum_comm +D1 -D2.
- : sum_comm sum_z ...- : sum_comm (sum_s D1) D3<- sum_comm D1 D2...%total (D1) (sum_comm D1 D2).
sum : nat -> nat -> nat -> type.sum_z : sum z N N.sum_s : sum M N P ->sum (s M) N (s P).
Recap
o programs are proofso functions from derivations to derivationso need adequacy of representationo need totalityo write proofs as Twelf logic programso we proved that sum is commutative
next: proofs about programming languages
Programming languages
a tiny programming language:
N nat________nat(N) exp
E1 exp E2 exp___________ E1 + E2 exp
E1 exp E2 exp______________let x = E1 in E2 exp
x is a bound variable in E2
Representing PLs
in OCaml:type exp =| Var of string| Nat of nat| Plus of exp * exp| Let of exp * string * exp
• no alpha-equivalence; choice of name matters• must implement scope, substitution manually• inadequate: what does Var "x" w/o Let represent?
N nat________
nat(N) exp
E1 exp E2 exp___________
E1 + E2 exp
E1 exp E2 exp______________
let x = E1 in E2 exp
Representing PLs
another try in OCaml:type exp =| Nat of nat| Plus of exp * exp| Let of exp * (exp -> exp)
• body of let is function that does substitution:let x = 1 in x + 2 == Let (Nat 1, (fun x -> Plus (x, Nat 2))• unbound var inadequacy goes away• functions that branch on arg, or raise exception?
N nat________
nat(N) exp
E1 exp E2 exp___________
E1 + E2 exp
E1 exp E2 exp______________
let x = E1 in E2 exp
Representing PLs
in Twelf:exp : type.nat : nat -> exp.plus : exp -> exp -> exp.let : exp -> (exp -> exp) -> exp.
• body of let is function that does substitution:let x = 1 in x + 2 == (let (nat 1) ([x] plus x (nat 2)))• Twelf functions are very weak, just templates• adequate, alpha-equivalence
N nat________
nat(N) exp
E1 exp E2 exp___________
E1 + E2 exp
E1 exp E2 exp______________
let x = E1 in E2 exp
Higher-order logic programming
count variables uses - e.g. count (let x = 1 in x + x) 2
count : exp -> nat -> type.
count_nat : count (nat _) z.
count_plus : count (plus E1 E2) C<- count E1 C1<- count E2 C2<- sum C1 C2 C.
Higher-order logic programming
count : exp -> nat -> type.
count_let : count (let E1 E2) C<- count E1 C1<- ({x:exp}{d:count x (s z)} count (E2 x) C2)<- sum C1 C2 C.• { } indicates scoped axioms (just for enclosed goal)• x is a fresh variable• substitute E2's bound variable with x• when we find x in E2 it gets a count of 1
Recap
• programming languages have scope and binding• want a convenient way to work with it• higher-order syntax representation• higher-order logic programming• only works because Twelf functions are weak
Twelf
this approach scales to realistic programming lanaguages:semantics and type safety proof for Standard ML: Lee, Crary, Harper Toward a Mechanized Metatheory of Standard ML http://www.cs.cmu.edu/~rwh/papers/tslf/full.pdf
formalized x86 arch. and type-safe assembly language: Crary, Sarkar Foundational Certified Code in a Metalogical Framework http://www.cs.cmu.edu/~crary/papers/2005/mafcc.pdf
Pointers
Pfenning, Logic Progamming course noteshttp://www.cs.cmu.edu/~fp/courses/lp/Pfenning, Computation and Deduction course noteshttp://www.cs.cmu.edu/~fp/courses/comp-ded/
Thanks for listening
questions?
Top Related