240 likes | 364 Views
Introduction to Sized Type Inference. “Calculating Sized Types” by Wei-Ngan Chin and Siau-Cheng Khoo published in PEPM00 and HOSC01 Presented by Xu Na. Meaning of Size. Int m – size of an integer is the integer itself
E N D
Introduction to Sized Type Inference “Calculating Sized Types” by Wei-Ngan Chin and Siau-Cheng Khoo published in PEPM00 and HOSC01 Presented by Xu Na Sized Types Inference
Meaning of Size Intm – size of an integer is the integer itself []m– size of a recursive data consists of its maximum depth. Boolm– m=0 for False and m=1 for True append:: []m! []n! []p s.t. m¸0 Æ n¸0 Æ p=m+n – size of a function is a relation between its input and output sizes. Sized Types Inference
annotated type size constraint Syntax of Sized Type e :: (,) Examples: 3 :: (Inti, (i = 3) ) [3] :: ([Inti]j, (i = 3) (j = 1)) [3,4] :: ([Inti]j, ((i = 3) (i = 4)) (j = 2) ) :: ([Int]j, (j = 2) ) True :: (Boolb, (b = 1) ) False :: (Boolb, (b = 0) ) append :: ([]m[]n []p,(m0) (n0) (p=m+n) ) Sized Types Inference
What is Sized Type? • An advanced type system to capture size relation of: • output in terms of inputs • pre-conditions on inputs • input invariant across recursion Sized Types Inference
size variables of integer types linear arithmetic constraints on size variables Example: tail (x:xs) = xs polymorphic type: tail :: [] [] sized type: tail :: []m []p size (m>0) // pre-condition (p+1=m) // output relation Sized Types Inference
zip :: [] [] [(,)] zip [] [] = [] zip (x:xs) (y:ys) = (x,y):(zip xs ys) Example: Sized type: zip :: []m []n [(,)]p size (m0) (n0) (n=m) // pre-condition (p=m) // output relation inv (0m+<m) (0n+<n) (m– m+= n – n+) // invariant (zip xsm ysn) …(zip xs1m1 ys1n1)… …(zip xs2m2 ys2n2)… … (m+,n+){(m1,n1),(m2,n2),…,…} Sized Types Inference
Syntax of Constraints Sized Types Inference
Sized Type Inference 1. Extension of Polymorphic Type Rules.2. Requires linear arithmetic constraint solver.3. Recursive letrec requires new fixed point computation. Sized Types Inference
Example f b xs = case b of False -> xs True -> append xs xs Assume: append :: []m []n []p st (m0) (n0) (p=m+n) f :: Booli []j []k What is the sized type for f? infer : ((i = 0) (k = j)) ((i = 1) (k = j+j)) Sized Types Inference
variable-rule application-rule Example (non-recursive) f b xs = case b of False -> xs True -> append xs xs f :: Booli []j []k append :: []m []n []p st (m0) (n0) (p=m+n) xs :: []kst (k = j) (append xs xs) :: []kst (k = j+j) Sized Types Inference
case-rule (case b ...) :: []kst ((i = 0) (k = j)) ((i = 1) (k = j+j)) Example (non-recursive) f :: Booli []j []k f b xs = case b of False -> xs True -> append xs xs :: []kst (k = j) :: []kst (k = j+j) Sized Types Inference
Sized Inference : Recursive Function Steps:1. Infer recursive call constraint & terminating constraint.2. Calculate a generalised transitive constraint.3. Incorporate terminating constraint. Sized Types Inference
[]i []j[]k []m []n[]p Example (recursive) append xs ys = case xs of [] -> ys (x:xs’) -> x:(append xs’ ys) Terminating Constraint: B :: [m,n,p] = (m = 0) (n 0) (p=n) Recursive Call Constraint: U :: [m,n,p] [i,j,k] = (i+1 = m) (j = n) (p=k+1) Sized Types Inference
Fixed Point via Omega Calculator Theoretic Closure (Least fixed point) U+ = k=1Uk Practical Fixed Point (via Omega Calculator ) R. P=closure(R) R P R+ Fixed-Point Check: (P=R+) (P o R P) U :: [m,n,p][i,j,k] = (i+1=m) (j = n) (p=k+1) closure(U) ::[m,n,p][m+,n+ ,p+] =(0 m+ <m) (n 0) (n+ = n) (m - m+ = p - p+ ) Sized Types Inference
Terminating Constraint: B :: [m,n,p] = (m = 0) (n 0) (p=n) Recursive Call Constraint: U :: [m,n,p] [i,j,k] = (i+1 = m) (j = n) (p=k+1) U+ ::[m,n,p][m+,n+ ,p+] =(0 m+ <m) (n 0) (n+ = n) (m - m+ = p - p+ ) Append :: [m,n,p] = B[m,n,p] ( m+,n+,p+ : U+ (m, n, p, m+,n+,p+) B[m+,n+,p+] ) = ((m=0)(n0)(p=n)) ((m1)(n0)(p=m+n)) = (m0)(n0)(p=m+n) Sized Types Inference
Prototype System Fun f x y = x + y {[s4,s5] -> [w3] :w3 = s4+s5 } Fun f1 x = f 0 x {[s14] -> [w3] :s14 = w3 } Fun append xs ys = case xs of { [] -> ys ; (x:xs') -> x : append xs' ys } {[s26,s27] -> [s28] :s28 = s27+s26 && 0 <= s27 && 0 <= s26 } Fun f4 xs = append xs xs {[s74] -> [w3] :w3 = 2s74 && 0 <= s74 } Fun filter p s = case s of { [] -> [] ; (x:xs) -> case p s of { True -> x : filter p xs ; False -> filter p xs } } {[s120,s121,s122] -> [s123] :0 <= s121 <= 1 && 0 <= s123 <= s122 && 0 <= s120 } Sized Types Inference
Prototype System Fun zipB xs ys = case xs of { [] -> ys ; (x:xs') -> case ys of { [] -> [] ; (y:ys') -> x : zipB xs' ys' } } {[s201,s202] -> [s203] :s203 = s202 && 0 <= s202 && 0 <= s201 } Fun zipA xs ys = case xs of { [] -> [] ; (x:xs') -> case ys of { [] -> [] ; (y:ys') -> x : zipA xs' ys' } } {[s235,s236] -> [s237] :0 <= s237 <= s235, s236 } Fun zip xs ys = case xs of { [] -> ys ; (x:xs') -> case ys of { [] -> xs ; (y:ys') -> x : zip xs' ys' } } {[s167,s168] -> [s169] :(s167<=s168 && s168 = s169) OR :(s168<s167 && s167 = s169) } Sized Types Inference
Why Sized Type is Useful? • Safety Analysis: termination, bounded space. • Vector-Based Memoisation. • Array Bounds Check Elimination. • Context-based Specialisation. Sized Types Inference
Termination Analysis Previous work based on abstract interpretation. e.g. Ullman, Jones, Plumer etc.KEY : Does a given recursion terminate? ack 0 m = m+1 ack (n+1) 0 = ack n 1 ack (n+1) (m+1) = ack n (ack (n+1) m) Sized type: ack :: Inti Intj Intk size (0 i) (0 j) // pre-condition inv (0 i+<i) ((i+ = i) (1i+) (0j+ <j)) // rec. invariant Sized Types Inference
max(0,n++k-n) k+ min(n+,k) Vector-Based Memoisation Eliminate redundant calls [Chin & Hagiya ICFP97] via vectorisation. bin(n,k) = case n of 0 -> 1 m+1 -> if (k <= 0 || k >= n) then 1 else bin(m-1,k-1) + bin(m,k) Sized type bin :: (Intn,Intk) -> Intp inv.(k+,1 k < n) (k+,1 n+ < n) (k+n+ n+k+) 0 k+ Problem - Bounds Analysis Sized Types Inference
bin(n,k) = let bin’(n+) = case n+ of 0 -> \ k+ -> 1 m+1 -> let z = bin’(m) bn k+ = if (k+ <= 0 || k+ >= n) then 1 else z(k+-1) + z(k+) l = max(0,n++k-n) u = min(n+,k) vec = array(l,u)[a:=bn(a)| a<-[l..u]] in (!)vec in if (0<=k && max(1,k)<=n) then bin’(n)(k) else 1 Vector-Based Memoisation bin(n,k) = case n of 0 -> 1 m+1 -> if (k <= 0 || k >= n) then 1 else bin(m-1,k-1) + bin(m,k) max(0,n++k-n) k+ min(n+,k) Sized Types Inference
0 lo m hi < length(arr) Bound Checks Elimination Bounds check can be eliminated by invariants over indexes. bsearch cmp key arr = let look:: (Intlo,Inthi) Intk INV (lo lo+) (hi+ hi) look(lo,hi) = if (hi>=lo) then let m=lo+(hi-lo)/2; x=arr!m in case cmp(key,x) of LESS -> look(lo,m-1) EQUAL -> m MORE -> look(m+1,hi) else -1 in look(0,(length arr)-1) arr ! m = if (0m <length(arr)) then sub(arr,m) else Sized Types Inference
zip1 xs ys = zip xs ys st(xs::[]m) (ys::[]n) (m n) Context Specialisation Specialisation can eliminate redundant tests. zip :: []m []n [(,)]p size((0 m n) (p=m)) ((0 n m) (p=n)) zip xs ys = case xs of [] -> [] (x:xs’) -> case ys of [] -> [] (y:ys’) -> (x,y):(zip xs’ ys’) zip1 :: []m []n [(,)]p size (0 m n) (p=m) zip1 xs ys = case xs of [] -> [] (x:xs’) -> (x,head ys):(zip1 xs’ (tail ys)) Sized Types Inference
zip2 xs ys = zip xs ys st(xs::[]m) (ys::[]n) (n m) Context Specialisation Specialisation can eliminate redundant tests. zip :: []m []n [(,)]p size((0 n m) (p=n)) ((0 m n) (p=m)) zip xs ys = case xs of [] -> [] (x:xs’) -> case ys of [] -> [] (y:ys) -> (x,y):(zip xs’ ys’) zip2 :: []m []n [(,)]p size (0 n m) (p=n) zip2 xs ys = case ys of [] -> [] (y:ys’) -> (head xs,y):(zip2 (tail xs) ys’) Sized Types Inference