Upload
others
View
4
Download
0
Embed Size (px)
Citation preview
Advanced Features of Type SystemsConcepts of Programming Languages—CoPL’15
Sebastian Hungerecker
Institute for Software Engineering and Programming Languages
February 8, 2016
Sebastian Hungerecker February 8, 2016 1
Introduction
I Type systems turn wrong behavior into errorsI Static type systems turn run-time into compile-time errorsI Advanced features catch even more errors at compile time
Sebastian Hungerecker February 8, 2016 2
Topics
Dependent Types
Refinement Types
Uniqueness Types
Sebastian Hungerecker February 8, 2016 3
Dependent Types
Types depend on values.
data Foo: Int -> Type where ...baz: (bar: Int) -> Foo bar
⇒ More information about types
⇒ More properties can be expressedFor example: Index out of bounds
Sebastian Hungerecker February 8, 2016 4
ADT in Idris
data Nat : Type whereZ : NatS : Nat -> Nat
Usage
i: Nat = S (S (S Z))
-- with more sugar:i: Nat = 3
Z = 0S Z = 1
S (S Z) = 2. . .
Sebastian Hungerecker February 8, 2016 5
Dependent Types in Idris
data Vect : Nat -> Type -> Type whereNil : Vect Z a(::) : a -> Vect n a -> Vect (S n) a
Usage
myVect: Vect 3 Int = 1 :: 2 :: 3 :: Nil--> compiles fine
myVect: Vect 2 Int = 1 :: 2 :: 3 :: Nil--> compile error
Sebastian Hungerecker February 8, 2016 6
Example: Sequential Vector (ι Function)
iotaHelper : (n: Nat) -> Vect n NatiotaHelper Z = NiliotaHelper (S m) = (S m) :: iotaHelper m
iota : (n: Nat) -> Vect n Natiota n = reverse (iotaHelper n)
Usage
iota 5--> (1 :: 2 :: 3 :: 4 :: 5 :: Nil): Vect 5 Nat
Sebastian Hungerecker February 8, 2016 7
Static Range Checking of Indices
data Fin : Nat -> Type whereFZ : {n: Nat} -> Fin (S n)FS : {n: Nat} -> Fin n -> Fin (S n)
Usage
i: Fin 2 = 0i: Fin 2 = 1--> compile fine
i: Fin 2 = 2--> compile error
FZ = 0FS FZ = 1
FS (FS FZ) = 2. . .
Sebastian Hungerecker February 8, 2016 8
Safe Vector Access
index : Fin n -> Vect n a -> aindex FZ (x :: xs) = xindex (FS k) (x :: xs) = index k xs
Usage
myVect: Vect 2 Nat = 1 :: 2 :: Nil
index 1 myVect--> 2
index 2 myVect--> compile error
∀n > 1. Fin n
∀n > 2. Fin n
Sebastian Hungerecker February 8, 2016 9
Safe Vector Access
index : Fin n -> Vect n a -> aindex FZ (x :: xs) = xindex (FS k) (x :: xs) = index k xs
Usage
myVect: Vect 2 Nat = 1 :: 2 :: Nil
index 1 myVect--> 2
index 2 myVect--> compile error
∀n > 1. Fin n
∀n > 2. Fin n
Sebastian Hungerecker February 8, 2016 9
Converting Numbers to Indices
natToFin : (x: Nat) -> (n: Nat) -> Maybe (Fin n)natToFin Z (S j) = Just FZnatToFin (S k) (S j) with (natToFin k j)
| Just k' = Just (FS k')| Nothing = Nothing
natToFin _ Z = Nothing
Usage
natToFin 2 3--> Just 2: Maybe (Fin 3)
natToFin 3 3--> Nothing
Sebastian Hungerecker February 8, 2016 10
Example Continuation: A “Real” Application
main : IO ()main = do {input <- getLinen: Nat = cast inputsquares = map (\x => x*x) (iota n)print squaresinput2 <- getLinei: Nat = cast input2case natToFin i n of
Just idx => print (index idx squares)Nothing => putStrLn "Number too large"
}
Sebastian Hungerecker February 8, 2016 11
Cat
Sebastian Hungerecker February 8, 2016 12
Limitations of Dependent Types in Idris
iotaTR : (n: Nat) -> Vect m Nat ->Vect (m+n) Nat
iotaTR Z acc = acciotaTR (S n) acc = iotaTR n (S n :: acc)
iota : (n: Nat) -> Vect n Natiota n = iotaTR n Nil
Type mismatch betweenVect m Nat (Type of acc)
and Vect (m + 0) Nat (Expected type)
Specifically: Type mismatch betweenm
and m + 0
Sebastian Hungerecker February 8, 2016 13
Limitations of Dependent Types in Idris
iotaTR : (n: Nat) -> Vect m Nat ->Vect (m+n) Nat
iotaTR Z acc = acciotaTR (S n) acc = iotaTR n (S n :: acc)
iota : (n: Nat) -> Vect n Natiota n = iotaTR n Nil
Type mismatch betweenVect m Nat (Type of acc)
and Vect (m + 0) Nat (Expected type)
Specifically: Type mismatch betweenm
and m + 0
Sebastian Hungerecker February 8, 2016 13
Why?
Huh?m 6=m+0?
Definition of +
Z + r = r(S l) + r = S (l + r)
ThusI 0+x= x is trivialI x+0 = x needs to be proven
Sebastian Hungerecker February 8, 2016 14
Overcoming Limitations of Dependent Types in Idris
iotaTR : {m: Nat} -> (n: Nat) ->Vect m Nat -> Vect (m+n) Nat
iotaTR {m} n acc =case n ofZ =>
rewrite plusZeroRightNeutral min acc
(S n') =>rewrite sym (plusSuccRightSucc m n')in iotaTR n' (n :: acc)
iota : (n: Nat) -> Vect n Natiota n = iotaTR n []
Sebastian Hungerecker February 8, 2016 15
Theorem Proving
plusSuccRightSucc : Claim(l : Nat) -> (r : Nat) -> ∀` ∈ N.∀r ∈ N.
S (l + r) = l + (S r) S(` + r) = ` + S(r)Induction Basis
plusSuccRightSucc Z r = S(0 + r) = 0 + S(r)refl follows from definition
Inductive StepplusSuccRightSucc (S l) r = S
(S(`) + r
)=Y
let inductiveHypot = Inductive HypothesisplusSuccRightSucc l r S(` + r) = ` + S(r)
in proof {
intros; YDef= S
(S(` + r)
)rewrite inductiveHypot;
IH= S(` + S(r)
)trivial; Def= S(`) + S(r)
}
0+ r = r
S(`)+ r = S(`+ r)
Sebastian Hungerecker February 8, 2016 16
Theorem Proving
plusSuccRightSucc : Claim(l : Nat) -> (r : Nat) -> ∀` ∈ N.∀r ∈ N.
S (l + r) = l + (S r) S(` + r) = ` + S(r)Induction Basis
plusSuccRightSucc Z r = S(0 + r) = 0 + S(r)refl follows from definition
Inductive StepplusSuccRightSucc (S l) r = S
(S(`) + r
)=Y
let inductiveHypot = Inductive HypothesisplusSuccRightSucc l r S(` + r) = ` + S(r)
in proof {
intros; YDef= S
(S(` + r)
)rewrite inductiveHypot;
IH= S(` + S(r)
)trivial; Def= S(`) + S(r)
}
0+ r = r
S(`)+ r = S(`+ r)
Sebastian Hungerecker February 8, 2016 16
Refinement Types
I Dependent ADTs cool, but cumbersomeI Combine types with predicatestype t2 = {x:t | p(x)}
I Automated SMT solver instead of manual theorem proving
Sebastian Hungerecker February 8, 2016 17
Qube Types
Built-In TypesI Integers: intI Integer vectors: intvec nI Arrays: [elementType | shapeVector]
Usage
let i: int = 42let iv: intvec 3 = [13, 23, 42]let tensor: [int | [2, 2, 3] ] =
[ 1, 2, 3,4, 5, 6,
7, 8, 9,10, 11, 12
| [2, 2, 3] ]
Sebastian Hungerecker February 8, 2016 18
Qube Types
Refinement Types
type nat = { i: int | 0 <= i }type index n:nat = { i: nat | i < n }
type natvec n:nat ={ iv: intvec n | ∀ i ∈ iv. 0 <= i }
type indexvec n:nat sv:(natvec n) ={ nv: natvec n | ∀ i,s ∈ nv,sv. i < s }
Sebastian Hungerecker February 8, 2016 19
Qube Types
Usage
let n: nat = 42 -- Workslet n2: nat = -5 -- Error !(-5 >= 0)
let idx: index n = 41 -- Workslet idx2: index n = 43 -- Error !(43 < 42)
let shape: natvec 3 = [2,2,3] -- Workslet iv: indexvec 3 shape =[0, 1, 2] -- Works
let iv2: indexvec 3 shape =[2, 1, 0] -- Error !(2 < 2)
let iv3: indexvec 3 [3,2,2] =[2, 1, 0] -- Works
Sebastian Hungerecker February 8, 2016 20
Safe Array Access
I Array access: array.[ iv ]
I array: [ T | shape ]
I iv: indexvec r shape where r is the length of shape
Usage
tensor.[ iv ] -- Workstensor.[ iv3 ] -- Error
Sebastian Hungerecker February 8, 2016 21
Uniqueness Types
And now forsomethingcompletelydifferent. . .
Sebastian Hungerecker February 8, 2016 22
Uniqueness Types
I Value can’t be used more than onceI Operations need to produce new value
Sebastian Hungerecker February 8, 2016 23
Example: File Handling
type file
fopen(name: string): unique filefwrite(text:string, f: unique file): unique filefclose(f: unique file): void
Usage
let f = fopen("foo.txt")let f = fwrite(f, "bar")fclose(f)
fwrite(f, "baz")--> Error: f has already been consumed
Sebastian Hungerecker February 8, 2016 24
Example: File Handling
type file
fopen(name: string): unique filefwrite(text:string, f: unique file): unique filefclose(f: unique file): void
Usage
let f = fopen("foo.txt")let f = fwrite(f, "bar")fclose(f)fwrite(f, "baz")--> Error: f has already been consumed
Sebastian Hungerecker February 8, 2016 24
Conclusion
I Type systems turn wrong behavior into errorsI Static type systems turn run-time into compile-time errors
⇒ Cost: (sometimes) have to write down type informationI Advanced features catch even more errors at compile time
⇒ Cost: even more type information required
Sebastian Hungerecker February 8, 2016 25
Outlook Express
What else can be guarenteed through types?I NullPointerExceptions through option typesI Validity of generated XML by translating XML schemas to type
hierachiesI SQL queries through row typesI Transactionality through monadsI Termination through dependent types & theorem proving
Sebastian Hungerecker February 8, 2016 26