Julien Cretin (Inria), Pedro Magalhaes (Utrecht) October 2011 - - PowerPoint PPT Presentation

julien cretin inria pedro magalhaes utrecht
SMART_READER_LITE
LIVE PREVIEW

Julien Cretin (Inria), Pedro Magalhaes (Utrecht) October 2011 - - PowerPoint PPT Presentation

Simon Peyton Jones, Dimitrios Vytiniotis (Microsoft Research) Stephanie Weirich, Brent Yorgey (University of Pennsylvania) Julien Cretin (Inria), Pedro Magalhaes (Utrecht) October 2011 Static typing eradicates whole species of bugs The


slide-1
SLIDE 1

Simon Peyton Jones, Dimitrios Vytiniotis (Microsoft Research) Stephanie Weirich, Brent Yorgey (University of Pennsylvania) Julien Cretin (Inria), Pedro Magalhaes (Utrecht)

October 2011

slide-2
SLIDE 2

 Static typing eradicates whole species of bugs  The static type of a function is a partial specification: its says something (but not too much) about what the function does reverse :: [a] -> [a] The spectrum of confidence

Increasingly precise specification Increasing confidence that the program does what you want

slide-3
SLIDE 3

 The static type of a function is like a weak specification: its says something (but not too much) about what the function does reverse :: [a] -> [a]  Static typing is by far the most widely-used program verification technology in use today: particularly good cost/benefit ratio

 Lightweight (so programmers use them)  Machine checked (fully automated, every compilation)  Ubiquitous (so programmers can’t avoid them)

slide-4
SLIDE 4

 Static typing eradicates whole species of bugs  Static typing is by far the most widely-used program verification technology in use today: particularly good cost/benefit ratio The spectrum of confidence

Increasingly precise specification Increasing confidence that the program does what you want

Hammer (cheap, easy to use, limited effectivenes) Tactical nuclear weapon (expensive, needs a trained user, but very effective indeed)

Types Coq

slide-5
SLIDE 5

The type system designer seeks to  Retain the Joyful Properties of types  While also:

 making more good programs pass the type checker  making fewer bad programs pass the type checker

slide-6
SLIDE 6
slide-7
SLIDE 7

 ‘a’ stands for a type  ‘f’ stands for a type constructor data Tree f a = Leaf a | Node (f (Tree f a)) type BinTree a = Tree (,) a type RoseTree a = Tree [] a type AnnTree a = Tree AN a data AN a = AN String a a

slide-8
SLIDE 8

 ‘a’ stands for a type  ‘f’ stands for a type constructor  You can do this in Haskell, but not in ML, Java, .NET etc  Kinds: data Tree f a = Leaf a | Node (f (Tree f a)) a :: * f :: * -> * Tree :: (*->*) -> * -> *

* is the kind of types

slide-9
SLIDE 9

 Just as

 Types classify terms eg 3 :: Int, (\x.x+1) :: Int -> Int  Kinds classify types eg Int :: *, Maybe :: * -> *, Maybe Int :: *

 Just as

 Types stop you building nonsensical terms eg (True + 4)  Kinds stop you building nonsensical types eg (Maybe Maybe)

 ::= * |  -> 

a :: * f :: * -> * Tree :: (*->*) -> * -> *

slide-10
SLIDE 10

 Being able to abstract over a higher-kinded ‘m’ is utterly crucial  We can give a kind to Monad: Monad :: (*->*) -> Constraint

class Monad m where return :: a -> m a (>>=) :: m a -> (a -> m b) -> m b sequence :: Monad m => [m a] -> m [a] sequence [] = return [] sequence (a:as) = a >>= \x -> sequence as >>= \xs -> return (x:xs)

slide-11
SLIDE 11

 But is this ok too?  What kind does T have?

 T :: (* -> *) -> * -> *?  T :: ((* -> *) -> *) -> (* -> *) -> *?

 Haskell 98 “defaults” to the first data T f a = MkT (f a) type T1 = T Maybe Int data F f = MkF (f Int) type T2 = T F Maybe Maybe :: * -> * F :: (*->*) -> *

slide-12
SLIDE 12

 What kind does T have?

 T :: (* -> *) -> * -> *?  T :: ((* -> *) -> *) -> (* -> *) -> *?

 Haskell 98 “defaults” to the first  This is Obviously Wrong! We want... data T f a = MkT (f a)

slide-13
SLIDE 13

 What kind does T have?

 T :: (* -> *) -> * -> *?  T :: ((* -> *) -> *) -> (* -> *) -> *?

 Haskell 98 “defaults” to the first  This is obviously wrong! We want... data T f a = MkT (f a)

T :: k. (k->*) -> k -> *

Kind polymorphism

slide-14
SLIDE 14

Syntax of kinds data T f a = MkT (f a)

T :: k. (k->*) -> k -> *

 ::= * |  ->  | k.  | k

slide-15
SLIDE 15

And hence: So poly-kinded type constructors mean that terms too must be poly-kinded. data T f a = MkT (f a)

T :: k. (k->*) -> k -> * MkT :: k. (f:k->*) (a:k). f a -> T f a

A kind A type

slide-16
SLIDE 16

 Just as we infer the most general type of a function definition, so we should infer the most general kind of a type definition  Just like for functions, the type constructor can be used only monomorphically its own RHS. T2 forces T’s kind to be (*->*) -> * data T f a = MkT (f a) | T2 (T Maybe Int)

slide-17
SLIDE 17

 Haskell today:

class Typeable a where typeOf :: a -> TypeRep instance Typeable Int where typeOf _ = TyCon “Int” instance Typeable a => Typeable (Maybe a) where typeOf _ = TyApp (TyCon “Maybe”) (typeOf (undefined :: a))

slide-18
SLIDE 18

instance Typeable a => Typeable (Maybe a) where typeOf _ = TyApp (TyCon “Maybe”) (typeOf (undefined :: a)) instance (Typeable f, Typeable a) => Typeable (f a) where typeOf _ = TyApp (typeOf (undefined :: f)) (typeOf (undefined :: a))

No! Yes!

But:  Typeable :: * -> Constraint, but f :: *->*  (undefined :: f) makes no sense, since f :: *->*

slide-19
SLIDE 19

 Typeable :: k. k -> Constraint Proxy :: k. k -> *  Now everything is cool:

class Typeable a where typeOf :: Proxy a -> TypeRep data Proxy a instance (Typeable f, Typeable a) => Typeable (f a) where typeOf _ = TyApp (typeOf (undefined :: Proxy f)) (typeOf (undefined :: Proxy a))

slide-20
SLIDE 20

 Type inference becomes a bit more tricky – but not much.

 Instantiate f :: forall k. forall (a:k). tau with a fresh kind unification variable for k, and a fresh type unification variable for a  When unifying (a ~ some-type), unify a’s kind with some-type’s kind.

 Intermediate language (System F)

 Already has type abstraction and application  Add kind abstraction and application

slide-21
SLIDE 21
slide-22
SLIDE 22

class Collection c where insert :: a -> c a -> c a instance Collection [] where insert x [] = [x] insert x (y:ys) | x==y = y : ys | otherwise = y : insert x ys Does not work! We need Eq!

slide-23
SLIDE 23

class Collection c where insert :: Eq a => a -> c a -> c a instance Collection [] where insert x [] = [x] insert x (y:ys) | x==y = y : ys | otherwise = y : insert x ys instance Collection BalancedTree where insert = …needs (>)…

This works

BUT THIS DOESN’T

slide-24
SLIDE 24

 We want the constraint to vary with the collection c!

class Collection c where type X c a :: Constraint insert :: X c a => a -> c a -> c a instance Collection [] where type X [] a = Eq a insert x [] = [x] insert x (y:ys) | x==y = y : ys | otherwise = y : insert x ys

An associated type of the class For lists, use Eq

slide-25
SLIDE 25

 We want the constraint to vary with the collection c!

class Collection c where type X c a :: Constraint insert :: X c a => a -> c a -> c a instance Collection BalancedTree where type X BalancedTree a = (Ord a, Hashable a) insert = …(>)…hash…

For balanced trees use (Ord,Hash)

slide-26
SLIDE 26

 Lovely because, it is simply a combination of

 Associated types (existing feature)  Having Constraint as a kind

 No changes at all to the intermediate language!

 ::= * |  ->  | k.  | k | Constraint

slide-27
SLIDE 27
slide-28
SLIDE 28

 Hurrah for GADTs  What is Zero, Succ? Kind of Vec?  Yuk! Nothing to stop you writing stupid types: f :: Vec Int a -> Vec Bool a

data Vec n a where Vnil :: Vec Zero a Vcons :: a -> Vec n a -> Vec (Succ n) a data Zero data Succ a

  • - Vec :: * -> * -> *
slide-29
SLIDE 29

 Haskell is a strongly typed language  But programming at the type level is entirely un-typed – or rather uni-typed, with one type, *.  How embarrassing is that?

data Zero data Succ a

  • - Vec :: * -> * -> *
slide-30
SLIDE 30

 Now the type (Vec Int a) is ill-kinded; hurrah  Nat is a kind, here introduced by ‘datakind’

datakind Nat = Zero | Succ Nat data Vec n a where Vnil :: Vec Zero a Vcons :: a -> Vec n a -> Vec (Succ n) a

 Vec :: Nat -> * -> *

slide-31
SLIDE 31

 Nat is an ordinary type, but it is automatically promoted to be a kind as well  Its constuctors are promotd to be (uninhabited) types  Mostly: simple, easy data Nat = Zero | Succ Nat data Vec n a where Vnil :: Vec Zero a Vcons :: a -> Vec n a -> Vec (Succ n) a

 Vec :: Nat -> * -> *

slide-32
SLIDE 32

Add :: Nat -> Nat -> Nat

data Nat = Zero | Succ Nat type family Add (a::Nat) (b::Nat) :: Nat type instance Add Z n = n type instance Add (Succ n) m = Succ (Add n m)

slide-33
SLIDE 33

 Where there is only one Foo (type or data constructor) use that  If both Foo’s are in scope, “Foo” in a type means the type constructor (backward compat)  If both Foo’s are in scope, ‘Foo means the data constructor

data Foo = Foo Int f :: T Foo -> Int

Type constructor Data constructor Which?

slide-34
SLIDE 34

 Which data types are promoted?  Keep it simple: only simple, vanilla, types with kinds of form T :: * -> * -> … -> *  Avoids the need for

 A sort system (to classify kinds!)  Kind equalities (for GADTs)

data T where MkT :: a -> (a->Int) -> T data S where MkS :: S Int

Existentials? GADTs?

slide-35
SLIDE 35
slide-36
SLIDE 36

Giant source language

  • 100+

contructors, dozens of types

  • Type inference

Tiny intermediate language

  • 10 constructors, 2 types
  • Explicitly typed
  • Optimiser preserves

types Core

slide-37
SLIDE 37

Types Kinds Abstraction and application for... Terms Coercions

slide-38
SLIDE 38

 Take lessons from term :: type and apply them to type :: kind

 Polymorphism  Constraint kind  Data types

 Hopefully: no new concepts. Re-use programmers intuitions abou how typing works, one level up.  Fits smoothly into the IL  Result: world peace