julien cretin inria pedro magalhaes utrecht
play

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


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

  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] Increasingly precise specification The spectrum of confidence Increasing confidence that the program does what you want

  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)

  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 Increasingly precise specification Coq Types The spectrum of confidence Increasing Hammer Tactical nuclear weapon (cheap, easy confidence that the (expensive, needs a trained to use, program does what user, but very effective limited you want indeed) effectivenes)

  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

  6. 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  ‘a’ stands for a type  ‘f’ stands for a type constructor

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

  8. a :: * f :: * -> * Tree :: (*->*) -> * -> *  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)

  9. 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)  Being able to abstract over a higher-kinded ‘m’ is utterly crucial  We can give a kind to Monad: Monad :: (*->*) -> Constraint

  10. data T f a = MkT (f a) type T1 = T Maybe Int Maybe :: * -> *  But is this ok too? F :: (*->*) -> * data F f = MkF (f Int) type T2 = T F Maybe  What kind does T have?  T :: (* -> *) -> * -> *?  T :: ((* -> *) -> *) -> (* -> *) -> *?  Haskell 98 “defaults” to the first

  11. data T f a = MkT (f a)  What kind does T have?  T :: (* -> *) -> * -> *?  T :: ((* -> *) -> *) -> (* -> *) -> *?  Haskell 98 “defaults” to the first  This is Obviously Wrong! We want...

  12. data T f a = MkT (f a)  What kind does T have?  T :: (* -> *) -> * -> *?  T :: ((* -> *) -> *) -> (* -> *) -> *?  Haskell 98 “defaults” to the first  This is obviously wrong! We want... T ::  k. (k->*) -> k -> * Kind polymorphism

  13. data T f a = MkT (f a) T ::  k. (k->*) -> k -> * Syntax of kinds  ::= * |  ->  |  k.  | k

  14. data T f a = MkT (f a) A kind T ::  k. (k->*) -> k -> * A type And hence: MkT ::  k.  (f:k->*) (a:k). f a -> T f a So poly-kinded type constructors mean that terms too must be poly-kinded.

  15.  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. data T f a = MkT (f a) | T2 (T Maybe Int) T2 forces T’s kind to be (* ->*) -> *

  16.  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))

  17. No! instance Typeable a => Typeable (Maybe a) where typeOf _ = TyApp (TyCon “Maybe”) (typeOf (undefined :: a)) Yes! instance (Typeable f, Typeable a) => Typeable (f a) where typeOf _ = TyApp (typeOf (undefined :: f)) (typeOf (undefined :: a)) But:  Typeable :: * -> Constraint, but f :: *->*  (undefined :: f) makes no sense, since f :: *->*

  18. class Typeable a where typeOf :: Proxy a -> TypeRep data Proxy a  Typeable ::  k. k -> Constraint Proxy ::  k. k -> *  Now everything is cool: instance (Typeable f, Typeable a) => Typeable (f a) where typeOf _ = TyApp (typeOf (undefined :: Proxy f)) (typeOf (undefined :: Proxy a))

  19.  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

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

  21. class Collection c where insert :: Eq a => a -> c a -> c a This instance Collection [] where works insert x [] = [x] insert x (y:ys) | x==y = y : ys | otherwise = y : insert x ys instance Collection BalancedTree where insert = …needs (>)… BUT THIS DOESN’T

  22.  We want the constraint to vary with the collection c! An associated type of the class 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 For lists, use Eq insert x [] = [x] insert x (y:ys) | x==y = y : ys | otherwise = y : insert x ys

  23.  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)

  24.  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

  25.  Hurrah for GADTs data Vec n a where Vnil :: Vec Zero a Vcons :: a -> Vec n a -> Vec (Succ n) a  What is Zero, Succ? Kind of Vec? data Zero data Succ a -- Vec :: * -> * -> *  Yuk! Nothing to stop you writing stupid types: f :: Vec Int a -> Vec Bool a

  26. data Zero data Succ a -- Vec :: * -> * -> *  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?

  27. 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 -> * -> *  Now the type (Vec Int a) is ill-kinded; hurrah  Nat is a kind , here introduced by ‘ datakind ’

  28. 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 -> * -> *  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

  29. 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) Add :: Nat -> Nat -> Nat

  30. Type constructor Data constructor data Foo = Foo Int f :: T Foo -> Int Which? 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

  31.  Which data types are promoted? Existentials? data T where MkT :: a -> (a->Int) -> T data S where GADTs? MkS :: S Int  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)

  32. Core Giant source language Tiny intermediate language • 100+ 10 constructors, 2 types • contructors, Explicitly typed • dozens of types Optimiser preserves • types • Type inference

  33. Abstraction and application for... Terms Types Coercions Kinds

Recommend


More recommend