lecture 8: summary of haskell course + type level...
TRANSCRIPT
![Page 1: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/1.jpg)
Lecture 8: Summary of Haskell course + TypeLevel Programming
Søren Haagerup
Department of Mathematics and Computer ScienceUniversity of Southern Denmark, Odense
October 31, 2017
![Page 2: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/2.jpg)
Principles from Haskell can be reused in otherlanguages
Sample piece of Java codeIf we should use some principles learned from this course, howwould we change this source code?
![Page 3: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/3.jpg)
Principles from Haskell can be reused in otherlanguages
• Write programs using small, pure functions, which areeasy to test and reason about
• Transform data using higher-order functions map, filter andfoldl/foldr/reduce
• Minimize mutation
• Minimize implicit dependencies
• Isolate side-effects – Avoid doing IO everywhere in yourprogram
![Page 4: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/4.jpg)
Types and Immutability
Mutable Immutabledata structures data structures
Dynamically typed Python Clojure (JVM)PHP Elixir (Erlang VM)
Statically typed Java (JVM), C# (CLR) HaskellC Scala (JVM)
There is a current trend towards more types and more precisetypes in programming languages.
![Page 5: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/5.jpg)
Nullable types
In C# we see something like the Maybe type constructor – thenullable types:
4
![Page 6: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/6.jpg)
TypeScript
• Taking a dynamically typed language (JavaScript) andturning it into a statically typed language.
• Compiler flags and LINT rules can be used to control howmany types are required from the programmer.
• TypeScript is a superset of Javascript, and with the mostrelaxed compiler flags, normal JavaScript can compileusing the TypeScript compiler.
5
![Page 7: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/7.jpg)
Introduction
• Type level programming is an activity which can only beperformed in languages with advanced type systemfeatures.
• Scala and Haskell are general-purpose languages where itis possible to do some Type-level programming.
• It might seem strange at first, but it is actually useful - wewill also see examples of this.
6
![Page 8: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/8.jpg)
Introduction
• Type level programming is an activity which can only beperformed in languages with advanced type systemfeatures.
• Scala and Haskell are general-purpose languages where itis possible to do some Type-level programming.
• It might seem strange at first, but it is actually useful - wewill also see examples of this.
6
![Page 9: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/9.jpg)
Introduction
• Type level programming is an activity which can only beperformed in languages with advanced type systemfeatures.
• Scala and Haskell are general-purpose languages where itis possible to do some Type-level programming.
• It might seem strange at first, but it is actually useful - wewill also see examples of this.
6
![Page 10: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/10.jpg)
Peano numbers represented by types
Recall the peano numbers
data Nat = Z | S Nat
where the numbers 0,1,2. . . are represented by the valuesZ, S Z, S (S Z). . . .
If we were to define this on the type levelinstead, we could introduce empty data declarations.
data Zdata S n
where the numbers 0,1,2. . . are represented by the typesZ, S Z, S (S Z). . . .The only member of the types is ⊥. I.e. ⊥ :: S (S Z).
7
![Page 11: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/11.jpg)
Peano numbers represented by types
Recall the peano numbers
data Nat = Z | S Nat
where the numbers 0,1,2. . . are represented by the valuesZ, S Z, S (S Z). . . . If we were to define this on the type levelinstead, we could introduce empty data declarations.
data Zdata S n
where the numbers 0,1,2. . . are represented by the typesZ, S Z, S (S Z). . . .The only member of the types is ⊥. I.e. ⊥ :: S (S Z).
7
![Page 12: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/12.jpg)
Type Classes ≈ Prolog PredicatesSo let’s say that we have defined
data Zdata S n
It turns out that the Prolog program
even(z).
even(s(N)):-odd(N).
odd(s(N)):-even(N).
corresponds quite closely to the following Haskell construction:
class Even nclass Odd ninstance Even Zinstance Odd n⇒ Even (S n)instance Even n⇒ Odd (S n)
8
![Page 13: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/13.jpg)
Prolog/Haskell sessions
| ?- even(z).
yes
| ?- even(s(z)).
no
In the Haskell context, the type n is even, if it is an instance ofthe type class Even n.
> :t (⊥ :: ((Even n)⇒ n)) :: Z(⊥ :: ((Even n)⇒ n)) :: Z :: Z> :t (⊥ :: ((Even n)⇒ n)) :: S Z< interactive>: 1 : 2 :
No instance for (Odd Z) arising from an expression type signatureIn the expression : (⊥ :: Even n⇒ n) :: S Z
9
![Page 14: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/14.jpg)
Defining addition for our type level numbers
add(0,B,B).
add(s(A),B,s(C)) :- add(A,B,C).
We can model this relation using multiparameter type classes
class Add a b cinstance Add Z b binstance Add a b c⇒ Add (S a) b (S c)
10
![Page 15: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/15.jpg)
Defining addition for our type level numbersclass Add a b cinstance Add Z b binstance Add a b c⇒ Add (S a) b (S c)
We can now verify an addition 1+3 = 4. To help us, define thefollowing “values”:
one :: S Zone = ⊥three :: S (S (S Z))three = ⊥add :: Add a b c⇒ a→ b→ cadd = ⊥
The addition is verified, since the following query type checks:
> :t add one three :: S (S (S (S Z)))add one three :: S (S (S (S Z))) :: S (S (S (S Z))) 11
![Page 16: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/16.jpg)
Multiparameter type classes+ Functional dependencies≈ Type level Functions
To define type level functions and not just relations, we need away to tell the compiler, that the “result” can be computedfrom the input. In Haskell, one can write:
class Add a b c | a b→ cinstance Add Z b binstance Add a b c⇒ Add (S a) b (S c)
> :t add three threeadd three three :: S (S (S (S (S (S Z)))))
12
![Page 17: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/17.jpg)
Practical Example: Length-indexed listsWe would like to introduce a data type Vec a n whichrepresents lists containing elements of type a, which is of lengthn. For example:
[ ] :: Vec Char Z[’a’ ] :: Vec a (S Z)[’a’,’b’ ] :: Vec a (S (S Z))[’a’,’b’,’c’ ] :: Vec a (S (S (S Z)))
We could then define
head :: Vec a (S n)→ atail :: Vec a (S n)→ Vec a nsafeZip :: Vec a n→ Vec b n→ Vec (a, b) n
Notice that head and tail would then be total functions, sincethe type checker discards the empty list.
13
![Page 18: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/18.jpg)
Practical Example: Length-indexed listsWe would like to introduce a data type Vec a n whichrepresents lists containing elements of type a, which is of lengthn. For example:
[ ] :: Vec Char Z[’a’ ] :: Vec a (S Z)[’a’,’b’ ] :: Vec a (S (S Z))[’a’,’b’,’c’ ] :: Vec a (S (S (S Z)))
We could then define
head :: Vec a (S n)→ atail :: Vec a (S n)→ Vec a nsafeZip :: Vec a n→ Vec b n→ Vec (a, b) n
Notice that head and tail would then be total functions, sincethe type checker discards the empty list.
13
![Page 19: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/19.jpg)
Practical Example: Length-indexed listsWe would like to introduce a data type Vec a n whichrepresents lists containing elements of type a, which is of lengthn. For example:
[ ] :: Vec Char Z[’a’ ] :: Vec a (S Z)[’a’,’b’ ] :: Vec a (S (S Z))[’a’,’b’,’c’ ] :: Vec a (S (S (S Z)))
We could then define
head :: Vec a (S n)→ atail :: Vec a (S n)→ Vec a nsafeZip :: Vec a n→ Vec b n→ Vec (a, b) n
Notice that head and tail would then be total functions, sincethe type checker discards the empty list.
13
![Page 20: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/20.jpg)
Why is it useful?
1. At compile time, we can make sure that the program willnever fail due to list length errors.
2. When implementing a matrix multiplication algorithm,where a matrix of size m× n should be multiplied by amatrix of size n× k, we do not need error handling in ourcode, if we are just working with types like the onepresented here.
3. There is no runtime overhead incurred by the extratype-level information - it is only used at compile time.
14
![Page 21: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/21.jpg)
Why is it useful?
1. At compile time, we can make sure that the program willnever fail due to list length errors.
2. When implementing a matrix multiplication algorithm,where a matrix of size m× n should be multiplied by amatrix of size n× k, we do not need error handling in ourcode, if we are just working with types like the onepresented here.
3. There is no runtime overhead incurred by the extratype-level information - it is only used at compile time.
14
![Page 22: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/22.jpg)
Why is it useful?
1. At compile time, we can make sure that the program willnever fail due to list length errors.
2. When implementing a matrix multiplication algorithm,where a matrix of size m× n should be multiplied by amatrix of size n× k, we do not need error handling in ourcode, if we are just working with types like the onepresented here.
3. There is no runtime overhead incurred by the extratype-level information - it is only used at compile time.
14
![Page 23: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/23.jpg)
IntroducingGeneralized Algebraic Data Types (GADTs)
It is not obvious how to define a type Vec with the propertiesfrom the previous slide, from what we have learned in thiscourse.The modern way to achieve it in Haskell is to use aGeneralized Algebraic Data Type (GADTs).
15
![Page 24: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/24.jpg)
IntroducingGeneralized Algebraic Data Types (GADTs)
The traditional ADT for lists
data List a = Nil | Cons a (List a)
can be written in GADT-notation by
data List a whereNil :: List aCons :: a→ List a→ List a
We specify the complete type signature of the data constructors.Referring to our types Z and S n from earlier, we can define
data Vec :: ∗ → ∗ → ∗whereNil :: Vec a ZCons :: a→ Vec a n→ Vec a (S n)
16
![Page 25: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/25.jpg)
head, tail and safeZip
Now we can define the functions announced earlier:
head :: Vec a (S n)→ ahead (Cons x ) = x
tail :: Vec a (S n)→ Vec a ntail (Cons xs) = xs
safeZip :: Vec a n→ Vec b n→ Vec (a, b) nsafeZip Nil Nil = NilsafeZip (Cons x xs) (Cons y ys) = Cons (x, y) (safeZip xs ys)
17
![Page 26: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/26.jpg)
Implementing replicate
We would like to implement replicate for our length-indexedvectors.
replicate :: n→ a→ Vec n a
What is wrong with this type?
The previously mentioned functions only used S n and Z onthe type level. But sometimes it is useful to give S n and Z asarguments to functions.
18
![Page 27: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/27.jpg)
Implementing replicate
We would like to implement replicate for our length-indexedvectors.
replicate :: n→ a→ Vec n a
What is wrong with this type?The previously mentioned functions only used S n and Z onthe type level. But sometimes it is useful to give S n and Z asarguments to functions.
18
![Page 28: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/28.jpg)
Singleton types:Chaining the type and the value level together
But we can add a singleton-type Nat which connects the valuelevel and the type level:
data Nat nat whereZ :: Nat ZS :: Nat n→ Nat (S n)
Then we can define
replicate :: Nat n→ a→ Vec n areplicate Z = Nilreplicate (S n) x = Cons x (replicate n x)
19
![Page 29: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/29.jpg)
What would be the type of (++)?
Let’s say we give input lists xs :: Vec a n and ys :: Vec a m.What could be a proper type for
(++) :: ?Nil ++ ys = ys(Cons x xs) ++ ys = Cons x (xs ++ ys)
20
![Page 30: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/30.jpg)
What would be the type of (++)?
Let’s say we give input lists xs :: Vec a n and ys :: Vec a m.We can use our type class from earlier:
(++) :: (Add n m r)⇒ Vec a n→ Vec a m→ Vec a rNil ++ ys = ys(Cons x xs) ++ ys = Cons x (xs ++ ys)
We can end up with a function (++) with the type given above,but we need to write the definition a bit differently.
21
![Page 31: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/31.jpg)
What would be the type of (++)?
Let’s say we give input lists xs :: Vec a n and ys :: Vec a m.We can use our type class from earlier:
(++) :: (Add n m r)⇒ Vec a n→ Vec a m→ Vec a rNil ++ ys = ys(Cons x xs) ++ ys = Cons x (xs ++ ys)
We can end up with a function (++) with the type given above,but we need to write the definition a bit differently.
21
![Page 32: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/32.jpg)
Defining (++) as a part of the Add type class
class Add a b c | a b→ c where(++) :: Vec t a→ Vec t b→ Vec t c
instance Add Z b b whereNil ++ ys = ys
instance Add a b c⇒ Add (S a) b (S c) where(Cons x xs) ++ ys = Cons x (xs ++ ys)
22
![Page 33: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/33.jpg)
Making life easier againHaskell Programmers have not been so happy about thesolution from before:
(++) :: (Add n m r)⇒ Vec a n→ Vec a m→ Vec a r
They asked:
1. Why do we need to add a type class constraint?
2. Why do we have to do our type level programming usingthe logical programming paradigm?
Wouldn’t it be better to introduce a way to write type levelfunctions using functional programming paradigm, and end upwith a type like
(++) :: Vec a n→ Vec a m→ Vec a (n :+ m)
where (:+ ) is a function on types?
23
![Page 34: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/34.jpg)
Making life easier againHaskell Programmers have not been so happy about thesolution from before:
(++) :: (Add n m r)⇒ Vec a n→ Vec a m→ Vec a r
They asked:
1. Why do we need to add a type class constraint?
2. Why do we have to do our type level programming usingthe logical programming paradigm?
Wouldn’t it be better to introduce a way to write type levelfunctions using functional programming paradigm, and end upwith a type like
(++) :: Vec a n→ Vec a m→ Vec a (n :+ m)
where (:+ ) is a function on types?
23
![Page 35: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/35.jpg)
Making life easier againHaskell Programmers have not been so happy about thesolution from before:
(++) :: (Add n m r)⇒ Vec a n→ Vec a m→ Vec a r
They asked:
1. Why do we need to add a type class constraint?
2. Why do we have to do our type level programming usingthe logical programming paradigm?
Wouldn’t it be better to introduce a way to write type levelfunctions using functional programming paradigm, and end upwith a type like
(++) :: Vec a n→ Vec a m→ Vec a (n :+ m)
where (:+ ) is a function on types?23
![Page 36: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/36.jpg)
Type families ≈ Type level functions
The following is a quite new feature of Haskell:
infixl 6 :+
type family n1 :+ n2 :: ∗type instance Z :+ n2 = n2type instance S n1 :+ n2 = S (n1 :+ n2)
infixr 5 ++
(++) :: Vec a n1→ Vec a n2→ Vec a (n1 :+ n2)Nil ++ ys = ysCons x xs ++ ys = Cons x (xs ++ ys)
24
![Page 37: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/37.jpg)
Practical example:Function with variable number of arguments
Say, we would like to implement the following family offunctions that sum up their integer arguments:
sumn :: Int1 → · · · → Intn → Intsumn = λi1 → · · · → λin → i1 + · · ·+ in
25
![Page 38: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/38.jpg)
Solution using a Type Family
type family MultiArgs n a :: ∗type instance MultiArgs Z a = atype instance MultiArgs (S n) a = a→MultiArgs n a
sum ′ :: Nat n→ Int→MultiArgs n Intsum ′ Z acc = accsum ′ (S n) acc = λi→ sum ′ n (acc + i)
sum :: Nat n→MultiArgs n Intsum n = sum ′ n 0
26
![Page 39: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/39.jpg)
Solution using a Type Family
type family MultiArgs n a :: ∗type instance MultiArgs Z a = atype instance MultiArgs (S n) a = a→MultiArgs n a
sum ′ :: Nat n→ Int→MultiArgs n Intsum ′ Z acc = accsum ′ (S n) acc = λi→ sum ′ n (acc + i)
sum :: Nat n→MultiArgs n Intsum n = sum ′ n 0
26
![Page 40: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/40.jpg)
Solution using a Type Family
Example GHCi session:
> sum Z0> sum (S Z)
< interactive>: 3 : 1 :
No instance for (Show (Int→ Int)) arising from a use of ‘ print ′
In a stmt of an interactive GHCi command : print it> sum (S Z) 33> sum (S (S Z)) 3 47
27
![Page 41: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/41.jpg)
Dependently Typed Programming
• A dependent type is a type that depends on a value.
• A dependent function’s return type may depend on thevalue of an argument
• The examples we have just seen with length-indexedvectors and functions with a variable number ofarguments, are examples of dependently typedprogramming.
28
![Page 42: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/42.jpg)
Dependently Typed Programming
• A dependent type is a type that depends on a value.
• A dependent function’s return type may depend on thevalue of an argument
• The examples we have just seen with length-indexedvectors and functions with a variable number ofarguments, are examples of dependently typedprogramming.
28
![Page 43: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/43.jpg)
Dependently Typed Programming
• A dependent type is a type that depends on a value.
• A dependent function’s return type may depend on thevalue of an argument
• The examples we have just seen with length-indexedvectors and functions with a variable number ofarguments, are examples of dependently typedprogramming.
28
![Page 44: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/44.jpg)
Phase distinction: Types are not values• In Haskell, types and values live in different scopes. We
can use singleton types to chain types and values together.
• Very recent versions of GHC have automatical promotion ofvalue level constructions to the type level.
• In general, features from the value level are being portedto the type level (functions→ type families),
• In general, features from the type level are being ported tothe kind level (type polymorphism→ kind polymorphism)
• Other languages, like Agda and Coq have an infinite stackof levels. And concepts from lower levels can be used onhigher leves. In Haskell, for now, we are restricted to thesmall hierarchy
value : type : kind : sortwhich - for practical purposes - seems to be enough.
29
![Page 45: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/45.jpg)
Phase distinction: Types are not values• In Haskell, types and values live in different scopes. We
can use singleton types to chain types and values together.• Very recent versions of GHC have automatical promotion of
value level constructions to the type level.
• In general, features from the value level are being portedto the type level (functions→ type families),
• In general, features from the type level are being ported tothe kind level (type polymorphism→ kind polymorphism)
• Other languages, like Agda and Coq have an infinite stackof levels. And concepts from lower levels can be used onhigher leves. In Haskell, for now, we are restricted to thesmall hierarchy
value : type : kind : sortwhich - for practical purposes - seems to be enough.
29
![Page 46: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/46.jpg)
Phase distinction: Types are not values• In Haskell, types and values live in different scopes. We
can use singleton types to chain types and values together.• Very recent versions of GHC have automatical promotion of
value level constructions to the type level.• In general, features from the value level are being ported
to the type level (functions→ type families),
• In general, features from the type level are being ported tothe kind level (type polymorphism→ kind polymorphism)
• Other languages, like Agda and Coq have an infinite stackof levels. And concepts from lower levels can be used onhigher leves. In Haskell, for now, we are restricted to thesmall hierarchy
value : type : kind : sortwhich - for practical purposes - seems to be enough.
29
![Page 47: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/47.jpg)
Phase distinction: Types are not values• In Haskell, types and values live in different scopes. We
can use singleton types to chain types and values together.• Very recent versions of GHC have automatical promotion of
value level constructions to the type level.• In general, features from the value level are being ported
to the type level (functions→ type families),• In general, features from the type level are being ported to
the kind level (type polymorphism→ kind polymorphism)
• Other languages, like Agda and Coq have an infinite stackof levels. And concepts from lower levels can be used onhigher leves. In Haskell, for now, we are restricted to thesmall hierarchy
value : type : kind : sortwhich - for practical purposes - seems to be enough.
29
![Page 48: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/48.jpg)
Phase distinction: Types are not values• In Haskell, types and values live in different scopes. We
can use singleton types to chain types and values together.• Very recent versions of GHC have automatical promotion of
value level constructions to the type level.• In general, features from the value level are being ported
to the type level (functions→ type families),• In general, features from the type level are being ported to
the kind level (type polymorphism→ kind polymorphism)• Other languages, like Agda and Coq have an infinite stack
of levels. And concepts from lower levels can be used onhigher leves. In Haskell, for now, we are restricted to thesmall hierarchy
value : type : kind : sortwhich - for practical purposes - seems to be enough.
29
![Page 49: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/49.jpg)
A taste of theCurry-Howard Isomorphism using Haskell
• A deep result from Computer Science, is the directrelationship between computer programs andmathematical proofs.
• This correspondance is the foundation of programminglanguages like Agda and Coq
• Essentially there is a bijection such that• Mathematical Propositions ≈ Types• Mathematical Proofs ≈ Programs
30
![Page 50: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/50.jpg)
A taste of theCurry-Howard Isomorphism using Haskell
The reverse function is essentially the following:
reverse :: Vec a n→ Vec a nreverse xs = go Nil xs
go :: Vec a m→ Vec a k→ Vec a (k :+ m)
go acc Nil = accgo acc (Cons x xs) = go (Cons x acc) xs
But it does not type check out of the box... It comes up withtwo quite clear error messages, though:
1. In def. of reverse: Couldn’t match type n with n :+ Z2. In def. of go: Could not deduce ((n :+ S m)∼S (n :+ m))
from the context (k∼S n) bound by a pattern withconstructor
Cons :: a→ Vec a n→ Vec a (S n)
31
![Page 51: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/51.jpg)
A taste of theCurry-Howard Isomorphism using Haskell
The reverse function is essentially the following:
reverse :: Vec a n→ Vec a nreverse xs = go Nil xs
go :: Vec a m→ Vec a k→ Vec a (k :+ m)
go acc Nil = accgo acc (Cons x xs) = go (Cons x acc) xs
But it does not type check out of the box... It comes up withtwo quite clear error messages, though:
1. In def. of reverse: Couldn’t match type n with n :+ Z2. In def. of go: Could not deduce ((n :+ S m)∼S (n :+ m))
from the context (k∼S n) bound by a pattern withconstructor
Cons :: a→ Vec a n→ Vec a (S n) 31
![Page 52: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/52.jpg)
A taste of theCurry-Howard Isomorphism using Haskell
We essentially need to prove the following statements aboutour Peano numbers defined on type level
∀n.n :+ Z ≡ n
and
∀n, m.(n :+ (S m)) ≡ (S (n :+ m))
As indicated earlier, a proof corresponds to program code.
32
![Page 53: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/53.jpg)
A taste of the C-H Iso. using HaskellBelow, we have extended our reverse definition with theneeded proofs:
go :: Vec a m→ Vec a k→ Vec a (k :+ m)
go acc Nil = accgo acc (Cons x xs) = subst (plus suc (size xs) (size acc))
$ go (Cons x acc) xs
reverse :: Vec a n→ Vec a nreverse xs = subst (plus zero (size xs))
$ go Nil xs
I have not explained how subst, size, plus suc and plus size isdefined1 - this could be a subject for another course.
1The details can be found onhttp://dev.stephendiehl.com/hask/#advanced-proofs
33
![Page 54: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/54.jpg)
This is it• This was the last lecture of the Haskell part of the
Programming Languages course.
• The obligatory assignment, due 13th of November at23.59 is the first half of your exam.
• My exam is The course evaluation, to be filled out by younow. To remind you, this was what we covered in each ofthe 8 lectures:
1. Expressions, Types and Patterns2. List algorithms, explicit recursion and list comprehensions3. List algorithms using higher order functions4. Algebraic Data Types5. Lazy Evaluation and Infinite Data Structures6. Proving and Testing Program Properties7. Monads and IO8. Type Level Programming
34
![Page 55: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/55.jpg)
This is it• This was the last lecture of the Haskell part of the
Programming Languages course.• The obligatory assignment, due 13th of November at
23.59 is the first half of your exam.
• My exam is The course evaluation, to be filled out by younow. To remind you, this was what we covered in each ofthe 8 lectures:
1. Expressions, Types and Patterns2. List algorithms, explicit recursion and list comprehensions3. List algorithms using higher order functions4. Algebraic Data Types5. Lazy Evaluation and Infinite Data Structures6. Proving and Testing Program Properties7. Monads and IO8. Type Level Programming
34
![Page 56: Lecture 8: Summary of Haskell course + Type Level Programmingshaagerup.github.io/dm552/files/lec8.pdf · data structures data structures Dynamically typed Python Clojure (JVM) PHP](https://reader033.vdocuments.mx/reader033/viewer/2022050302/5f6b653f4a598f7a9805cb8c/html5/thumbnails/56.jpg)
This is it• This was the last lecture of the Haskell part of the
Programming Languages course.• The obligatory assignment, due 13th of November at
23.59 is the first half of your exam.• My exam is The course evaluation, to be filled out by you
now. To remind you, this was what we covered in each ofthe 8 lectures:
1. Expressions, Types and Patterns2. List algorithms, explicit recursion and list comprehensions3. List algorithms using higher order functions4. Algebraic Data Types5. Lazy Evaluation and Infinite Data Structures6. Proving and Testing Program Properties7. Monads and IO8. Type Level Programming
34