Advanced Features of Type Systems - Concepts of ... · Limitations of Dependent Types in Idris...

Post on 27-Jul-2020

4 views 0 download

transcript

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