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 digits :: String -> 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. 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