------------------------------------------------------------------------- -- Haskell: The Craft of Functional Programming -- Simon Thompson -- (c) Addison-Wesley, 1999. -- -- Chapter 5 ------------------------------------------------------------------------- module Chapter5 where import Prelude hiding (id) -- Data types: tuples and lists -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- Introducing tuples, lists and strings -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type ShopItem = (String,Int) type Basket = [ShopItem] basket1 :: Basket basket1 = [ ("Salt: 1kg",139) , ("Plain crisps",25) , ("Gin: 1lt",1099) ] basket2 :: Basket basket2 = [] basket3 :: Basket basket3 = [ ("Salt: 1kg",139) , ("Plain crisps",25) , ("Plain crisps",25) ] -- Tuple types -- ^^^^^^^^^^^ -- Minimum and maximum of two integers. minAndMax :: Int -> Int -> (Int,Int) minAndMax x y | x>=y = (y,x) | otherwise = (x,y) -- Adding a pair of intgers. addPair :: (Int,Int) -> Int addPair (x,y) = x+y -- Shifting around the structure of an ((Int,Int),Int). shift :: ((Int,Int),Int) -> (Int,(Int,Int)) shift ((x,y),z) = (x,(y,z)) -- Selecting parts of a tuple name :: ShopItem -> String price :: ShopItem -> Int name (n,p) = n price (n,p) = p -- Adding a pair using the built-in selectors, fst and snd. addPair' :: (Int,Int) -> Int addPair' p = fst p + snd p -- Fibonacci numbers: an efficient function, fastFib. fibStep :: (Int,Int) -> (Int,Int) fibStep (u,v) = (v,u+v) fibPair :: Int -> (Int,Int) fibPair n | n==0 = (0,1) | otherwise = fibStep (fibPair (n-1)) fastFib :: Int -> Int fastFib = fst . fibPair fibTwoStep :: Int -> Int -> (Int,Int) fibTwoStep x y = (y,x+y) -- Lists in Haskell -- ^^^^^^^^^^^^^^^^ -- Various examples of lists list1 :: [Int] list1 = [1,2,3,4,1,4] list2 :: [Bool] list2 = [True] list3 :: String list3 = ['a','a','b'] list4 :: String list4 = "aab" list5 :: [ Int -> Int ] list5 = [fastFib,fastFib] list6 :: [ [Int] ] list6 = [[12,2],[2,12],[]] list7 :: [Int] list7 = [2 .. 7] list8 :: [Float] list8 = [3.1 .. 7.0] list9 :: String list9 = ['a' .. 'm'] list10 :: [Int] list10 = [7,6 .. 3] list11 :: [Float] list11 = [0.0,0.3 .. 1.0] list12 :: String list12 = ['a','c' .. 'n'] -- List comprehensions -- ^^^^^^^^^^^^^^^^^^^ -- Examples of list comprehensions ex :: [Int] ex = [2,4,7] comp1 :: [Int] comp1 = [ 2*n | n<-ex] comp2 :: [Bool] comp2 = [ isEven n | n<-ex ] isEven :: Int -> Bool isEven n = (n `mod` 2 == 0) comp3 :: [Int] comp3 = [ 2*n | n <- ex , isEven n , n>3 ] -- Add all the pairs in a list of pairs. addPairs :: [(Int,Int)] -> [Int] addPairs pairList = [ m+n | (m,n) <- pairList ] -- Return only the sums of pairs which are increasing. addOrdPairs :: [(Int,Int)] -> [Int] addOrdPairs pairList = [ m+n | (m,n) <- pairList , m String digits st = [ ch | ch<-st , isDigit ch ] -- Are all the integers in a list even? or odd? allEven, allOdd :: [Int] -> Bool allEven xs = (xs == [x | x<-xs, isEven x]) allOdd xs = ([] == [x | x<-xs, isEven x]) -- A library database -- ^^^^^^^^^^^^^^^^^^ -- Types type Person = String type Book = String type Database = [ (Person , Book) ] -- An example database. exampleBase :: Database exampleBase = [ ("Alice" , "Tintin") , ("Anna" , "Little Women") , ("Alice" , "Asterix") , ("Rory" , "Tintin") ] -- The books borrowed by a particular person in the given database. books :: Database -> Person -> [Book] books dBase findPerson = [ book | (person,book) <- dBase , person==findPerson ] -- Making a loan is done by adding a pair to the database. makeLoan :: Database -> Person -> Book -> Database makeLoan dBase pers bk = [ (pers,bk) ] ++ dBase -- To return a loan. returnLoan :: Database -> Person -> Book -> Database returnLoan dBase pers bk = [ pair | pair <- dBase , pair /= (pers,bk) ] -- Testing the database. -- Commented out because borrowed is not defined here. -- test1 :: Bool -- test1 = borrowed exampleBase "Asterix" test2 :: Database test2 = makeLoan exampleBase "Alice" "Rotten Romans" -- Generic functions: polymorphism -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- The polymorphic identity function. id :: a -> a id x = x -- A mystery function. mystery :: (Bool,a) -> Char mystery (x,y) = if x then 'c' else 'd' -- The String type -- ^^^^^^^^^^^^^^^ -- Example strings str1, str2, str3, str4, str5 :: String str1 = "baboon" str2 = "" str3 = "\99a\116" str4 = "gorilla\nhippo\nibex" str5 = "1\t23\t456" pstr1, pstr2, pstr3, pstr4, pstr5 :: IO () pstr1 = putStr str1 pstr2 = putStr str2 pstr3 = putStr str3 pstr4 = putStr str4 pstr5 = putStr str5