Advanced Features of Type Systems Concepts of Programming - - PowerPoint PPT Presentation

advanced features of type systems
SMART_READER_LITE
LIVE PREVIEW

Advanced Features of Type Systems Concepts of Programming - - PowerPoint PPT Presentation

Advanced Features of Type Systems Concepts of Programming LanguagesCoPL 15 Sebastian Hungerecker Institute for Software Engineering and Programming Languages February 8, 2016 Sebastian Hungerecker February 8, 2016 1 Introduction


slide-1
SLIDE 1

Advanced Features of Type Systems

Concepts of Programming Languages—CoPL ’15 Sebastian Hungerecker

Institute for Software Engineering and Programming Languages

February 8, 2016

Sebastian Hungerecker February 8, 2016 1

slide-2
SLIDE 2

Introduction

◮ Type systems turn wrong behavior into errors ◮ Static type systems turn run-time into compile-time errors ◮ Advanced features catch even more errors at compile time

Sebastian Hungerecker February 8, 2016 2

slide-3
SLIDE 3

Topics Dependent Types Refinement Types Uniqueness Types

Sebastian Hungerecker February 8, 2016 3

slide-4
SLIDE 4

Dependent Types Types depend on values.

data Foo: Int -> Type where ... baz: (bar: Int) -> Foo bar ⇒ More information about types ⇒ More properties can be expressed

For example: Index out of bounds

Sebastian Hungerecker February 8, 2016 4

slide-5
SLIDE 5

ADT in Idris

data Nat : Type where Z : Nat S : Nat -> Nat

Usage

i: Nat = S (S (S Z))

  • - with more sugar:

i: Nat = 3 Z = 0 S Z = 1 S (S Z) = 2 ...

Sebastian Hungerecker February 8, 2016 5

slide-6
SLIDE 6

Dependent Types in Idris

data Vect : Nat -> Type -> Type where Nil : 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

slide-7
SLIDE 7

Example: Sequential Vector (ι Function)

iotaHelper : (n: Nat) -> Vect n Nat iotaHelper Z = Nil iotaHelper (S m) = (S m) :: iotaHelper m iota : (n: Nat) -> Vect n Nat iota n = reverse (iotaHelper n)

Usage

iota 5

  • -> (1 :: 2 :: 3 :: 4 :: 5 :: Nil): Vect 5 Nat

Sebastian Hungerecker February 8, 2016 7

slide-8
SLIDE 8

Static Range Checking of Indices

data Fin : Nat -> Type where FZ : {n: Nat} -> Fin (S n) FS : {n: Nat} -> Fin n -> Fin (S n)

Usage

i: Fin 2 = 0 i: Fin 2 = 1

  • -> compile fine

i: Fin 2 = 2

  • -> compile error

FZ = 0 FS FZ = 1 FS (FS FZ) = 2 ...

Sebastian Hungerecker February 8, 2016 8

slide-9
SLIDE 9

Safe Vector Access

index : Fin n -> Vect n a -> a index FZ (x :: xs) = x index (FS k) (x :: xs) = index k xs

Usage

myVect: Vect 2 Nat = 1 :: 2 :: Nil index 1 myVect

  • -> 2

index 2 myVect

  • -> compile error

Sebastian Hungerecker February 8, 2016 9

slide-10
SLIDE 10

Safe Vector Access

index : Fin n -> Vect n a -> a index FZ (x :: xs) = x index (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

slide-11
SLIDE 11

Converting Numbers to Indices

natToFin : (x: Nat) -> (n: Nat) -> Maybe (Fin n) natToFin Z (S j) = Just FZ natToFin (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

slide-12
SLIDE 12

Example Continuation: A “Real” Application

main : IO () main = do { input <- getLine n: Nat = cast input squares = map (\x => x*x) (iota n) print squares input2 <- getLine i: Nat = cast input2 case natToFin i n of Just idx => print (index idx squares) Nothing => putStrLn "Number too large" }

Sebastian Hungerecker February 8, 2016 11

slide-13
SLIDE 13

Cat

Sebastian Hungerecker February 8, 2016 12

slide-14
SLIDE 14

Limitations of Dependent Types in Idris

iotaTR : (n: Nat) -> Vect m Nat -> Vect (m+n) Nat iotaTR Z acc = acc iotaTR (S n) acc = iotaTR n (S n :: acc) iota : (n: Nat) -> Vect n Nat iota n = iotaTR n Nil

Sebastian Hungerecker February 8, 2016 13

slide-15
SLIDE 15

Limitations of Dependent Types in Idris

iotaTR : (n: Nat) -> Vect m Nat -> Vect (m+n) Nat iotaTR Z acc = acc iotaTR (S n) acc = iotaTR n (S n :: acc) iota : (n: Nat) -> Vect n Nat iota n = iotaTR n Nil Type mismatch between Vect m Nat (Type of acc) and Vect (m + 0) Nat (Expected type) Specifically: Type mismatch between m and m + 0

Sebastian Hungerecker February 8, 2016 13

slide-16
SLIDE 16

Why? Huh?

m = m+0?

Definition of +

Z + r = r (S l) + r = S (l + r)

Thus

◮ 0+x = x is trivial ◮ x+0 = x needs to be proven

Sebastian Hungerecker February 8, 2016 14

slide-17
SLIDE 17

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 of Z => rewrite plusZeroRightNeutral m in acc (S n') => rewrite sym (plusSuccRightSucc m n') in iotaTR n' (n :: acc) iota : (n: Nat) -> Vect n Nat iota n = iotaTR n []

Sebastian Hungerecker February 8, 2016 15

slide-18
SLIDE 18

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 Step plusSuccRightSucc (S l) r = S S(ℓ)+r = let inductiveHypot = Inductive Hypothesis plusSuccRightSucc l r S(ℓ+r) = ℓ+S(r) in proof { intros;

  • Def

= S S(ℓ+r) rewrite inductiveHypot;

IH

= S ℓ+S(r) trivial;

Def

= S(ℓ)+S(r) }

Sebastian Hungerecker February 8, 2016 16

slide-19
SLIDE 19

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 Step plusSuccRightSucc (S l) r = S S(ℓ)+r = let inductiveHypot = Inductive Hypothesis plusSuccRightSucc l r S(ℓ+r) = ℓ+S(r) in proof { intros;

  • Def

= 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

slide-20
SLIDE 20

Refinement Types

◮ Dependent ADTs cool, but cumbersome ◮ Combine types with predicates

type t2 = {x:t | p(x)}

◮ Automated SMT solver instead of manual theorem proving

Sebastian Hungerecker February 8, 2016 17

slide-21
SLIDE 21

Qube Types Built-In Types

◮ Integers: int ◮ Integer vectors: intvec n ◮ Arrays: [elementType | shapeVector]

Usage

let i: int = 42 let 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

slide-22
SLIDE 22

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

slide-23
SLIDE 23

Qube Types Usage

let n: nat = 42

  • - Works

let n2: nat = -5

  • - Error !(-5 >= 0)

let idx: index n = 41

  • - Works

let idx2: index n = 43

  • - Error !(43 < 42)

let shape: natvec 3 = [2,2,3] -- Works let 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

slide-24
SLIDE 24

Safe Array Access

◮ Array access: array.[ iv ] ◮ array: [ T | shape ] ◮ iv: indexvec r shape where r is the length of shape

Usage

tensor.[ iv ]

  • - Works

tensor.[ iv3 ]

  • - Error

Sebastian Hungerecker February 8, 2016 21

slide-25
SLIDE 25

Uniqueness Types

And now for something completely

  • different. . .

Sebastian Hungerecker February 8, 2016 22

slide-26
SLIDE 26

Uniqueness Types

◮ Value can’t be used more than once ◮ Operations need to produce new value

Sebastian Hungerecker February 8, 2016 23

slide-27
SLIDE 27

Example: File Handling

type file fopen(name: string): unique file fwrite(text:string, f: unique file): unique file fclose(f: unique file): void

Usage

let f = fopen("foo.txt") let f = fwrite(f, "bar") fclose(f)

Sebastian Hungerecker February 8, 2016 24

slide-28
SLIDE 28

Example: File Handling

type file fopen(name: string): unique file fwrite(text:string, f: unique file): unique file fclose(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

slide-29
SLIDE 29

Conclusion

◮ Type systems turn wrong behavior into errors ◮ Static type systems turn run-time into compile-time errors

⇒ Cost: (sometimes) have to write down type information

◮ Advanced features catch even more errors at compile time

⇒ Cost: even more type information required

Sebastian Hungerecker February 8, 2016 25

slide-30
SLIDE 30

Outlook Express What else can be guarenteed through types?

◮ NullPointerExceptions through option types ◮ Validity of generated XML by translating XML schemas to type

hierachies

◮ SQL queries through row types ◮ Transactionality through monads ◮ Termination through dependent types & theorem proving

Sebastian Hungerecker February 8, 2016 26