Chapter 15 Functional Programming
Total Page:16
File Type:pdf, Size:1020Kb
Topics Chapter 15 Numbers n Natural numbers n Haskell numbers Functional Programming Lists n List notation n Lists as a data type n List operations Chapter 15: Functional Programming 2 Numbers Natural Numbers The natural numbers are the numbers 0, 1, Haskell provides a sophisticated 2, and so on, used for counting. hierarchy of type classes for describing various kinds of numbers. Introduced by the declaration data Nat = Zero | Succ Nat Although (some) numbers are provided n The constructor Succ (short for ‘successor’) as primitives data types, it is has type Nat à Nat. theoretically possible to introduce them n Example: as an element of Nat the number 7 through suitable data type declarations. would be represented by Succ(Succ(Succ(Succ(Succ(Succ(Succ Zero)))))) Chapter 15: Functional Programming 3 Chapter 15: Functional Programming 4 Natural Numbers Natural Numbers Every natural number is represented by a Multiplication ca be defined by unique value of Nat. (x) :: Nat à Nat à Nat m x Zero = Zero On the other hand, not every value of Nat m x Succ n = (m x n) + m represents a well-defined natural number. n Example: ^, Succ ^, Succ(Succ ^) Nat can be a member of the type class Eq Addition ca be defined by instance Eq Nat where Zero == Zero = True (+) :: Nat à Nat à Nat Zero == Succ n = False m + Zero = m Succ m == Zero = False m + Succ n = Succ(m + n) Succ m == Succ n = (m == n) Chapter 15: Functional Programming 5 Chapter 15: Functional Programming 6 1 Natural Numbers Haskell Numbers Nat can be a member of the type class Ord instance Ord Nat where Haskell provide, as primitives, the following Zero < Zero = False types: Zero < Succ n = True n Int single-precision integers Succ m < Zero = False n Integer arbitrary-precision integers Succ m < Succ n = (m < n) n Float singe-precision floating-point Elements of Nat can be printed by numbers showNat :: Nat à String n Double double-precision gloating-point showNatZero = “Zero” numbers showNat (Succ Zero) = “Succ Zero” n Rational rational number showNat (Succ(Succ n)) = “Succ (“ ++ showNat (Succ n) ++ “)7 ” Chapter 15: Functional Programming 8 The Numeric Type Classes Integral Types The same symbols, +, x, and so on, are The members of the Integral type are two used for arithmetic on each numeric type. primitive types Int and Integer. n Overloaded functions. The operators div and mod are provided All Haskell number types are instances of as primitive. the type class Num defined by class (Eq a, Show a) Þ Num a where n If x and y are integers, and y is not zero, then ë û (+), (-), (x) :: a à a à a x div y = x / y . negate :: a à a ë13.8û = 13, ë-13.8û = -14 fromInteger :: Integer à a n The value x mod y is defined by the equation … x = (x div y) * y + (x mod y) x – y = x + negate y Chapter 15: Functional Programming 9 Chapter 15: Functional Programming 10 Lists List Notation Lists can be used to fetch and carry data A finite list is denoted using square brackets and from one function to another. commas. n [1,2,3] Lists can be taken apart, rearranged, and n [“hello”,”goodbye”] combined with other lists. All the elements of a list must have the same Lists can be summed and multiplied. type. Lists of characters can be read and The empty list is written as []. printed. A singleton list contains only one element n [x] … n [[]] the empty list is its only member Chapter 15: Functional Programming 11 Chapter 15: Functional Programming 12 2 List Notation Lists as a data type If the elements of a list all have type a, A list can be constructed fro scratch by then the list itself will be assigned the type starting with an empty list and [a]. successively adding elements one by one. n [1,2,3] :: [Int] n Elements can be added to the front of the list, n [‘h’,’e’,’l’,’l’,’o’] :: [Char] or the rear, or to somewhere in the middle. n [[1,2],[3]] :: [[Int]] n [(+),(x)] :: [Int à Int à Int] Data type declaration (list): A list may contain the same value more data List a = Nil | Cons a (List a) than once. n The constructor Cons (short for ‘construct’) Two lists are equal if and only if they add an element to the front of the list. contain the same value in the same order. [1,2,3] Cons 1 (Cons 2 (Cons 3 Nil)) Chapter 15: Functional Programming 13 Chapter 15: Functional Programming 14 Lists as a data type Lists as a data type In functional programming, lists are Like functions over data types, functions defined as elements of List a. over lists can be defined by pattern n The syntax [a] is used instead of List a. matching. n The constructor Nil is written as [] n The constructor Cons is written as an infix instance (Eq a) Þ Eq [a] where operator (:) [] == [] = True (:) associates to the right [] == (y:ys) = False [1,2,3] = 1:(2:(3:[])) = 1:2:3:[] (x:xs) == [] = False (x:xs) == (y:ys)= (x == y) Ù (xs == ys) Chapter 15: Functional Programming 15 Chapter 15: Functional Programming 16 List Operations Concatenation Some of the most commonly used Two lists, both of the same type, can be functions and operations on lists. concatenated to form one longer list. This function is denoted by the binary For each function: give the definition, operator ++. illustrate its use, and state some of its ? [1,2,3] ++ [4,5] [1,2,3,4,5] properties. ? [1,2] ++ [] ++ [1] [1,2,1] Chapter 15: Functional Programming 17 Chapter 15: Functional Programming 18 3 Concatenation Concatenation The formal definition of ++ is n It is not the case that xs ++ ^ = ^ (++) :: [a] à [a] à [a] ? [1,2,3] ++ undefined [] ++ ys = ys [1,2,3{Interrupted!} (x:xs) ++ ys = x:(xs++ys) n The list [1,2,3] ++ ^ is a partial list; in full n The definition of ++ is by pattern matching form it is the list 1:2:3:^. on the left-hand argument. The evaluator can compute the first three n The two patterns are disjoint and cover all elements, but thereafter it goes into a nonterminating computation, so we interrupt it. cases, apart from the undefined list ^. Some properties: n It follows by case exhaustion that (xs ++ ys) ++ zs = xs ++ (ys ++ zs) ^ ++ ys = ^ xs ++ [] = [] ++ xs = xs Chapter 15: Functional Programming 19 Chapter 15: Functional Programming 20 Reverse Length This function reverses the order of The length of a list is the number of elements in a finite list. elements it contains. ? reverse [1,2,3,4,5] The definition is [5,4,3,2,1] length :: [a] à Int The definition is length [] = 0 reverse :: [a] à [a] length (x:xs) = 1 + length(xs) reverse [] =[] The nature of the list elements is reverse (x:xs) = reverse xs ++ [x] irrelevant when computing the length: In words, to reverse a list (x:xs) one reverses xs and then adds x to the end. ? length [undefined,undefined] 2 Chapter 15: Functional Programming 21 Chapter 15: Functional Programming 22 Length Head and Tail Not every list has a well-defined length. n The partial lists have an undefined length The function head selects the first ^, x:^, x:y:^ element of a nonempty list, and tail n Only finite lists have well-defined lengths. selects the rest: The list [^,^] is a finite list, not a partial list head :: [a] à a because it is the list ^:^:[], which ends in [] head [] = error “empty list” not ^. The computer cannot produce the head (x:xs) = x elements, but it can produce the length of the list. tail :: [a] à [a] The function length satisfies a distribution tail [] = error “empty list” property: tail (x:xs) = xs length(xs ++ ys) = length xs + length ys n These are constant-time operations, since they deliver their result in one reduction step. Chapter 15: Functional Programming 23 Chapter 15: Functional Programming 24 4 Init and last Init and last The function last and init select the last First attempt (definition): element of a nonempty list and what last :: [a] à a remains after the last element has been last = head × reverse removed. init :: [a] à a ? last [1,2,3,4,5] init = reverse × tail × reverse 5 ? init [1,2,3,4,5] [1,2,3,4] Problem? n init xs = ^ for all partial and infinite lists xs Chapter 15: Functional Programming 25 Chapter 15: Functional Programming 26 Init and last Init and last Second attempt (definition): Third attempt (definition): last (x:xs) = if null xs then x else last xs n Since [x] is an abbreviation for x:[] last [x] = x init (x:xs) = if null xs then [] else x:init xs last (x:xs) = last xs init [x] = [] With this definition init (x:xs) = x:init xs Problem? n init xs = xs for all partial and infinite lists xs n There is a serious danger of confusion because the patterns [x] and (x:xs) are not disjoint. The second includes the first as a special case. Chapter 15: Functional Programming 27 Chapter 15: Functional Programming 28 Init and last Init and last Definition n If the order of the equations are reversed: last :: [a] à a last’ (x:xs) = last’ xs last [] = error “empty list” last’ [x] = x last [x] = x n The definition of last’ would simply be last (x:y:ys) = last(y:ys) incorrect. last’ xs = ^ init :: [a] à [a] n It is not a good practice to write definition that init [] = error “empty list” depend critically on the order of the init [x] = [] equations.