Redline's Autodidact Repo
changeset 49:5b8bc8cbfa98
Updated previous RWH solutions and posted all but the last 3 solutions from Chapter 3.
line diff
1.1 --- a/books/rwh/chapter01/WC.hs Mon Mar 09 14:49:35 2009 -0400 1.2 +++ b/books/rwh/chapter01/WC.hs Mon Mar 16 13:03:29 2009 -0400 1.3 @@ -2,4 +2,4 @@ 1.4 -- lines beginning with "--" are comments 1.5 1.6 main = interact wordCount 1.7 - where wordCount input = show (length (lines input)) ++ "\n" 1.8 \ No newline at end of file 1.9 + where wordCount input = show (length (lines input)) ++ "\n"
2.1 --- a/books/rwh/chapter01/exercise03.hs Mon Mar 09 14:49:35 2009 -0400 2.2 +++ b/books/rwh/chapter01/exercise03.hs Mon Mar 16 13:03:29 2009 -0400 2.3 @@ -1,4 +1,4 @@ 2.4 -- file: chapter01/exercise03.hs 2.5 2.6 main = interact wordCount 2.7 - where wordCount input = show (length (words input)) ++ "\n" 2.8 \ No newline at end of file 2.9 + where wordCount input = show (length (words input)) ++ "\n"
3.1 --- a/books/rwh/chapter01/exercise04.hs Mon Mar 09 14:49:35 2009 -0400 3.2 +++ b/books/rwh/chapter01/exercise04.hs Mon Mar 16 13:03:29 2009 -0400 3.3 @@ -1,4 +1,4 @@ 3.4 -- file: chapter01/exercise04.hs 3.5 3.6 main = interact wordCount 3.7 - where wordCount input = show (length input) ++ "\n" 3.8 \ No newline at end of file 3.9 + where wordCount input = show (length input) ++ "\n"
4.1 --- a/books/rwh/chapter02/add.hs Mon Mar 09 14:49:35 2009 -0400 4.2 +++ b/books/rwh/chapter02/add.hs Mon Mar 16 13:03:29 2009 -0400 4.3 @@ -1,4 +1,3 @@ 4.4 -- file: chapter02/add.hs 4.5 --- authors mistakenly titled as ch03/add.hs 4.6 4.7 add a b = a + b 4.8 \ No newline at end of file
5.1 --- a/books/rwh/chapter02/exercise02.hs Mon Mar 09 14:49:35 2009 -0400 5.2 +++ b/books/rwh/chapter02/exercise02.hs Mon Mar 16 13:03:29 2009 -0400 5.3 @@ -1,5 +1,5 @@ 5.4 -- file: chapter02/exercise02.hs 5.5 --- section: The Type of a Function of More Than One Argument (1) 5.6 +-- section: The Type of a Function of More Than One Argument 5.7 5.8 -- The last function could return the first or last elements of a list or a random element. 5.9 -- It cannot return a list and it cannot take more than one argument. 5.10 \ No newline at end of file
6.1 --- a/books/rwh/chapter02/exercise03.hs Mon Mar 09 14:49:35 2009 -0400 6.2 +++ b/books/rwh/chapter02/exercise03.hs Mon Mar 16 13:03:29 2009 -0400 6.3 @@ -1,8 +1,6 @@ 6.4 -- file: chapter02/exercise03.hs 6.5 -- section: The Type of a Function of More Than One Argument 6.6 6.7 -lastButOne xs = if (length xs == 2) 6.8 - then head xs 6.9 --- else if (length xs < 2) 6.10 --- then print "Your list is too short. It must have 2 or more elements." 6.11 - else lastButOne (drop 1 xs) 6.12 \ No newline at end of file 6.13 +lastButOne xs = if length xs == 2 6.14 + then head xs 6.15 + else lastButOne (tail xs) -- or (drop 1 xs)
7.1 --- a/books/rwh/chapter02/myDrop.hs Mon Mar 09 14:49:35 2009 -0400 7.2 +++ b/books/rwh/chapter02/myDrop.hs Mon Mar 16 13:03:29 2009 -0400 7.3 @@ -3,5 +3,21 @@ 7.4 7.5 myDrop :: Int -> [a] -> [a] 7.6 myDrop n xs = if n <= 0 || null xs 7.7 - then xs 7.8 - else myDrop (n - 1) (tail xs) 7.9 \ No newline at end of file 7.10 + then xs 7.11 + else myDrop (n - 1) (tail xs) 7.12 + 7.13 +myDrop2 :: Int -> [a] -> [a] 7.14 +myDrop2 n xs -- I think I like this best. 7.15 + | n <= 0 = xs 7.16 + | null xs = xs 7.17 + | otherwise = myDrop2 (n - 1) (tail xs) 7.18 + 7.19 +myDrop3 :: Int -> [a] -> [a] 7.20 +myDrop3 n xs 7.21 + | n <= 0 || null xs = xs 7.22 + | otherwise = myDrop3 (n - 1) (tail xs) 7.23 + 7.24 +niceDrop :: Int -> [a] -> [a] 7.25 +niceDrop n xs | n <= 0 = xs 7.26 +niceDrop _ [] = [] 7.27 +niceDrop n (_:xs) = niceDrop (n - 1) xs 7.28 \ No newline at end of file
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/books/rwh/chapter03/AlgebraicVector.hs Mon Mar 16 13:03:29 2009 -0400 8.3 @@ -0,0 +1,12 @@ 8.4 +-- file: chapter03/AlgebraicVector.hs 8.5 +-- x and y coordinates or lengths. 8.6 +data Cartesian2D = Cartesian2D Double Double 8.7 + deriving (Eq, Show) 8.8 + 8.9 +-- Angle and distance (magnitude). 8.10 +data Polar2D = Polar2D Double Double 8.11 + deriving (Eq, Show) 8.12 + 8.13 +-- Polar Coordinates and Cartesian Coordinates are different. 8.14 +-- The lesson? Use tuples in small, local situations. 8.15 +-- Otherwise stick to Type or Data declarations. 8.16 \ No newline at end of file
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/books/rwh/chapter03/BadIndent.hs Mon Mar 16 13:03:29 2009 -0400 9.3 @@ -0,0 +1,8 @@ 9.4 +-- file: chapter03/BadIndent.hs 9.5 +-- This is the leftmost column. 9.6 + 9.7 + -- Our first declaration is in column 4. 9.8 + firstBadIndentation = 1 9.9 + 9.10 + -- Our second is left of the first, which is illegal! 9.11 + secondBadIndentation = 2 9.12 \ No newline at end of file
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/books/rwh/chapter03/BadPattern.hs Mon Mar 16 13:03:29 2009 -0400 10.3 @@ -0,0 +1,6 @@ 10.4 +-- file: chapter03/BadPattern.hs 10.5 + 10.6 +badExample (x:xs) = x + badExample xs 10.7 + 10.8 +goodExample (x:xs) = x + goodExample xs 10.9 +goodExample _ = 0 -- Wildcards are nice sometimes. 10.10 \ No newline at end of file
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 11.2 +++ b/books/rwh/chapter03/BadTree.hs Mon Mar 16 13:03:29 2009 -0400 11.3 @@ -0,0 +1,8 @@ 11.4 +-- file: chapter03/BadTree.hs 11.5 + 11.6 +bad_nodesAreSame (Node a _ _) (Node a _ _) = Just a 11.7 +bad_nodesAreSame _ _ = Nothing 11.8 + 11.9 +nodesAreSame (Node a _ _) (Node b _ _) 11.10 + | a == b = Just a 11.11 +nodesAreSame _ _ = Nothing 11.12 \ No newline at end of file
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 12.2 +++ b/books/rwh/chapter03/BogusPattern.hs Mon Mar 16 13:03:29 2009 -0400 12.3 @@ -0,0 +1,25 @@ 12.4 +-- file: ch03/BogusPattern.hs 12.5 + 12.6 +data Fruit = Apple | Orange 12.7 + deriving (Show) 12.8 + 12.9 +apple = "apple" 12.10 + 12.11 +orange = "orange" 12.12 + 12.13 +-- This next section of code is jacked up. 12.14 + 12.15 +whichFruit :: String -> Fruit 12.16 +whichFruit f = case f of 12.17 + apple -> Apple 12.18 + orange -> Orange 12.19 + 12.20 +equational apple = Apple 12.21 +equational orange = Orange 12.22 + 12.23 +-- We refer to a pattern that always succeeds as irrefutable. 12.24 +-- Plain variable names and the wild card _ are examples of irrefutable patterns. 12.25 + 12.26 +betterFruit f = case f of 12.27 + "apple" -> Apple 12.28 + "orange" -> Orange 12.29 \ No newline at end of file
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 13.2 +++ b/books/rwh/chapter03/BookStore.hs Mon Mar 16 13:03:29 2009 -0400 13.3 @@ -0,0 +1,84 @@ 13.4 +-- file: chapter03/BookStore.hs 13.5 + 13.6 +type CustomerID = Int 13.7 +type ReviewBody = String 13.8 +type BookRecord = (BookInfo, BookReview) 13.9 + 13.10 +type CardHolder = String 13.11 +type CardNumber = String 13.12 +type Address = [String] 13.13 + 13.14 +type BookID = Int -- Having all these type synonyms seems like boilerplate. 13.15 +type BookTitle = String -- What can I do about it? 13.16 +type BookAuthors = [String] 13.17 + 13.18 +data BookInfo = Book Int String [String] 13.19 + deriving (Show) 13.20 + 13.21 +data MagazineInfo = Magazine Int String [String] 13.22 + deriving (Show) 13.23 + 13.24 +data BookReview = BookReview BookInfo CustomerID String 13.25 + 13.26 +data BetterReview = BetterReview BookInfo CustomerID ReviewBody 13.27 + 13.28 +data BillingInfo = CreditCard CardNumber CardHolder Address -- This is an example of an Algebraic Data Type... 13.29 + | CashOnDelivery -- ...not to be confused with an Abstract Data Type... 13.30 + | Invoice CustomerID -- ...it has several type constructor options within it. 13.31 + deriving (Show) -- All data declarations are in fact Algebraic Data Types. 13.32 + 13.33 +bookID (Book id title authors) = id -- Pattern matching will magically pull out the values we stored earlier. 13.34 +bookTitle (Book id title authors) = title -- Yay, pattern matching! Note that Haskell type fields are... 13.35 +bookAuthors (Book id title authors) = authors -- ...positional. We refer to them by location, not name. 13.36 + 13.37 +nicerID (Book id _ _) = id -- These are equivalent pattern matching accessors to those above. 13.38 +nicerTitle (Book _ title _) = title -- The _ character serves as a wildcard in the matching process. 13.39 +nicerAuthors (Book _ _ authors) = authors -- A little bit more concise but still repetitive. 13.40 + 13.41 +-- IMPORTANT! When writing a series of patterns, match one against each type constructor. Or else. 13.42 + 13.43 +data Customer = Customer { -- Since those earlier accessors were boilerplate, we can use this nice... 13.44 + customerID :: CustomerID -- ..."record syntax" to handle the problem and automatically... 13.45 + , customerName :: String -- ...accessor functions. Ya know, "for free". 13.46 + , customerAddress :: Address 13.47 +} deriving (Show) 13.48 + 13.49 +customer1 = Customer 271828 "J.R. Hacker" 13.50 + ["255 Syntax Ct", 13.51 + "Milpitas, CA 95134", 13.52 + "USA"] 13.53 + 13.54 +customer2 = Customer { -- Record syntax can also be used in construction, if you think it's clearer. 13.55 + customerID = 271829 -- Customers shouldn't share IDs. See customer1. 13.56 + , customerAddress = ["1048576 Disk Drive", 13.57 + "Milpitas, CA 95134", 13.58 + "USA"] 13.59 + , customerName = "Jane Q. Citizen" 13.60 + } 13.61 + 13.62 +book0 = Book 9780135072455 "Algebra of Programming" 13.63 + ["Richard Bird", "Oege de Moor"] 13.64 +book1 = Book 0 "The Book of Imaginary Beings" 13.65 + ["Jorge Luis Borges"] 13.66 +book2 = Book 1 "Cosmicomics" 13.67 + ["Italo Calvino"] 13.68 +book3 = Book 173 "Use of Weapons" 13.69 + ["Iain M. Banks"] 13.70 +book4 = Book 2 "The Wealth of Networks" 13.71 + ["Yochai Benkler"] 13.72 +book5 = Book 6561 "Real World Haskell" 13.73 + ["John Goerzen", "Bryan O'Sullivan", "Don Stewart"] 13.74 +book6 = Book 3 "Probability Theory" 13.75 + ["E.T.H. Jaynes"] 13.76 +bookList = [book0,book1,book2,book3,book4,book5,book6] 13.77 + 13.78 +-- Identical Types :: ([Char],[Char]) 13.79 +a = ("Porpoise", "Grey") 13.80 +b = ("Table", "Oak") 13.81 + 13.82 +-- Different Types 13.83 +data Cetacean = Cetacean String String 13.84 +data Furniture = Furniture String String 13.85 + 13.86 +c = Cetacean "Porpoise" "Grey" 13.87 +d = Furniture "Table" "Oak" 13.88 \ No newline at end of file
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 14.2 +++ b/books/rwh/chapter03/Braces.hs Mon Mar 16 13:03:29 2009 -0400 14.3 @@ -0,0 +1,10 @@ 14.4 +-- file: chapter03/Braces.hs 14.5 + 14.6 +bar = let a = 1 14.7 + b = 2 14.8 + c = 3 14.9 + in a + b + c 14.10 + 14.11 +foo = let { a = 1; b = 2; 14.12 + c = 3 } 14.13 + in a + b + c 14.14 \ No newline at end of file
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 15.2 +++ b/books/rwh/chapter03/GlobalVariable.hs Mon Mar 16 13:03:29 2009 -0400 15.3 @@ -0,0 +1,3 @@ 15.4 +-- file: chapter03/GlobalVariable.hs 15.5 + 15.6 +itemName = "Weighted Companion Cube"
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 16.2 +++ b/books/rwh/chapter03/GoodIndent.hs Mon Mar 16 13:03:29 2009 -0400 16.3 @@ -0,0 +1,8 @@ 16.4 +-- file: chapter03/GoodIndent.hs 16.5 +-- This is the leftmost column. 16.6 + 16.7 + -- It's fine for top-level declarations to start in any column. 16.8 + firstGoodIndentation = 1 16.9 + 16.10 + -- ...provided all subsequent declarations do, too! 16.11 + secondGoodIndentation = 2 16.12 \ No newline at end of file
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 17.2 +++ b/books/rwh/chapter03/Guards.hs Mon Mar 16 13:03:29 2009 -0400 17.3 @@ -0,0 +1,6 @@ 17.4 +-- file: chapter03/Guards.hs 17.5 + 17.6 +fromMaybe defval wrapper = 17.7 + case wrapped of 17.8 + Nothing -> defval 17.9 + Just value -> value 17.10 \ No newline at end of file
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 18.2 +++ b/books/rwh/chapter03/Indentation.hs Mon Mar 16 13:03:29 2009 -0400 18.3 @@ -0,0 +1,10 @@ 18.4 +-- file: chapter03/Indentation.hs 18.5 + 18.6 +foo = let firstDefinition = blah blah 18.7 + -- a comment-only line is treated as empty 18.8 + continuation blah 18.9 + 18.10 + -- we reduce the indentation, so this is a new definition 18.11 + secondDefinition = yada yada 18.12 + continuation yada 18.13 + in whatever 18.14 \ No newline at end of file
19.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 19.2 +++ b/books/rwh/chapter03/Lending.hs Mon Mar 16 13:03:29 2009 -0400 19.3 @@ -0,0 +1,20 @@ 19.4 +-- file: chapter03/Lending.hs 19.5 + 19.6 +lend amount balance = let reserve = 100 19.7 + newBalance = balance - amount 19.8 + in if balance < reserve 19.9 + then Nothing 19.10 + else Just newBalance 19.11 + 19.12 +lend2 amount balance = if amount < reserve * 0.5 19.13 + then Just newBalance 19.14 + else Nothing 19.15 + where reserve = 100 19.16 + newBalance = balance - amount 19.17 + 19.18 +lend3 amount balance 19.19 + | amount <= 0 = Nothing 19.20 + | amount > reserve * 0.5 = Nothing 19.21 + | otherwise = Just newBalance 19.22 + where reserve = 100 19.23 + newBalance = balance - amount 19.24 \ No newline at end of file
20.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 20.2 +++ b/books/rwh/chapter03/ListADT.hs Mon Mar 16 13:03:29 2009 -0400 20.3 @@ -0,0 +1,27 @@ 20.4 +-- file: chapter03/ListADT.hs 20.5 + 20.6 +data List a = Cons a (List a) 20.7 + | Nil 20.8 + deriving (Show) 20.9 + 20.10 +data Tree a = Node a (Tree a) (Tree a) 20.11 + | Empty 20.12 + deriving (Show) 20.13 + 20.14 +-- Here are two simple recursive data types. 20.15 +-- Lists and binary trees. For example... 20.16 +-- a Tree is either a node with two children... 20.17 +-- or an empty value. 20.18 + 20.19 +-- Want to see a neat proof of type equivalence... 20.20 +-- between [a] and List a? Of course you do. 20.21 + 20.22 +fromList (x:xs) = Cons x (fromList xs) 20.23 + [] = Nil 20.24 + 20.25 +-- List a and [a] are an example of isomorphic types, types with the same shape. 20.26 + 20.27 +simpleTree = Node "parent" (Node "left child" Empty Empty) 20.28 + (Node "right child" Empty Empty) 20.29 + 20.30 +-- Java's null value doesn't exist in Haskell so we use the Empty constructor instead. 20.31 \ No newline at end of file
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 21.2 +++ b/books/rwh/chapter03/LocalFunction.hs Mon Mar 16 13:03:29 2009 -0400 21.3 @@ -0,0 +1,7 @@ 21.4 +-- file: chapter03/LocalFunction.hs 21.5 + 21.6 +pluralise :: String -> [Int] -> [String] 21.7 +pluralise word counts = map plural counts 21.8 + where plural 0 = "no " ++ word ++ "s" 21.9 + plural 1 = "one " ++ word ++ "s" 21.10 + plural n = show n ++ " " ++ word "s" 21.11 \ No newline at end of file
22.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 22.2 +++ b/books/rwh/chapter03/MySecond.hs Mon Mar 16 13:03:29 2009 -0400 22.3 @@ -0,0 +1,17 @@ 22.4 +-- file: chapter03/MySecond.hs 22.5 + 22.6 +mySecond :: [a] -> a 22.7 +mySecond xs = if null (tail xs) -- Error reporting is nice to have but... 22.8 + then error "list too short" -- it doesn't let us choose whether to... 22.9 + else head (tail xs) -- crash or try to recover. 22.10 + 22.11 +safeSecond :: [a] -> Maybe a 22.12 +safeSecond [] = Nothing 22.13 +safeSecond xs - if null (tail xs) -- Maybe gives us that opportunity. 22.14 + then Nothing -- Nothing happens if null (tail xs). 22.15 + else Just (head (tail xs)) -- And if else then Just (head (tail xs)). 22.16 + 22.17 +-- This cleans up safeSecond with pattern matching. It's certainly more concise. 22.18 +tidySecond :: [a] -> Maybe a 22.19 +tidySecond (_:x:_) = Just x 22.20 +tidySecond _ = Nothing
23.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 23.2 +++ b/books/rwh/chapter03/NestedLets.hs Mon Mar 16 13:03:29 2009 -0400 23.3 @@ -0,0 +1,11 @@ 23.4 +-- file: chapter03/NestedLets.hs 23.5 + 23.6 +foo = let a = 1 23.7 + in let b = 2 23.8 + in a + b 23.9 + 23.10 +bar = let x = 1 23.11 + in ((let x = "foo" in x), x) 23.12 + 23.13 +quux a = let a = "foo" 23.14 + in a ++ "eek"
24.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 24.2 +++ b/books/rwh/chapter03/Nullable.hs Mon Mar 16 13:03:29 2009 -0400 24.3 @@ -0,0 +1,15 @@ 24.4 +-- file: chapter03/Nullable.hs 24.5 + 24.6 +data Maybe a = Just a 24.7 + | Nothing 24.8 + 24.9 +someBool = Just True 24.10 + 24.11 +someString = Just "something" 24.12 + 24.13 +wrapped = Just (Just "wrapped") 24.14 + 24.15 +-- The Maybe type exists to allow things to fail. 24.16 +-- There's a decent wikibook article on it here: 24.17 +-- http://en.wikibooks.org/wiki/Haskell/Hierarchical_libraries/Maybe 24.18 +-- I hope the book will cover Maybe, Just and Nothing in further detail later. 24.19 \ No newline at end of file
25.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 25.2 +++ b/books/rwh/chapter03/Roygbiv.hs Mon Mar 16 13:03:29 2009 -0400 25.3 @@ -0,0 +1,34 @@ 25.4 +-- file: chapter03/Roygbiv.hs 25.5 +-- This is an example of "enumeration types" familiar as C's Enums in Haskell. 25.6 + 25.7 +-- NOTE: Haskell enumeration types cannot be used like Integers as in C enums. 25.8 +-- Don't be against this. The Type system is saving you from yourself. 25.9 + 25.10 +data Roygbiv = Red 25.11 + | Orange 25.12 + | Yellow 25.13 + | Green 25.14 + | Blue 25.15 + | Indigo 25.16 + | Violet 25.17 + deriving (Eq, Show) 25.18 + 25.19 +-- Which is equivalent to 25.20 +-- enum roygbiv { 25.21 +-- red, 25.22 +-- orange, 25.23 +-- yellow, 25.24 +-- green, 25.25 +-- blue, 25.26 +-- indigo, 25.27 +-- violet 25.28 +-- }; 25.29 +-- such as 25.30 +data BookInfo = Book Int String [String] 25.31 + deriving (Show) 25.32 +-- is equivalent to 25.33 +-- struct book_info { 25.34 +-- int id; 25.35 +-- char *name; 25.36 +-- char **authors; 25.37 +-- }; 25.38 \ No newline at end of file
26.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 26.2 +++ b/books/rwh/chapter03/ShapeUnion.hs Mon Mar 16 13:03:29 2009 -0400 26.3 @@ -0,0 +1,32 @@ 26.4 +-- file: chapter03/ShapeUnion.hs 26.5 + 26.6 +type Vector = (Double, Double) 26.7 + 26.8 +data Shape = Circle Vector Double 26.9 + | Poly [Vector] 26.10 + 26.11 +-- Is much nicer than... 26.12 + 26.13 +-- enum shape_type { 26.14 +-- shape_circle, 26.15 +-- shape_poly, 26.16 +-- }; 26.17 + 26.18 +-- struct circle { 26.19 +-- struct vector centre; 26.20 +-- float radius; 26.21 +-- }; 26.22 + 26.23 +-- struct poly { 26.24 +-- size_t num_vertices; 26.25 +-- struct vector *vertices; 26.26 +-- }; 26.27 + 26.28 +-- struct shape { 26.29 +-- enum shape_type type; 26.30 +-- union { 26.31 +-- struct circle circle; 26.32 +-- struct poly poly; 26.33 +-- } shape; 26.34 +-- 26.35 +-- }; 26.36 \ No newline at end of file
27.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 27.2 +++ b/books/rwh/chapter03/Tuple.hs Mon Mar 16 13:03:29 2009 -0400 27.3 @@ -0,0 +1,7 @@ 27.4 +-- file: chapter03/Tuple.hs 27.5 + 27.6 +third (a,b,c) = c 27.7 + 27.8 +complicated (True, a, x:xs, 5) = (a, xs) 27.9 +-- I feel like "complicated (True, a, [b], 5) = (a, (tail [b]))" should be equivalent but it throws an exception. 27.10 +-- Something about Non-exhaustive patterns in function. Hrm. The pattern match must not have recognized the list. 27.11 \ No newline at end of file
28.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 28.2 +++ b/books/rwh/chapter03/add.hs Mon Mar 16 13:03:29 2009 -0400 28.3 @@ -0,0 +1,12 @@ 28.4 +-- file: chapter03/add.hs 28.5 + 28.6 +add a b = a + b 28.7 + 28.8 +myNot True = False 28.9 +myNot False = True 28.10 + 28.11 +sumList (x:xs) = x + sumList xs 28.12 +sumList [] = 0 28.13 + 28.14 +-- List notation is in fact short for a cons string. I.e. [1..5] is short for [1,2,3,4,5] 28.15 +-- which is short for (1:(2:(3:(4:(5:[]))))).
29.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 29.2 +++ b/books/rwh/chapter03/exercise01.hs Mon Mar 16 13:03:29 2009 -0400 29.3 @@ -0,0 +1,9 @@ 29.4 +-- file: chapter03/exercise01.hs 29.5 +-- section: Recursive Types 29.6 + 29.7 +data List a = Cons a (List a) 29.8 + | Nil 29.9 + deriving (Show) 29.10 + 29.11 +toList (Cons a as) = a:(toList as) 29.12 +toList Nil = [] 29.13 \ No newline at end of file
30.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 30.2 +++ b/books/rwh/chapter03/exercise02.hs Mon Mar 16 13:03:29 2009 -0400 30.3 @@ -0,0 +1,10 @@ 30.4 +-- file: chapter03/exercise02.hs 30.5 +-- section: Recursive Types 30.6 + 30.7 +data Tree a = Node a (Maybe (Tree a)) (Maybe (Tree a)) 30.8 + deriving (Show) 30.9 + 30.10 +-- Actually, what you want to handle Empty correctly is: 30.11 + 30.12 +data MyTree a = MyTree (Maybe (a, MyTree a, MyTree a)) 30.13 + deriving (Show) 30.14 \ No newline at end of file
31.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 31.2 +++ b/books/rwh/chapter03/exercise03_04.hs Mon Mar 16 13:03:29 2009 -0400 31.3 @@ -0,0 +1,16 @@ 31.4 +-- file: chapter03/exercise03_04.hs 31.5 +-- section: Conditional Evaluation with Guards 31.6 + 31.7 +myLength :: [a] -> Int 31.8 +myLength xs = if null xs -- They're all pretty. 31.9 + then 0 31.10 + else 1 + myLength (tail xs) 31.11 + 31.12 +myLength2 :: [a] -> Int 31.13 +myLength2 xs -- But I think this reads best, at least for non-haskellers. 31.14 + | null xs = 0 31.15 + | otherwise = 1 + myLength (tail xs) 31.16 + 31.17 +myLength3 :: [a] -> Int 31.18 +myLength3 [] = 0 -- And this is most concise and best for haskellers. 31.19 +myLength3 (_:xs) = 1 + myLength3 xs 31.20 \ No newline at end of file
32.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 32.2 +++ b/books/rwh/chapter03/exercise05.hs Mon Mar 16 13:03:29 2009 -0400 32.3 @@ -0,0 +1,6 @@ 32.4 +-- file: chapter03/exercise05.hs 32.5 +-- section: Conditional Evaluation with Guards 32.6 + 32.7 +listMean :: [Double] -> Double 32.8 +listMean [] = 0 32.9 +listMean xs = sum xs / fromIntegral (length xs) 32.10 \ No newline at end of file
33.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 33.2 +++ b/books/rwh/chapter03/exercise06.hs Mon Mar 16 13:03:29 2009 -0400 33.3 @@ -0,0 +1,9 @@ 33.4 +-- file: chapter03/exercise06.hs 33.5 +-- section: Conditional Evaluation with Guards 33.6 + 33.7 +palindrome :: [a] -> [a] 33.8 +palindrome [] = [] 33.9 +palindrome xs = xs ++ myReverse xs 33.10 + 33.11 +myReverse [] = [] 33.12 +myReverse (x:xs) = myReverse xs ++ [x] 33.13 \ No newline at end of file
34.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 34.2 +++ b/books/rwh/chapter03/exercise07.hs Mon Mar 16 13:03:29 2009 -0400 34.3 @@ -0,0 +1,10 @@ 34.4 +-- file: chapter03/exercise07.hs 34.5 +-- section: Conditional Evaluation with Guards 34.6 + 34.7 +myReverse :: [a] -> [a] 34.8 +myReverse [] = [] 34.9 +myReverse (x:xs) = myReverse xs ++ [x] 34.10 + 34.11 +-- isPalindrome :: [a] -> Bool 34.12 +isPalindrome [] = True 34.13 +isPalindrome xs = myReverse xs == xs 34.14 \ No newline at end of file
35.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 35.2 +++ b/books/rwh/chapter03/exercise08.hs Mon Mar 16 13:03:29 2009 -0400 35.3 @@ -0,0 +1,15 @@ 35.4 +-- file: chapter03/exercise08.hs 35.5 +-- section: Conditional Evaluation with Guards 35.6 + 35.7 +import Data.List -- I've seen this before but it hasn't yet been introduced in the book. For shame. 35.8 + 35.9 +listSort :: [[a]] -> [[a]] 35.10 +listSort [] = [] 35.11 +listSort x = sortBy f x 35.12 + where 35.13 + f p q = compare (length p) (length q) -- why does this last line work?!?? 35.14 +-- and how the hell would I do it with pattern patching? 35.15 + 35.16 +--listByLen :: [[a]] -> [[a]] 35.17 +--listByLen [] = [] 35.18 +--listByLen (x:y:z) = sortBy (compare (length x) (length y)) z 35.19 \ No newline at end of file
36.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 36.2 +++ b/books/rwh/chapter03/exercise09.hs Mon Mar 16 13:03:29 2009 -0400 36.3 @@ -0,0 +1,17 @@ 36.4 +-- file: chapter03/exercise09.hs 36.5 +-- section: Conditional Evaluation with Guards 36.6 + 36.7 +intersperse :: a -> [[a]] -> [a] 36.8 +intersperse a xs 36.9 + | null xs = [] 36.10 + | length xs == 1 = head xs 36.11 + | otherwise = head xs ++ [a] ++ intersperse a (tail xs) 36.12 + 36.13 +-- I definitely prefer the second version. 36.14 +-- The solution was obvious but I forgot to write the concatenated a as [a] 36.15 +-- which confused the type checker. ++ can only accept lists, of course. 36.16 + 36.17 +intersperse2 :: a -> [[a]] -> [a] 36.18 +intersperse2 _ [] = [] 36.19 +intersperse2 _ (x:[]) = x 36.20 +intersperse2 s (x:xs) = x ++ [s] ++ intersperse s xs
37.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 37.2 +++ b/books/rwh/chapter03/exercise10.hs Mon Mar 16 13:03:29 2009 -0400 37.3 @@ -0,0 +1,36 @@ 37.4 +-- file: chapter03/exercise10.hs 37.5 +-- section: Conditional Evaluation with Guards 37.6 + 37.7 +data Tree a = Node a (Tree a) (Tree a) 37.8 + | Empty 37.9 + deriving (Show) 37.10 + 37.11 +simpleTree = Node "parent" (Node "left child" Empty Empty) 37.12 + (Node "right child" Empty Empty) 37.13 + 37.14 +-- Obviously, you never want to write code like complicatedTree. 37.15 +-- This is for illustrative purposes only. 37.16 +complicatedTree = Node "/" (Node "/boot" Empty 37.17 + (Node "/boot/grub" Empty Empty)) 37.18 + (Node "/home" 37.19 + (Node "/home/redline" 37.20 + (Node "/home/redline/code" 37.21 + (Node "/home/redline/code/books" Empty Empty) 37.22 + (Node "/home/redline/code/random" Empty Empty)) 37.23 + (Node "/home/redline/videos" Empty Empty)) 37.24 + (Node "/home/crazyman" Empty 37.25 + (Node "/home/crazyman/music" 37.26 + (Node "/home/crazyman/music/Singles" Empty Empty) 37.27 + (Node "/home/crazyman/music/Albums" 37.28 + (Node "/home/crazyman/music/Albums/Amon Tobin" Empty Empty) Empty)))) 37.29 + 37.30 +-- This was mostly tricky because I needlessly tried to figure out the type Signature for treeHeight. 37.31 +-- The pattern matching will figure out how to walk the tree. I don't really have to. 37.32 +treeHeight Empty = 0 37.33 +treeHeight (Node _ Empty Empty) = 1 37.34 +treeHeight (Node _ subTL Empty) = 1 + treeHeight subTL 37.35 +treeHeight (Node _ Empty subTR) = 1 + treeHeight subTR 37.36 +treeHeight (Node _ subTL subTR) 37.37 + | treeHeight subTL == treeHeight subTR = 1 + treeHeight subTL 37.38 + | treeHeight subTL > treeHeight subTR = 1 + treeHeight subTL 37.39 + | treeHeight subTL < treeHeight subTR = 1 + treeHeight subTR 37.40 \ No newline at end of file
38.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 38.2 +++ b/books/rwh/chapter03/exercise11.hs Mon Mar 16 13:03:29 2009 -0400 38.3 @@ -0,0 +1,7 @@ 38.4 +-- file: chapter03/exercise11.hs 38.5 +-- section: Conditional Evaluation with Guards 38.6 + 38.7 +data Direction = Left 38.8 + | Right 38.9 + | Straight 38.10 + deriving (Show) 38.11 \ No newline at end of file
39.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 39.2 +++ b/books/rwh/chapter03/exercise12.hs Mon Mar 16 13:03:29 2009 -0400 39.3 @@ -0,0 +1,3 @@ 39.4 +-- file: chapter03/exercise12.hs 39.5 +-- section: Conditional Evaluation with Guards 39.6 +
40.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 40.2 +++ b/books/rwh/chapter03/letwhere.hs Mon Mar 16 13:03:29 2009 -0400 40.3 @@ -0,0 +1,10 @@ 40.4 +-- file: chapter03/letwhere.hs 40.5 + 40.6 +bar = let b = 2 40.7 + c = True 40.8 + in let a = b 40.9 + in (a, c) 40.10 + 40.11 +foo = x 40.12 + where x = y 40.13 + where y = 2 40.14 \ No newline at end of file
41.1 --- a/books/rwh/functions.hs Mon Mar 09 14:49:35 2009 -0400 41.2 +++ b/books/rwh/functions.hs Mon Mar 16 13:03:29 2009 -0400 41.3 @@ -5,14 +5,19 @@ 41.4 41.5 -- GHCi functions: :set || :unset [prompt,], :?, :info (function), :type (expr), :load "filePath", :module + Data.Ratio, :show bindings. 41.6 -- GHCi continued: many can be abbreviated with their first initial but not unset. it is the last well-typed expression. 41.7 +-- GHC: -fwarn-incomplete-patterns will notify of patterns that don't match against all a type's constructors. 41.8 +-- GHC: -fwarn-name-shadowing will notify of shadowed names in nested lets. 41.9 +-- Type magic: data defines new type. type creates new type synonyms. deriving and show do what? 41.10 +-- Types cont: What can I say about Maybe Nothing Just Empty? 41.11 -- Arithmetic operators: + - / * ^ ** though negative numbers have to be written (-) number. Otherwise the expression is ill typed. 41.12 -- Arithmetic continued: ^ does integer exponentiation while ** handles floating point. % is in Data.Ratio. 41.13 --- Arithmetic continued: sqrt succ pred sin truncate round floor ceiling odd even compare mod 41.14 +-- Arithmetic continued: sqrt succ pred sin truncate round floor ceiling odd even compare mod sum 41.15 -- Note that prefix form is attained by enclosing the operator in parentheses followed by it's arguments. 41.16 -- Hence (-) with one argument will subtract that argument from 0. It's polymorphic. 41.17 --- Boolean Logic, Value Comparisons: && || == < > <= >= /= not 41.18 --- Conditional: if then else 41.19 --- Local assignment: let 41.20 +-- Boolean Logic, Value Comparisons: && || == < > <= >= /= not otherwise 41.21 +-- Conditional: if then else case | (|s are called guards and are used for conditional evaluation) 41.22 +-- Local assignment: let starts variable declarations, in ends it and starts the function body. where is a let whose assignment 41.23 +-- Local assignment: applies to the code behind it rather than in front of it. 41.24 -- Lists: ++ (:) length head tail take drop null last 41.25 -- Lists continued: The notation for list construction is brackets with comma separated values like so: [1,2,3] or ['a','b','c']. 41.26 -- Lists continued: List enumeration can be done with eg. [1..20] to construct a list from one to 20 or [1,4..15] to specify stepping. 41.27 @@ -20,5 +25,5 @@ 41.28 -- Lists continued: (:) is the constructor or cons function. It appends a single element to the front of the list i.e. (1 : [2,3]). 41.29 -- Tuple operators: (on pairs: fst, snd) 41.30 -- String handling: lines words 41.31 --- IO: putStrLn print readFile 41.32 +-- IO: putStrLn print readFile error 41.33 -- Random functions: pi
