algebraic types - gitlab · 2020. 3. 19. · dataexpr = lit integer| add exprexpr| sub exprexpr...

26
Algebraic Types Chapter 14 of Thompson

Upload: others

Post on 05-Mar-2021

4 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Algebraic Types - GitLab · 2020. 3. 19. · dataExpr = Lit Integer| Add ExprExpr| Sub ExprExpr This describes an integer expression as something that one of: a literal, like 42;

Algebraic TypesChapter 14 of Thompson

Page 2: Algebraic Types - GitLab · 2020. 3. 19. · dataExpr = Lit Integer| Add ExprExpr| Sub ExprExpr This describes an integer expression as something that one of: a literal, like 42;

Types so far …

Base types Int, Integer, Float, Bool, CharComposite types:

tuples (t1,t2,…,tn)lists [t1]functions (t1 -> t2)

Algebraic types enumerated, product (record), sum (union)Now, we will see more types that are recursive and polymorphic

Page 3: Algebraic Types - GitLab · 2020. 3. 19. · dataExpr = Lit Integer| Add ExprExpr| Sub ExprExpr This describes an integer expression as something that one of: a literal, like 42;

Recursive types: example

data NTree = NilT |Node Integer NTree NTree

Such types allow us to build data structures of arbitrary size.

12

10 17

14 20• •

• • • •

Page 4: Algebraic Types - GitLab · 2020. 3. 19. · dataExpr = Lit Integer| Add ExprExpr| Sub ExprExpr This describes an integer expression as something that one of: a literal, like 42;
Page 5: Algebraic Types - GitLab · 2020. 3. 19. · dataExpr = Lit Integer| Add ExprExpr| Sub ExprExpr This describes an integer expression as something that one of: a literal, like 42;

Polymorphic types: example

data Maybe a = Nothing | Just a

Built into the Haskell prelude and used for modelling program errors.

Reusable in different situations, such as the built in list type.

Page 6: Algebraic Types - GitLab · 2020. 3. 19. · dataExpr = Lit Integer| Add ExprExpr| Sub ExprExpr This describes an integer expression as something that one of: a literal, like 42;

Review: algebraic data types in general

data Typename= Con1 t11 t12 … t1i |

Con2 t21 t22 … t2j |…Conm tm1 tm2 … tmk

Each Coni is a constructor, followed by n types, where n ≥ 0, allowing us to build values of the type by using the constructor as a function:Coni :: ti1 -> ti2 -> … -> tin -> Typename

Page 7: Algebraic Types - GitLab · 2020. 3. 19. · dataExpr = Lit Integer| Add ExprExpr| Sub ExprExpr This describes an integer expression as something that one of: a literal, like 42;

Examples

Enumerated types have constructors with no arguments:data Season = Spring | Summer | Autumn | Winter

Product types have a single constructor:data People = Person Name Age

Sum types have a number of constructors taking different arguments:data Shape = Circle Float |

Rectangle Float Float

Page 8: Algebraic Types - GitLab · 2020. 3. 19. · dataExpr = Lit Integer| Add ExprExpr| Sub ExprExpr This describes an integer expression as something that one of: a literal, like 42;

Examples: pattern matching

To distinguish among alternatives and to extract components:

area :: Shape -> Floatarea (Circle r) = pi*r*rarea (Rectangle h w) = h*w

Page 9: Algebraic Types - GitLab · 2020. 3. 19. · dataExpr = Lit Integer| Add ExprExpr| Sub ExprExpr This describes an integer expression as something that one of: a literal, like 42;

Recursive algebraic types: example

A recursive type is a type described in terms of itself:data Expr = Lit Integer |

Add Expr Expr |Sub Expr Expr

This describes an integer expression as something that one of:a literal, like 42;the sum of two subexpressions; orthe difference between two subexpressions

expr1 = Lit 2expr2 = Add (Lit 2) (Lit 3)expr3 = Add (Sub (Lit 3) (Lit 1)) (Lit 3)

Expr

Lit 2

Expr

Add

Lit 2 Lit 3

Expr

Add

Sub Lit 3

Lit 3 Lit 1

Page 10: Algebraic Types - GitLab · 2020. 3. 19. · dataExpr = Lit Integer| Add ExprExpr| Sub ExprExpr This describes an integer expression as something that one of: a literal, like 42;

Primitive recursion over expressions

[Live coding for eval and show over integer expressions]

Page 11: Algebraic Types - GitLab · 2020. 3. 19. · dataExpr = Lit Integer| Add ExprExpr| Sub ExprExpr This describes an integer expression as something that one of: a literal, like 42;

Recursive algebraic types: trees

A tree is either nil (empty) or the joining of two subtrees into a tree node:data NTree = NilT |

Node Integer NTree NTreeFor example:

treeEx1 = Node 10 NilT NilTtreeEx2 = Node 17 (Node 14 NilT NilT)

(Node 20 NilT NilT)

Similarly, a list is either the empty list []or constructed from a head and a tail using :

list1 = [10, [], []]list2 = [17, [14, [], []], [20, [], []]]

10

• •

17

14 20

• • • •

Page 12: Algebraic Types - GitLab · 2020. 3. 19. · dataExpr = Lit Integer| Add ExprExpr| Sub ExprExpr This describes an integer expression as something that one of: a literal, like 42;

Primitive recursion over trees

[live coding for sumTree, depth, occurs]

Page 13: Algebraic Types - GitLab · 2020. 3. 19. · dataExpr = Lit Integer| Add ExprExpr| Sub ExprExpr This describes an integer expression as something that one of: a literal, like 42;

More recursion over expressions

Since addition is associative, it would be nice to present integer expressions including addition in a normalized right-associative form:

(2+3)+4 = 2+(3+4)((2+3)+4)+5 = 2+(3+(4+5))((2-((6+7)+8))+4)+5 = (2-(6+(7+8)))+(4+5)

Aim: spot occurrences ofAdd (Add e1 e2) e3

and transform them toAdd e1 (Add e2 e3)

[live coding for assoc]

Page 14: Algebraic Types - GitLab · 2020. 3. 19. · dataExpr = Lit Integer| Add ExprExpr| Sub ExprExpr This describes an integer expression as something that one of: a literal, like 42;

Non-primitive recursion over expressions

assoc :: Expr -> Expr

assoc (Add (Add e1 e2) e3)= assoc (Add e1 (Add e2 e3))

assoc (Add e1 e2) = Add (assoc e1) (assoc e2)

assoc (Sub e1 e2) = Sub (assoc e1) (assoc e2)

assoc (Lit n) = Lit n

Page 15: Algebraic Types - GitLab · 2020. 3. 19. · dataExpr = Lit Integer| Add ExprExpr| Sub ExprExpr This describes an integer expression as something that one of: a literal, like 42;

Termination

assoc (Add (Add e1 e2) e3)= assoc (Add e1 (Add e2 e3))

The RHS makes progress by moving the expression tree from left-associative to right-associative.None of the other equations move a plus in the other direction, so after applying the above equation some finite number of times there will be no more exposed addition symbols at the top level of the LHS.

Page 16: Algebraic Types - GitLab · 2020. 3. 19. · dataExpr = Lit Integer| Add ExprExpr| Sub ExprExpr This describes an integer expression as something that one of: a literal, like 42;

Syntax: infix constructors

Can also write:data Expr' = Lit' Integer |

Expr' :+: Expr' |Expr' :-: Expr'

The infix operators must start with :

Page 17: Algebraic Types - GitLab · 2020. 3. 19. · dataExpr = Lit Integer| Add ExprExpr| Sub ExprExpr This describes an integer expression as something that one of: a literal, like 42;

Mutual recursion

data Person = Adult Name Address Bio |Child Name

data Bio = Parent String [Person] |NonParent String

type Name = Stringtype Address = [String]

Page 18: Algebraic Types - GitLab · 2020. 3. 19. · dataExpr = Lit Integer| Add ExprExpr| Sub ExprExpr This describes an integer expression as something that one of: a literal, like 42;

Mutual recursion

showPerson (Adult nm ad bio) = show nm ++ show ad ++ showBio bio

showPerson (Child nm) = show nm

showBio (Parent st perList)= st ++ concat (map showPerson perList)

showBio (NonParent st)= st

Page 19: Algebraic Types - GitLab · 2020. 3. 19. · dataExpr = Lit Integer| Add ExprExpr| Sub ExprExpr This describes an integer expression as something that one of: a literal, like 42;
Page 20: Algebraic Types - GitLab · 2020. 3. 19. · dataExpr = Lit Integer| Add ExprExpr| Sub ExprExpr This describes an integer expression as something that one of: a literal, like 42;

Polymorphic algebraic types

Type variables can be used to make an algebraic type polymorphic.Example:

data Pairs a = Pr a a

pair1 = Pr 2 3 :: Pairs Intpair2 = Pr [] [3] :: Pairs [Int]pair3 = Pr [] [] :: Pairs [a]

equalPair :: Eq a => Pairs a -> BoolequalPair (Pr x y) = (x==y)

Page 21: Algebraic Types - GitLab · 2020. 3. 19. · dataExpr = Lit Integer| Add ExprExpr| Sub ExprExpr This describes an integer expression as something that one of: a literal, like 42;

Polymorphic algebraic types: lists

infixr 5 ::: -- same fixity and associativity as list cons :data List a = NilL | a ::: (List a)

deriving (Eq,Ord,Show,Read)A user-defined list type:List a instead of builtin [a]NillL instead of builtin []::: instead of builtin :

2+3 ::: 4+5 ::: NilL5 ::: (9 ::: NilL)

Page 22: Algebraic Types - GitLab · 2020. 3. 19. · dataExpr = Lit Integer| Add ExprExpr| Sub ExprExpr This describes an integer expression as something that one of: a literal, like 42;

Polymorphic algebraic types: trees

data Tree a = Nil | Node a (Tree a) (Tree a)deriving (Eq,Ord,Show,Read)

depthT :: Tree a -> IntegerdepthT Nil = 0depthT (Node n t1 t2) = 1 + max (depthT t1) (depthT t2)

collapse :: Tree a -> [a]collapse Nil = []collapse (Node x t1 t2)

= collapse t1 ++ [x] ++ collapse t2

Page 23: Algebraic Types - GitLab · 2020. 3. 19. · dataExpr = Lit Integer| Add ExprExpr| Sub ExprExpr This describes an integer expression as something that one of: a literal, like 42;

Polymorphic algebraic types: trees

collapse (Node 12(Node 34 Nil Nil) (Node 3 (Node 17 Nil Nil) Nil))

= [34, 12, 17, 3]

Page 24: Algebraic Types - GitLab · 2020. 3. 19. · dataExpr = Lit Integer| Add ExprExpr| Sub ExprExpr This describes an integer expression as something that one of: a literal, like 42;

Polymorphic algebraic types: trees

mapTree :: (a -> b) -> Tree a -> Tree bmapTree f Nil = NilmapTree f (Node x t1 t2)

= Node (f x) (mapTree f t1) (mapTree f t2)

Page 25: Algebraic Types - GitLab · 2020. 3. 19. · dataExpr = Lit Integer| Add ExprExpr| Sub ExprExpr This describes an integer expression as something that one of: a literal, like 42;

Polymorphic algebraic types: sum types

data Either a b = Left a | Right b

deriving (Eq,Ord,Read,Show)

eitherEG1 = Left "Duke of Prunes”

:: Either String Int

eitherEG2 = Right 33312

:: Either String Int

isLeft :: Either a b -> Bool

isLeft (Left _) = TrueisLeft (Right _) = False

Page 26: Algebraic Types - GitLab · 2020. 3. 19. · dataExpr = Lit Integer| Add ExprExpr| Sub ExprExpr This describes an integer expression as something that one of: a literal, like 42;

Polymorphic algebraic types: sum types

either :: (a -> c) -> (b -> c) -> Either a b -> c

This is a higher-order function: takes functions as arguments.

Functions can also return functions as results!

either f g (Left x) = f xeither f g (Right y) = g y