Programming in Haskell: Lecture 21

S P Suresh

October 28, 2019

Suresh PRGH 2019: Lecture 21 October 28, 2019 1 / 20 • A recursive datatype t is one which has some components of the same type t

• Some constructors of a recursive type t have t among their input types, as well as the return type

Recursive data types

• Just like we have recursive functions, we can have recursive data types

Suresh PRGH 2019: Lecture 21 October 28, 2019 2 / 20 • Some constructors of a recursive t have t among their input types, as well as the return type

Recursive data types

• Just like we have recursive functions, we can have recursive data types

• A recursive datatype t is one which has some components of the same type t

Suresh PRGH 2019: Lecture 21 October 28, 2019 2 / 20 Recursive data types

• Just like we have recursive functions, we can have recursive data types

• A recursive datatype t is one which has some components of the same type t

• Some constructors of a recursive data type t have t among their input types, as well as the return type

Suresh PRGH 2019: Lecture 21 October 28, 2019 2 / 20 Example: Nat

• Simplest recursive data type

data Nat = Zero | Succ Nat

Zero :: Nat Succ :: Nat -> Nat

Suresh PRGH 2019: Lecture 21 October 28, 2019 3 / 20 • Predecessor:

pred :: Nat -> Nat pred Zero = Zero pred (Succ n) = n

Functions on Nat

• Check for zero:

isZero :: Nat -> Bool isZero Zero = True isZero _ = False

Suresh PRGH 2019: Lecture 21 October 28, 2019 4 / 20 Functions on Nat

• Check for zero:

isZero :: Nat -> Bool isZero Zero = True isZero _ = False

• Predecessor:

pred :: Nat -> Nat pred Zero = Zero pred (Succ n) = n

Suresh PRGH 2019: Lecture 21 October 28, 2019 4 / 20 • Multiplication:

mult :: Nat -> Nat -> Nat mult m Zero = Zero mult m (Succ n) = plus m (mult m n)

Functions on Nat

• Addition:

plus :: Nat -> Nat -> Nat plus m Zero = m plus m (Succ n) = Succ (plus m n)

Suresh PRGH 2019: Lecture 21 October 28, 2019 5 / 20 Functions on Nat

• Addition:

plus :: Nat -> Nat -> Nat plus m Zero = m plus m (Succ n) = Succ (plus m n)

• Multiplication:

mult :: Nat -> Nat -> Nat mult m Zero = Zero mult m (Succ n) = plus m (mult m n)

Suresh PRGH 2019: Lecture 21 October 28, 2019 5 / 20 • The left show has type Nat -> String • The left show has type Int -> String

• In show = show . turnToInt

Showing Nat

• A custom show for Nat:

data Nat = Zero | Succ Nat instance Show Nat where show = show . turnToInt turnToInt :: Nat -> Int turnToInt Zero = 0 turnToInt (Succ n) = turnToInt n + 1

Suresh PRGH 2019: Lecture 21 October 28, 2019 6 / 20 • The left show has type Nat -> String • The left show has type Int -> String

Showing Nat

• A custom show for Nat:

data Nat = Zero | Succ Nat instance Show Nat where show = show . turnToInt turnToInt :: Nat -> Int turnToInt Zero = 0 turnToInt (Succ n) = turnToInt n + 1

• In show = show . turnToInt

Suresh PRGH 2019: Lecture 21 October 28, 2019 6 / 20 • The left show has type Int -> String

Showing Nat

• A custom show for Nat:

data Nat = Zero | Succ Nat instance Show Nat where show = show . turnToInt turnToInt :: Nat -> Int turnToInt Zero = 0 turnToInt (Succ n) = turnToInt n + 1

• In show = show . turnToInt • The left show has type Nat -> String

Suresh PRGH 2019: Lecture 21 October 28, 2019 6 / 20 Showing Nat

• A custom show for Nat:

data Nat = Zero | Succ Nat instance Show Nat where show = show . turnToInt turnToInt :: Nat -> Int turnToInt Zero = 0 turnToInt (Succ n) = turnToInt n + 1

• In show = show . turnToInt • The left show has type Nat -> String • The left show has type Int -> String

Suresh PRGH 2019: Lecture 21 October 28, 2019 6 / 20 • This is the built-in type [a] • Functions are defined as usual on pattern matching:

head :: List a -> a head ( x _) = x

• Exception on head Nil

Example: List

• Recursive data types can also be polymorphic

List a = Nil | Cons a (List a)

Suresh PRGH 2019: Lecture 21 October 28, 2019 7 / 20 • Functions are defined as usual on pattern matching:

head :: List a -> a head (Cons x _) = x

• Exception on head Nil

Example: List

• Recursive data types can also be polymorphic

List a = Nil | Cons a (List a)

• This is the built-in type [a]

Suresh PRGH 2019: Lecture 21 October 28, 2019 7 / 20 • Exception on head Nil

Example: List

• Recursive data types can also be polymorphic

List a = Nil | Cons a (List a)

• This is the built-in type [a] • Functions are defined as usual on pattern matching:

head :: List a -> a head (Cons x _) = x

Suresh PRGH 2019: Lecture 21 October 28, 2019 7 / 20 Example: List

• Recursive data types can also be polymorphic

List a = Nil | Cons a (List a)

• This is the built-in type [a] • Functions are defined as usual on pattern matching:

head :: List a -> a head (Cons x _) = x

• Exception on head Nil

Suresh PRGH 2019: Lecture 21 October 28, 2019 7 / 20 • Exception on head Nil

• Can fix it with custom head

head :: List a -> Maybe a head Nil = Nothing head (Cons x _) = Just x

List

• List and head

List a = Nil | Cons a (List a) head :: List a -> a head (Cons x _) = x

Suresh PRGH 2019: Lecture 21 October 28, 2019 8 / 20 • Can fix it with custom head

head :: List a -> Maybe a head Nil = Nothing head (Cons x _) = Just x

List

• List and head

List a = Nil | Cons a (List a) head :: List a -> a head (Cons x _) = x

• Exception on head Nil

Suresh PRGH 2019: Lecture 21 October 28, 2019 8 / 20 List

• List and head

List a = Nil | Cons a (List a) head :: List a -> a head (Cons x _) = x

• Exception on head Nil

• Can fix it with custom head

head :: List a -> Maybe a head Nil = Nothing head (Cons x _) = Just x

Suresh PRGH 2019: Lecture 21 October 28, 2019 8 / 20 • The empty is a binary tree • A node containing an element with left and right subtrees is a binary tree

BTree

data BTree a = Nil | Node (BTree a) a (BTree a)

• Two value constructors:

Nil :: BTree a Node :: BTree a -> a -> BTree a -> BTree a

Binary trees

• A binary tree is defined as follows:

Suresh PRGH 2019: Lecture 21 October 28, 2019 9 / 20 • A node containing an element with left and right subtrees is a binary tree

• Type constructor BTree

data BTree a = Nil | Node (BTree a) a (BTree a)

• Two value constructors:

Nil :: BTree a Node :: BTree a -> a -> BTree a -> BTree a

Binary trees

• A binary tree data structure is defined as follows: • The empty tree is a binary tree

Suresh PRGH 2019: Lecture 21 October 28, 2019 9 / 20 • Type constructor BTree

data BTree a = Nil | Node (BTree a) a (BTree a)

• Two value constructors:

Nil :: BTree a Node :: BTree a -> a -> BTree a -> BTree a

Binary trees

• A binary tree data structure is defined as follows: • The empty tree is a binary tree • A node containing an element with left and right subtrees is a binary tree

Suresh PRGH 2019: Lecture 21 October 28, 2019 9 / 20 • Two value constructors:

Nil :: BTree a Node :: BTree a -> a -> BTree a -> BTree a

Binary trees

• A binary tree data structure is defined as follows: • The empty tree is a binary tree • A node containing an element with left and right subtrees is a binary tree

• Type constructor BTree

data BTree a = Nil | Node (BTree a) a (BTree a)

Suresh PRGH 2019: Lecture 21 October 28, 2019 9 / 20 Binary trees

• A binary tree data structure is defined as follows: • The empty tree is a binary tree • A node containing an element with left and right subtrees is a binary tree

• Type constructor BTree

data BTree a = Nil | Node (BTree a) a (BTree a)

• Two value constructors:

Nil :: BTree a Node :: BTree a -> a -> BTree a -> BTree a

Suresh PRGH 2019: Lecture 21 October 28, 2019 9 / 20 Binary trees

Node (Node Nil 2 Nil) 3 (Node Nil 5 Nil)

3

2 5

Suresh PRGH 2019: Lecture 21 October 28, 2019 10 / 20 Binary trees

Node (Node Nil 4 Nil) 6 (Node (Node Nil 2 Nil) 3 (Node Nil 5 Nil))

6

4 3

2 5

Suresh PRGH 2019: Lecture 21 October 28, 2019 11 / 20 Binary trees

Node (Node Nil 4 Nil) 6 (Node (Node Nil 2 Nil) 3 (Node Nil 5 Nil))

• We omit nodes representing Nil usually

6

4 3

2 5

Suresh PRGH 2019: Lecture 21 October 28, 2019 12 / 20 • Corresponding BTree

Node (Node Nil 1 (Node Nil 2 Nil)) 3 (Node (Node Nil 4 Nil) 5 Nil)

Binary trees

• Yet another binary tree

3

1 5

2 4

Suresh PRGH 2019: Lecture 21 October 28, 2019 13 / 20 Binary trees

• Yet another binary tree

3

1 5

2 4

• Corresponding BTree

Node (Node Nil 1 (Node Nil 2 Nil)) 3 (Node (Node Nil 4 Nil) 5 Nil)

Suresh PRGH 2019: Lecture 21 October 28, 2019 13 / 20 • Height: number of nodes on longest path from root

height :: BTree a -> Int height Nil = 0 height (Node tl x tr) = 1 + max (height tl) (height tr)

Functions on binary trees

• Number of nodes in a tree

size :: BTree a -> Int size Nil = 0 size (Node tl x tr) = 1 + size tl + size tr

Suresh PRGH 2019: Lecture 21 October 28, 2019 14 / 20 Functions on binary trees

• Number of nodes in a tree

size :: BTree a -> Int size Nil = 0 size (Node tl x tr) = 1 + size tl + size tr

• Height: number of nodes on longest path from root

height :: BTree a -> Int height Nil = 0 height (Node tl x tr) = 1 + max (height tl) (height tr)

Suresh PRGH 2019: Lecture 21 October 28, 2019 14 / 20 6 6

4 3 3 4

2 5 5 2

• Haskell code:

reflect :: BTree a -> BTree a reflect Nil = Nil reflect (Node tl x tr) = Node (reflect tr) x (reflect tl)

Functions on binary trees

• Reflect the tree on its “vertical axis”

Suresh PRGH 2019: Lecture 21 October 28, 2019 15 / 20 6 6

4 3 3 4

2 5 5 2 • Haskell code:

reflect :: BTree a -> BTree a reflect Nil = Nil reflect (Node tl x tr) = Node (reflect tr) x (reflect tl)

Functions on binary trees

• Reflect the tree on its “vertical axis”

Suresh PRGH 2019: Lecture 21 October 28, 2019 15 / 20 6

3 4

5 2 • Haskell code:

reflect :: BTree a -> BTree a reflect Nil = Nil reflect (Node tl x tr) = Node (reflect tr) x (reflect tl)

Functions on binary trees

• Reflect the tree on its “vertical axis”

6

4 3

2 5

Suresh PRGH 2019: Lecture 21 October 28, 2019 15 / 20 • Haskell code:

reflect :: BTree a -> BTree a reflect Nil = Nil reflect (Node tl x tr) = Node (reflect tr) x (reflect tl)

Functions on binary trees

• Reflect the tree on its “vertical axis”

6 6

4 3 3 4

2 5 5 2

Suresh PRGH 2019: Lecture 21 October 28, 2019 15 / 20 Functions on binary trees

• Reflect the tree on its “vertical axis”

6 6

4 3 3 4

2 5 5 2 • Haskell code:

reflect :: BTree a -> BTree a reflect Nil = Nil reflect (Node tl x tr) = Node (reflect tr) x (reflect tl)

Suresh PRGH 2019: Lecture 21 October 28, 2019 15 / 20 • Let t be the tree below: 3

1 5

2 4

• levels t = [3,1,5,2,4]

Functions on binary trees

• levels – List nodes level by level and from left to right inside each level

Suresh PRGH 2019: Lecture 21 October 28, 2019 16 / 20 • levels t = [3,1,5,2,4]

Functions on binary trees

• levels – List nodes level by level and from left to right inside each level

• Let t be the tree below: 3

1 5

2 4

Suresh PRGH 2019: Lecture 21 October 28, 2019 16 / 20 Functions on binary trees

• levels – List nodes level by level and from left to right inside each level

• Let t be the tree below: 3

1 5

2 4

• levels t = [3,1,5,2,4]

Suresh PRGH 2019: Lecture 21 October 28, 2019 16 / 20 Functions on binary trees

• levels

levels :: BTree a -> [a] levels = concat . levels' levels' :: BTree a -> [[a]] levels' Nil = [] levels' (Node tl x tr) = [x]:join (levels' tl) (levels' tr) join :: [[a]] -> [[a]] -> [[a]] join [] yss = yss join xss [] = xss join (xs:xss) (ys:yss) = xs++ys: join xss yss

Suresh PRGH 2019: Lecture 21 October 28, 2019 17 / 20 • Split the list in two halves • Recursively create a binary tree from each half • Join them together

• As balanced as possible • Strategy:

Creating a binary tree

• Create a binary tree from a list

Suresh PRGH 2019: Lecture 21 October 28, 2019 18 / 20 • Split the list in two halves • Recursively create a binary tree from each half • Join them together

• Strategy:

Creating a binary tree

• Create a binary tree from a list • As balanced as possible

Suresh PRGH 2019: Lecture 21 October 28, 2019 18 / 20 • Split the list in two halves • Recursively create a binary tree from each half • Join them together

Creating a binary tree

• Create a binary tree from a list • As balanced as possible • Strategy:

Suresh PRGH 2019: Lecture 21 October 28, 2019 18 / 20 • Recursively create a binary tree from each half • Join them together

Creating a binary tree

• Create a binary tree from a list • As balanced as possible • Strategy: • Split the list in two halves

Suresh PRGH 2019: Lecture 21 October 28, 2019 18 / 20 • Join them together

Creating a binary tree

• Create a binary tree from a list • As balanced as possible • Strategy: • Split the list in two halves • Recursively create a binary tree from each half

Suresh PRGH 2019: Lecture 21 October 28, 2019 18 / 20 Creating a binary tree

• Create a binary tree from a list • As balanced as possible • Strategy: • Split the list in two halves • Recursively create a binary tree from each half • Join them together

Suresh PRGH 2019: Lecture 21 October 28, 2019 18 / 20 Creating a binary tree

• Creating a balanced tree from a list

createTree :: [a] -> BTree a createTree [] = Nil createTree xs = Node (createTree front) x (createTree back) where n = length xs (front, x:back) = splitAt (n `div` 2) xs

levels (createTree [0..14]) = [7,3,11,1,5,9,13,0,2,4,6,8,10,12,14] height (createTree [0..14]) = 4

Suresh PRGH 2019: Lecture 21 October 28, 2019 19 / 20 • Not particularly readable! • Addressed in the next class

Showing a binary tree

• To be able to show a binary tree, we need to derive a Show instance

data BTree a = Nil | Node (BTree a) a (BTree a) deriving Show

createTree [0..14] = Node (Node (Node (Node Nil 0 Nil) 1 (Node Nil 2 Nil)) 3 (Node (Node Nil 4 Nil) 5 (Node Nil 6 Nil))) 7 (Node (Node (Node Nil 8 Nil) 9 (Node Nil 10 Nil)) 11 (Node (Node Nil 12 Nil) 13 (Node Nil 14 Nil)))

Suresh PRGH 2019: Lecture 21 October 28, 2019 20 / 20 • Addressed in the next class

Showing a binary tree

• To be able to show a binary tree, we need to derive a Show instance

data BTree a = Nil | Node (BTree a) a (BTree a) deriving Show

createTree [0..14] = Node (Node (Node (Node Nil 0 Nil) 1 (Node Nil 2 Nil)) 3 (Node (Node Nil 4 Nil) 5 (Node Nil 6 Nil))) 7 (Node (Node (Node Nil 8 Nil) 9 (Node Nil 10 Nil)) 11 (Node (Node Nil 12 Nil) 13 (Node Nil 14 Nil)))

• Not particularly readable!

Suresh PRGH 2019: Lecture 21 October 28, 2019 20 / 20 Showing a binary tree

• To be able to show a binary tree, we need to derive a Show instance

data BTree a = Nil | Node (BTree a) a (BTree a) deriving Show

createTree [0..14] = Node (Node (Node (Node Nil 0 Nil) 1 (Node Nil 2 Nil)) 3 (Node (Node Nil 4 Nil) 5 (Node Nil 6 Nil))) 7 (Node (Node (Node Nil 8 Nil) 9 (Node Nil 10 Nil)) 11 (Node (Node Nil 12 Nil) 13 (Node Nil 14 Nil)))

• Not particularly readable! • Addressed in the next class

Suresh PRGH 2019: Lecture 21 October 28, 2019 20 / 20