Imperative Programming with Dependent Types
Hongwei XiUniversity 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
e
Typing Assignment
exexunit
Typing Loop
ebooliieunitwhileeeiunit
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 …
Top Related