Com S 541 Lecture -*- Outline -*- * data-driven recursion (Thompson 14, Davie sections 3.2, 4.4) > module DataDriven where > import Prelude hiding (toInteger) key idea: recursion is based on the structure (grammar) of a type. ** data declaration in Haskell data Color = Red | Yellow | Green data [a] = [] | a : [a] ** example: the natural numbers ------------------------------------------ DATA-DRIVEN RECURSION Definition of natural numbers: > data Nat = Zero | Succ Nat deriving Eq To define a function f :: Nat -> t define recursively by: f Zero = ... -- basis f (Succ n) = ... -- inductive case Examples: > toInteger :: Nat -> Integer > plus :: Nat -> Nat -> Nat ------------------------------------------ Explain the data notation (section 4.4, algebraic types) the deriving Eq is not important here develop these using examples: base case: toInteger Zero = 0 inductive case: want toInteger (Succ (Succ (Succ Zero))) = 3 given toInteger (Succ (Succ Zero)) = 2 how do we get 3 from 2? generalizing from this example, toInteger (Succ n) = 1 + (toInteger n) > toInteger Zero = 0 > toInteger (Succ n) = 1 + (toInteger n) base case: plus Zero n = n inductive case: want plus (Succ (Succ Zero)) Zero = (Succ (Succ Zero)) given plus (Succ Zero) Zero = (Succ Zero) how do we get 2 from 1? generalizing from this example, plus (Succ m) n = plus m (Succ n) > plus Zero n = n > plus (Succ m) n = plus m (Succ n) Q: How does the structure of the program resemble the data declaration? note the recursion occurs where the grammar is recursive. Q: How does the data declaration resemble a grammar? Pitfalls: need to parenthesize the patterns ------------------------------------------ FOR YOU TO DO -- data Nat = Zero | Succ Nat deriving Eq mult :: Nat -> Nat -> Nat equal :: Nat -> Nat -> Bool ------------------------------------------ Q: What would isZero :: Nat -> Bool be like? ** structure of data determines structure of code ------------------------------------------ GENERALIZING HOW TO WRITE RECUSIONS data NonEmptyList a = Write maxl :: (Ord a) => NonEmptyList a -> a such that Write nth :: NonEmptyList a -> Nat -> a such that ------------------------------------------ Q: How would you define a non-empty list in English? a non-empty list is either [x], or y:lst, where lst is a non-empty list in Haskell data NonEmptyList a = Sing a | a :# (NonEmptyList a) pitfall: can't use : as a constructor, as already used for lists (kind of irregular that can't overload that...) nth (Sing 1) Zero = 1 nth (0 :# (1 :# (2 :# (Sing 3)))) (Succ (Succ Zero)) = 2 pitfall: example has to be parenthesized, as :# isn't declared infixr, pitfall: also constructors need to be parenthesized Sing(1) isn't the same as (Sing 1), and doesn't work. Q: can you write this? ------------------------------------------ RECURSION OVER GRAMMARS > data Exp = BoolLit Bool | IntLit Integer > | Sub Exp Exp > | Equal Exp Exp > | If Exp Exp Exp Write the following eval :: Exp -> Exp such that eval (Sub (IntLit 5) (IntLit 4)) = (IntLit 1) ------------------------------------------ Q: What are the base cases? Q: Where should there be a recursion? Q: Examples for each recursive case? Moral: in general can think of all recursions as recursions over grammars