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 data 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 data 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
• 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 (Cons 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 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
Binary trees
• A binary tree data structure 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