types, types, types

Upload
fronxwurmus 
Category
Self Improvement

view
390 
download
12
Embed Size (px)
description
Transcript of types, types, types
types, types, types
types, types, typesIn a weird parallel world where programming is based on type theory, every term has a type, if you declare it or not, every function has a type, and polymorphic functions can't know the type of their argument or see what's inside.
Even if you don't use languages from that world, they can still be an inspiration.
goals
dissatisfied
excited
common language
outlinewarmup. just ask the type inferencer
main A. type checking is lie detectionmain B. what is type theory anyway?
examples.
bonus. kinds
just ask thetype inferencer
just ask the type inferencerghci> :type 3 > 0
Hey type inferencer, I was just wondering:
4 What's the type of 3 > 0?
just ask the type inferencerghci> :type 3 > 0
3 > 0 :: Bool
The term 3 > 0 has the type Bool.
just ask the type inferencerghci> :type not
just ask the type inferencerghci> :type not
not :: Bool > Bool
"not" is a function that takes a Bool to a Bool.
just ask the type inferencerghci> let f (x, y) = Trueghci> :type f
just ask the type inferencerghci> let f (x, y) = Trueghci> :type f
f :: (t, t1) > Bool
f is a function that takes a pair ofany two types to a Bool.
someVar = f (True, "abc")  True
just ask the type inferencerghci> let f x y = x == yghci> :type f
just ask the type inferencerghci> let f x y = x == yghci> :type f
f :: Eq a => a > a > Bool
f is a function that takes two of thesame type "a" to a Bool.
The type "a" must support equality.
just ask the type inferencerghci> :info Eq
class Eq a where (==) :: a > a > Bool (/=) :: a > a > Bool
("a" is a placeholder for a concrete type here.)
just ask the type inferencerghci> let f x = x * 2ghci> :type f
just ask the type inferencerghci> let f x = x * 2ghci> :type f
f :: Num a => a > a
f is a function that takes a value of any type "a" to a value of the same type "a".
There must be an instance of Num for the type "a".
just ask the type inferencerghci> :info Num
class Num a where (+) :: a > a > a (*) :: a > a > a () :: a > a > a negate :: a > a abs :: a > a ...
just ask the type inferencerghci> let f x = x * 2ghci> f True
<interactive>:24:1: No instance for (Num Bool) arising from a use of `f' Possible fix: add an instance declaration for (Num Bool) In the expression: f True In an equation for `it': it = f True
ok
summary4 if you don't know the type, ask the type inferencer
4 functions have types
4 operations constrain types
main A
type checkingis lie detection
type checking is lie detectionintIdentity :: Int > IntintIdentity x = x
type checking is lie detectionintIdentity :: Int > IntintIdentity x = 42
But that's not an identity function! :(
how can we prevent ourselves from lying?
the function that…
type checking is lie detection intIdentity :: Int > Intidentity :: a > aidentity x = ???
type checking is lie detection intIdentity :: Int > Intidentity :: a > aidentity x = 42
type checking is lie detection intIdentity :: Int > Intidentity :: a > aidentity x = 42
That's a lie!The function must accept an argument of any type.
type checking is lie detection intIdentity :: Int > Intidentity :: a > aidentity x = 42
That's a lie!The function must accept an argument of any type.And it must return an argument of the same type.
type checking is lie detection intIdentity :: Int > Intidentity :: a > aidentity x = x
There is only one valid implementation*!
*that terminates and returns a value
parametricity
c++ templates and parametricitytemplate <typename t>t identity(t a) { return ???;}
c++ templates and parametricitytemplate <typename t>t identity(t a) { return 42;}
end of intermission
parametricityf :: [t] > [t]
What can this function not do?
parametricityf :: [t] > [t]
What can this function not do?
4 insert items
4 change values
parametricityf :: [t] > [t]
So what can it do at all?
parametricityf :: [t] > [t]
So what can it do at all?
4 rearrange list items
4 drop list items
parametricityHere is a valid implementation:
tail :: [t] > [t]tail (x:xs) = xs  nonemptytail _ = []  empty
 example usage: tail [1,2,3]  [2,3] tail "abc"  "bc" tail []  [] tail ""  ""
parametricity / lie detectionf :: [t] > t
parametricity / lie detectionhead :: [t] > thead (x:_) = x
parametricity / lie detectionhead :: [t] > thead (x:_) = x
Warning: Pattern match(es) are nonexhaustive In an equation for `head': Patterns not matched: []
parametricity / lie detectionhead :: [t] > thead (x:_) = xhead [] = ???
4 the type [t] > t is not inhabited
4 any function that claims to have that type is a lie
summary4 the less a function knows, the less it can do
4 if you can use a more abstract type, do it
4 not every type is inhabited
main B
what istype theory
anyway?
"type theory is the grand, unified theory of computation"— robert harper
type theory is a formal language that describeshow terms and typesrelate to each other
example: pairs4 how to combine two types into a pair type
4 how to construct values of that type
4 how to deconstruct pair values and types
4 how to simplify terms involving pairs
type theory: formation rulesA is a type <—— "assuming that…"B is a type——————————————— (∧F)A ∧ B is a type <—— "…this is a valid thing to write"
type theory: introduction rulesA is a typeB is a type——————————————— (∧F)A ∧ B is a type
x:A y:B——————————— (∧Introduction)(x,y) : A∧B
type theory: elimination rulesA is a typeB is a type——————————————— (∧F)A ∧ B is a type
x:A y:B z : A∧B——————————— (∧I) ——————————— (∧E1)(x,y) : A∧B first z : A
type theory: elimination rulesA is a typeB is a type——————————————— (∧F)A ∧ B is a type
x:A y:B z : A∧B z : A∧B——————————— (∧I) ——————————— (∧E1) ———————————— (∧E2)(x,y) : A∧B first z : A second z : B
type theory: computation rulesfirst(x,y) —> x
second(x,y) —> y
(The left side reduces to the right side.)
4 formation rulesspecify syntax for types
4 introduction rulesspecify syntax for types and terms
4 elimination rulesare inverses of introduction rules (sort of)
4 computation rulesdescribe how terms can be simplified by evaluating them
next example: functions
type theory: implicationpropositional logic
A => B assuming that A implies BA and assuming there is a proof of A—————— B there is a proof of B
type theory: implicationpropositional logic type theory 
A => B f : (A => B)A x : A—————— ———————————— (=> Elimination) B (f x) : B
type theory: implicationHow do we construct a function?
type theory: implicationHow do we construct a function?
x:A . . given an object of type A, . an object of type B can be deduced . ——— y:B
type theory: implicationHow do we construct a function?
[x:A] [discharged assumption] . . given an object of type A, . an object of type B can be deduced . y:B———————————————— (=> Introduction) ??? : A => B
type theory: implicationHow do we construct a function?
[x:A] [discharged assumption] . . given an object of type A, . an object of type B can be deduced . y:B———————————————— (=>I)(λx. y) : A => B any function that takes an A and returns a B is a proof of A => B
type theory: implicationintroduction: elimination:
[x:A] f: A => B x:A . ——————————————— . (f x) : B . y:B———————————————— computation:(λx. y) : A => B beta reduction
a program is welltypedif it can be derived
using the rules
types as propositions
programs as proofs
"Curry–Howard correspondence"
what does that mean for some actual programs?
programs as proofsx :: Bool
programs as proofsx :: Boolx = False
programs as proofsx :: Boolx = False
(empty) (empty)——————————— ————————————True : bool False : bool
False is exactly one of the ways of how you construct a bool.
not bad
programs as proofsdata Color = Red  Green  Blue
c :: Color
programs as proofsdata Color = Red  Green  Blue
c :: Colorc = Blue
Blue is exactly one of the ways of how you construct a Color.
programs as proofsf :: (a > b) > a > b
programs as proofsf :: (a > b) > a > bf f1 x = ???
programs as proofsf :: (a > b) > a > bf f1 x = f1 x
programs as proofsf :: (a > b) > a > bf f1 x = f1 x
Why does a function of that type exist?
programs as proofsf :: (a > b) > a > bf f1 x = f1 x
Why does a function of that type exist?
A => B A———————————— B
programs as proofsf :: (a > b) > a > bf f1 x = f1 x
Why does a function of that type exist?
A => B [A]———————————— A => B
programs as proofsf :: (a > b) > (a > b)f f1 x = f1 x
Why does a function of that type exist?
[A => B] [A]———————————————————— (sort of a silly proof)(A => B) => (A => B)
if it's provable, you can write a program
a welltyped program constitutes a proof
programs as proofsf :: (b > c) > (a > b) > a > cf f1 f2 x = ???
programs as proofsf :: (b > c) > (a > b) > a > cf f1 f2 x = ???
compare:
A => B B => C——————————————— transitivity A => C
programs as proofsf :: (b > c) > (a > b) > a > cf f1 f2 x = f1 (f2 x)
compare:
A => B B => C——————————————— transitivity A => C
programs as proofsf :: (a > b > c) > b > a > c
programs as proofsflip :: (a > b > c) > b > a > cflip f y x = f x y
programs as proofsflip :: (a > b > c) > b > a > cflip f y x = f x y
So what is flip a proof of?
programs as proofsflip :: (a > b > c) > b > a > cflip f y x = f x y
So what is flip a proof of?
4 commutativity of implication
(A => (B => C)) <=> (B => (A => C))
but not every typehas a proof
programs as proofsf :: a > bf x = ???
programs as proofsf :: a > bf x = ???
If there is such a function, A => B must be provable.
?——————A => B
programs as proofsf :: a > bf x = ???
If there is such a function, A => B must be provable.
Nope.——————A => B
programs as proofsf :: a > bf x = ???
 hypothetical usage examples:foo :: Int bar :: Boolfoo = f "hello" bar = f "hello"
programs as proofsf :: a > bf x = ???
 hypothetical usage examples:foo :: Int bar :: Boolfoo = f "hello" bar = f "hello"
You can't construct a value of an unknown type.
c++ templates and proofstemplate <typename t, typename t2>t2 f(t a, t2 b) { return ???;}
c++ templates and proofstemplate <typename t, typename t2>t2 f(t a, t2 b) { return "whatever";}
okay, so…
`typename t` does not mean `∀t`
end of intermission
summary4 type theory is a formal language that describes how
terms and types relate to each other
4 a program is a proof of its type
4 not every type has a proof (or is inhabited)
end of theory
so like, how would iwrite a head function
if i needed to?
3 options
option 1: more explicit input typetype NonEmptyList a = (a, [a])
option 1: more explicit input typetype NonEmptyList a = (a, [a])
head :: NonEmptyList a > ahead (x, _) = x
option 2: more explicit output type head :: [a] > ??head (x:_) = ThereIsTotallyAn x
option 2: more explicit output type head :: [a] > ??head (x:_) = ThereIsTotallyAn xhead [] = NopeNothingNada
option 2: more explicit output typehead :: [a] > MaybeAn ahead (x:_) = ThereIsTotallyAn xhead [] = NopeNothingNada
option 2: more explicit output typehead :: [a] > MaybeAn ahead (x:_) = ThereIsTotallyAn xhead [] = NopeNothingNada
data MaybeAn a = ThereIsTotallyAn a  NopeNothingNada
MaybeAn a may contain an a, but it is not an a itself.
option 2: more explicit output typehead :: [a] > Maybe ahead (x:_) = Just xhead [] = Nothing
data Maybe a = Just a  Nothing
Maybe a may contain an a, but it is not an a itself.
option 3: lengthaware list typedata TaggedList length a   add here: constructors for  empty and nonempty lists 
data Zero  0data Succ n  1, 2, 3, 4, 5, 6, …
head :: TaggedList (Succ n) a > ahead (x : _) = x
option 3: lengthaware list typedata TaggedList length a where Empty :: TaggedList Zero a (:.) :: a  an item > TaggedList length a  a list > TaggedList (Succ length) a  a longer list
data Zero  0data Succ n  1, 2, 3, 4, 5, 6, …
head :: TaggedList (Succ n) a > ahead (x :. _) = x
wow
let's do somestatic ducktyping!
duck —> type# THIS IS PYTHON
def foo(x): return x * 2
print foo(3) # 6print foo("hi") # "hihi"
duck —> typefoo x = x * 2
main = do print (foo 3)  6
ghci> :type foofoo :: Num a => a > a
duck —> typefoo x = x * 2
main = do print (foo 3) print (foo "hi")
No instance for (Num [Char]) arising from a use of `foo'Possible fix: add an instance declaration for (Num [Char])In the first argument of `print', namely `(foo "hi")'In a stmt of a 'do' block: print (foo "hi")
duck —> typeclass Mul a where (*) :: a > Int > a
(a can be any concrete type)
duck —> typeclass Mul a where (*) :: a > Int > a
instance Mul Int where x * y = x Builtin.* y
instance Mul String where x * 1 = x x * n  n <= 0 = ""  n > 0 = x ++ x * (n  1)
duck —> typemain = do print (foo 3::Int)  6 print (foo "hi")  "hihi"
Boom. Done. Works.
bonus:
kinds
kindsThe comma in (Bool, Int) is a typeforming operator!
ghci> :kind (,)(,) :: * > * > *
kindsThe comma in (Bool, Int) is a typeforming operator!
ghci> :kind (,)(,) :: * > * > *
ghci> :kind (,) Bool(,) Bool :: * > *
kindsThe comma in (Bool, Int) is a typeforming operator!
ghci> :kind (,)(,) :: * > * > *
ghci> :kind (,) Bool(,) Bool :: * > *
ghci> :kind (,) Bool Int(,) Bool Int :: *
kindsghci> :kind [Int][] :: *
ghci> :kind [][] :: * > *
alright
Reading recommendation4 TTFP — Type Theory and Functional Programming
fin
questions
questions
appendix
nested listsvar nestedList = [ 1 , 2 , [ 3 , [ 4, 5 ] ] ];
nested listsdata NestedList a = Atom a  Nest [NestedList a]
nestedList :: NestedList IntnestedList = Nest [ Atom 1 , Atom 2 , Nest [ Atom 3 , Nest [ Atom 4 , Atom 5 ] ] ]