270 likes | 429 Views
Imperative Programming with Dependent Types. Hongwei Xi University of Cincinnati. A Wish List. We would like to have a programming language that should be simple and general support extensive error checking facilitate proofs of program properties
E N D
Imperative Programming with Dependent Types Hongwei Xi University of Cincinnati
A Wish List • We would like to have a programming language that should • be simple and general • support extensive error checking • facilitate proofs of program properties • possess correct and efficient implementation • ... ...
Reality • Invariably, there are many conflicts among this wish list • These conflicts must be resolved with careful attention to the needs of the user
Advantages of Types • Capturing errors at compile-time • Enabling compiler optimizations • Facilitating program verification • Serving as program documentation
Limitations of (Simple) Types • Not general enough • Many correct programs cannot be typed • Not specific enough • Many interesting properties cannot be captured
Dependent Types • Dependent types are types that are • more refined • dependent on the values of expressions • Examples • int(i): singleton type containing only integer i • <int> array(n): type for integer arrays of size n
Type System Design • A practically useful type system should be • Scalable • Applicable • Comprehensible • Unobtrusive • Flexible
Xanadu • Xanadu is a dependently typed imperative programming language with C-like syntax • The type of a variable in Xanadu can change during execution • The programmer may need to provide dependent type annotations for type-checking purpose
Early Design Decisions • Practical type-checking • Realistic programming features • Conservative extension • Pay-only-if-you-use policy
Examples of Dependent Types in Xanadu • int(a): singleton types containing the only integer equal to a, where a ranges over all integers • <‘a> array(a): types for arrays of size a in which all elements are of type ‘a, where a ranges over all natural numbers
Examples of Dependent Types in Xanadu • int(i,j) is defined as [a:int | i < a < j] int(a),that is, the sum of all types int(a) for i < a < j • int[i,j), int(i,j] , int[i,j] are defined similarly
A Xanadu Program {n:nat} unit init (int vec[n]) { var int ind, size;; size = arraysize(vec); invariant: [i:nat] (ind: int(i)) for (ind=0; ind<size; ind=ind+1){ vec[ind] = ind; } }
A Slight Variation {n:nat} unit init (int vec[n]) { var nat ind, size;; size = arraysize(vec); for (ind=0; ind<size; ind=ind+1){ vec[ind] = ind; } }
Dependent Record Types • A polymorphic type for arrays{n:nat} <‘a> array(n) { size: int(n); data[n]: ‘a}
Binary Search in Xanadu {n:nat} int bs(key: int, vec: <int> array(n)) { var: l: int [0, n], h: int [-1, n); m: int; x: float;; l = 0; h = vec.size - 1; while (l <= h) { m = (l + h) / 2; x = vec.data[m]; if (x < key) { l = m - 1; } else if (x > key) { h = m + 1; } else { return m; } } return –1; }
Dependent Record Types • A polymorphic type for 2-dimensional arrays:{n:nat} <‘a> array2(m,n) { row: int(m); col: int(n); data[m][n]: ‘a}
Dependent Record Types • A polymorphic type for sparse arrays:<‘a>sparseArray(m,n) { row: int(m); col: int(n); data[m]: <int[0,n) * ‘a> list}
Dependent Union Types • A polymorphic type for lists:union <‘a> list with nat = { Nil(0); {n:nat} Cons(n+1) of ‘a * <‘a> list(n) } • Nil: <‘a> list(0) • Cons: {n:nat} ‘a * <‘a> list(n) -> ‘a list(n+1)
Dependent Union Types • A polymorphic type for binary trees:union <‘a> tree with (nat,nat) = { E(0,0); {sl:nat,sr:nat,hl:nat,hr:nat} B(sl+sr+1,1+max(hl,hr)) of <‘a> tree(sl,hl) * ‘a * <‘a> tree(sr,hr) }
Typing Judgment in Xanadu f1;D;G |- e: (f2;D;t)
Typing Assignment • f1;D;G |- e: (f2;D;t)--------------------f1;D;G |- x = e: (f2;D[x->t];unit)
Typing Loop f1;D1 |- $f.D f1,f;D;G|- e:(f2;D2;bool(i)) f2,i=1;D2;G |- e2:(f3;D3;unit) f3;D3 |- $f.D----------------------------f1;D1;G |-while(e1,e2):(f2,i=0;D2;unit)
Reverse Append in Xanadu (‘a) {m:nat,n:nat} <‘a> list(m+n) revApp (xs:<‘a> list(m),ys:<‘a> list(n)) {var: ‘a x;;invariant: [m1:nat,n1:nat | m1+n1=m+n] (xs:<‘a> list(m1), ys:<‘a> list(n1))while (true) { switch (xs) { case Nil: return ys; case Cons (x, xs): ys = Cons(x, ys); } } exit; /* can never be reached */ }
Constraint Generation in Type-checking The following integer constraint is generated when the revApp example is type-checked: m:nat,n:nat, m1:nat,n1:nat, m1+n1=m+n, a:nat, m1=a+1 |= a+(n1+1)=m+n
Conclusion • It is still largely an elusive goal in practice to verify the correctness of a program • It is therefore important to identify those program properties that can be effectively verified for realistic programs
Conclusion • We have designed a type-theoretic approach to capturing simple arithmetic reasoning • The preliminary studies indicate that this approach allows the programmer to capture many more properties in realistic programs
Future Work • Adding more program features into Xanadu • Constructing a compiler for Xanadu that can compile dependent types from source level into bytecode level • Incorporating dependent types into Java and …