1 of 21

Parametricity

ryantm

2 of 21

Ad hoc Polymorphism

“Overloading”

f(int x)

f(bool x)

f(String x)

3 of 21

Parametric Polymorphism

“Generics”

def f[A](x: List[A]): List [A] // Scala

List<A> f<A>(List<A> x) // C#

<A> List<A> f(List<A> x) // Java

f :: [a] -> [a] -- Haskell

4 of 21

Parametric Polymorphism

Limits the function writer

Gives guarantees to the caller

5 of 21

Limits the function writer

f :: [a] -> [a]

`a` can be anything, which is very limiting

cannot dispatch on type of argument at runtime

6 of 21

Other limits on the function writer

fromMaybe :: a -> Maybe a -> a

Purely functional language: we can only use the arguments to construct the return.

7 of 21

Breaking parametricity

null, exceptions

Type-casing (isInstanceOf)

Type-casting (asInstanceOf)

Side-effects, equals/toString/hashCode

notify/wait, classOf/.getClass

General recursion

8 of 21

Parametric Polymorphism

These guarantees are given by parametricity

https://twitter.com/parametricity

9 of 21

Examples

f :: a -> a-> a

10 of 21

Examples

f :: a -> a-> a

f a1 _ = a1

or

f _ a2 = a2

11 of 21

Examples

f :: a -> Int

12 of 21

Examples

f :: a -> Int

f _ = 1

13 of 21

Examples

f :: [a] -> [b]

14 of 21

Examples

f :: [a] -> [b]

[ ] -- empty list

15 of 21

Examples

f :: [a] -> [a]

16 of 21

Examples

f :: [a] -> [a]

f = id

f = reverse

f as = as ++ as

17 of 21

Examples

q :: (a -> b) -> (b -> c) -> a -> c

18 of 21

Examples

q :: (a -> b) -> (b -> c) -> a -> c

q f g a = g (f a)

19 of 21

More complex guarantees

r :: [a] -> [a]

f :: a -> b

r (map f as) = map f (r as)

20 of 21

Parametricity Limitations

reverse :: [a] -> [a]

tail :: [a] -> [a]

Need automated checking to build confidence

21 of 21

References