├── .gitignore ├── CaesarCipher.hs ├── Chapter1.hs ├── Chapter10.hs ├── Chapter12.hs ├── Chapter1Ex.hs ├── Chapter2.hs ├── Chapter2Ex.hs ├── Chapter3.hs ├── Chapter3Ex.hs ├── Chapter4.hs ├── Chapter4Ex.hs ├── Chapter5.hs ├── Chapter5Ex.hs ├── Chapter6.hs ├── Chapter6Ex.hs ├── Chapter7.hs ├── Chapter7Ex.hs ├── Chapter9.hs ├── CountdownProblem.hs ├── CreditCardValidator.hs ├── Hangman.hs ├── Monads.hs ├── README.md ├── Scratch.hs ├── Setup.hs └── programming-in-haskell.cabal /.gitignore: -------------------------------------------------------------------------------- 1 | dist/* 2 | -------------------------------------------------------------------------------- /CaesarCipher.hs: -------------------------------------------------------------------------------- 1 | module CaesarCipher where 2 | 3 | import Data.Char hiding (isLower, isUpper) 4 | 5 | {- 6 | 7 | a Caesar cipher, also known as the shift cipher, Caesar's code or Caesar shift, 8 | is one of the simplest and most widely known encryption techniques. 9 | It is a type of substitution cipher in which each letter in the plaintext 10 | is replaced by a letter some fixed number of positions down the alphabet. 11 | For example, with a left shift of 3, D would be replaced by A, E 12 | would become B, and so on. 13 | The method is named after Julius Caesar, who used it in his private correspondence. 14 | 15 | "haskell is fun" 16 | with a shift factor of 3 17 | "kdvnhoo lv ixq" 18 | shift factor of 10 19 | "rkcuovv sc pex" 20 | 21 | -} 22 | 23 | isInRange :: Char -> Char -> Char -> Bool 24 | isInRange l u c = (c >= l) && (c <= u) 25 | 26 | isLower :: Char -> Bool 27 | isLower = isInRange 'a' 'z' 28 | 29 | isUpper :: Char -> Bool 30 | isUpper = isInRange 'A' 'Z' 31 | 32 | -- 33 | 34 | let2Int :: Char -> Char -> Int 35 | let2Int x c = ord c - ord x 36 | 37 | lcLet2Int :: Char -> Int 38 | lcLet2Int = let2Int 'a' 39 | 40 | ucLet2Int :: Char -> Int 41 | ucLet2Int = let2Int 'A' 42 | 43 | -- 44 | 45 | int2Let :: Char -> Int -> Char 46 | int2Let x n = chr (ord x + n) 47 | 48 | int2LcLet :: Int -> Char 49 | int2LcLet = int2Let 'a' 50 | 51 | int2UcLet :: Int -> Char 52 | int2UcLet = int2Let 'A' 53 | 54 | -- 55 | 56 | shift :: Int -> Char -> Char 57 | shift n c | isLower c = int2LcLet ((lcLet2Int c + n) `mod` 26) 58 | | isUpper c = int2UcLet ((ucLet2Int c + n) `mod` 26) 59 | | otherwise = c 60 | 61 | encode :: Int -> String -> String 62 | encode n xs = [shift n x | x <- xs] 63 | 64 | decode :: Int -> String -> String 65 | decode n = encode (-n) 66 | 67 | -- Assignment: how to crack it! :D 68 | -------------------------------------------------------------------------------- /Chapter1.hs: -------------------------------------------------------------------------------- 1 | module Chapter1 where 2 | 3 | -- what is functional programming? 4 | -- immutability 5 | -- highr order functions 6 | -- recursion 7 | -- purity 8 | -- lazy evaluation 9 | 10 | {- 11 | other fp languages (or supports fp) 12 | erlang (elixir) 13 | lisp (scheme, racket, clojure, elisp) 14 | ml 15 | f# 16 | scala 17 | javascript 18 | php 19 | perl 20 | java 8 21 | python 22 | -} 23 | 24 | double x = x + x 25 | 26 | {- 27 | 2 types of evaluation 28 | eager/strict (call by value) 29 | lazy (call by name) 30 | 31 | show Java version of summing 1 to 10 32 | show Haskell version of summing 1 to 10 33 | repl: sum [1..10] 34 | 35 | Features of Haskell 36 | 1. Concise programs 37 | 2. Powerful Type System 38 | 3. List Comprehensions 39 | 4. Recursive Functions 40 | 5. Higher-order Functions 41 | 6. Monadic Effects 42 | 7. Lazy Evaluation 43 | 8. Reasoning about programs 44 | 45 | Historical Background 46 | 1930s Alonzo Church 47 | Lambda Calculus - a system for mathematical computation 48 | using function abstraction and application 49 | 1950s John McCarthy Lisp (LISt Processor) 50 | 1st fp language (with mutable data) 51 | 1960s Peter Landin ISWIM (If you See What I Mean) 52 | 1st 'pure' fp language (no assignments) 53 | 1970s John Backus FP (Functional Programming) 54 | extensive use of higher order functions 55 | 1970s Robin Milner ML (Meta-Language) 56 | fp with type inference and polymorphic types (generics) 57 | 1970s and 1980s David Turner Miranda 58 | developed a number of lazy fp languages 59 | 1987 Simon Peyton Jones, Paul Hudak, Philip Wadler, John Hughes, et al. 60 | Haskell 61 | 2003 Haskell 98 Report 62 | 1st stable version 63 | 64 | Use in the Industry 65 | Google 66 | Facebook 67 | Twitter 68 | League of Legends 69 | Call of Duty 70 | Eve Online 71 | 72 | -} 73 | 74 | sum' [] = 0 75 | sum' (x : xs) = x + sum' xs 76 | 77 | qsort [] = [] 78 | qsort (x : xs) = qsort smaller ++ [x] ++ qsort larger 79 | where 80 | smaller = [l | l <- xs, l <= x] 81 | larger = [r | r <- xs, r > x] 82 | 83 | {- 84 | install ghc 85 | 86 | install development environment 87 | emacs 88 | vi 89 | eclipsefp 90 | fpcomplete 91 | 92 | ghci interpreter 93 | http://tryhaskell.org/ 94 | 95 | -} 96 | -------------------------------------------------------------------------------- /Chapter10.hs: -------------------------------------------------------------------------------- 1 | module Chapter10 where 2 | 3 | import Prelude hiding (Left, Right, String) 4 | 5 | {- 6 | 7 | Types and Classes 8 | 9 | 10 | Type declarations 11 | declaring type synonyms 12 | 13 | -} 14 | 15 | type String = [Char] 16 | 17 | type Pos = (Int, Int) 18 | type Board = [Pos] 19 | 20 | -- it can also be parameterised 21 | 22 | type Assoc k v = [(k, v)] 23 | 24 | {- 25 | 26 | Data declarations 27 | 28 | data Bool = False | True 29 | 30 | -} 31 | 32 | 33 | data Move = Left | Right | Up | Down 34 | deriving Show 35 | 36 | move :: Move -> Pos -> Pos 37 | move Left (x, y) = (x - 1, y) 38 | move Right (x, y) = (x + 1, y) 39 | move Up (x, y) = (x, y + 1) 40 | move Down (x, y) = (x, y - 1) 41 | 42 | moves :: [Move] -> Pos -> Pos 43 | moves [] p = p 44 | moves (m : ms) p = moves ms (move m p) 45 | 46 | 47 | flip :: Move -> Move 48 | flip Left = Right 49 | flip Right = Left 50 | flip Up = Down 51 | flip Down = Up 52 | 53 | 54 | data Shape = Circle Float | Rect Float Float 55 | deriving Show 56 | 57 | square :: Float -> Shape 58 | square n = Rect n n 59 | 60 | area :: Shape -> Float 61 | area (Circle r) = pi * r ^ 2 62 | area (Rect x y) = x * y 63 | 64 | {- 65 | 66 | Recursive types 67 | 68 | -} 69 | 70 | data Nat = Zero | Succ Nat 71 | deriving Show 72 | 73 | nat2int :: Nat -> Int 74 | nat2int Zero = 0 75 | nat2int (Succ n) = 1 + nat2int n 76 | 77 | int2nat :: Int -> Nat 78 | int2nat 0 = Zero 79 | int2nat n = Succ (int2nat (n - 1)) 80 | 81 | add :: Nat -> Nat -> Nat 82 | add Zero n = n 83 | add (Succ m) n = Succ (add m n) 84 | 85 | 86 | 87 | data List a = Nil | Cons a (List a) 88 | deriving Show 89 | 90 | len :: List a -> Int 91 | len Nil = 0 92 | len (Cons _ xs) = 1 + len xs 93 | 94 | 95 | 96 | data Tree a = Leaf a | Branch (Tree a) a (Tree a) 97 | deriving Show 98 | 99 | t :: Tree Int 100 | t = Branch (Branch (Leaf 1) 3 (Leaf 4)) 5 (Branch (Leaf 6) 7 (Leaf 9)) 101 | 102 | occurs :: Eq a => a -> Tree a -> Bool 103 | occurs m (Leaf n) = m == n 104 | occurs m (Branch l n r) = m == n || occurs m l || occurs m r 105 | 106 | -- if the tree is ordered 107 | 108 | occurs' :: Ord a => a -> Tree a -> Bool 109 | occurs' m (Leaf n) = m == n 110 | occurs' m (Branch l n r) | m == n = True 111 | | m < n = occurs' m l 112 | | otherwise = occurs' m r 113 | 114 | flatten :: Tree a -> [a] 115 | flatten (Leaf n) = [n] 116 | flatten (Branch l n r) = flatten l ++ [n] ++ flatten r 117 | -------------------------------------------------------------------------------- /Chapter12.hs: -------------------------------------------------------------------------------- 1 | module Chapter12 where 2 | 3 | -- Lazy Evaluation 4 | 5 | -- evaluate an expression when it is needed 6 | 7 | inc :: Int -> Int 8 | inc n = n + 1 9 | 10 | {- 11 | 12 | Eager Evaluation or CBV 13 | 14 | inc (2 * 3) 15 | inc 6 16 | 6 + 1 17 | 7 18 | 19 | Lazy Evaluation or CBN 20 | 21 | inc (2 * 3) 22 | (2 * 3) + 1 23 | 6 + 1 24 | 7 25 | 26 | -} 27 | 28 | {- 29 | 30 | This does not hold for most imperative languages 31 | 32 | CBN 33 | n = 0 34 | n + (n = 1) 35 | 0 + (n = 1) 36 | 0 + 1 37 | 1 38 | 39 | CBV 40 | n = 0 41 | n + (n = 1) 42 | n + 1 43 | 1 + 1 44 | 2 45 | 46 | -} 47 | 48 | mult :: (Int, Int) -> Int 49 | mult (x, y) = x * y 50 | 51 | {- 52 | 53 | CBV 54 | mult (1 + 2, 2 + 3) 55 | mult (3, 2 + 3) 56 | mult (3, 5) 57 | 3 * 5 58 | 15 59 | 60 | CBN 61 | mult (1 + 2, 2 + 3) 62 | (1 + 2) * (2 + 3) 63 | 3 * (2 + 3) 64 | 3 * 5 65 | 15 66 | 67 | -} 68 | 69 | -- Lambda Expressions 70 | 71 | mult' :: Int -> Int -> Int 72 | mult' x = \ y -> x * y 73 | 74 | {- 75 | 76 | CBV 77 | mult (1 + 2) (2 + 3) 78 | mult 3 (2 + 3) 79 | (\ y -> 3 * y) (2 + 3) 80 | (\ y -> 3 * y) 5 81 | 3 * 5 82 | 15 83 | 84 | CBN 85 | mult (1 + 2) (2 + 3) 86 | (\ y -> (1 + 2) * y) (2 + 3) 87 | (1 + 2) * (2 + 3) 88 | 3 * (2 + 3) 89 | 3 * 5 90 | 15 91 | 92 | -} 93 | 94 | -- Termination 95 | 96 | inf :: Int 97 | inf = 1 + inf 98 | 99 | {- 100 | 101 | Both CBV and CBN will not terminate 102 | 103 | inf 104 | 1 + inf 105 | 1 + 1 + inf 106 | 1 + 1 + 1 + inf 107 | 1 + 1 + 1 + 1 + ...... 108 | 109 | -} 110 | 111 | fst' :: (Int, Int) -> Int 112 | fst' (x, _) = x 113 | 114 | {- 115 | CBV 116 | fst (0, inf) 117 | fst (0, 1 + inf) 118 | fst (0, 1 + 1 + .....) 119 | 120 | CBN 121 | fst (0, inf) 122 | 0 123 | 124 | -} 125 | 126 | -- Number of reductions 127 | 128 | square :: Int -> Int 129 | square x = x * x 130 | 131 | {- 132 | 133 | CBV 134 | square (1 + 2) 135 | square 3 136 | 3 * 3 137 | 9 138 | 139 | CBN 140 | square (1 + 2) 141 | (1 + 2) * (1 + 2) 142 | 3 * (1 + 2) 143 | 3 * 3 144 | 9 145 | 146 | -} 147 | 148 | -- Infinite Structures 149 | 150 | ones :: [Int] 151 | ones = 1 : ones 152 | 153 | {- 154 | 155 | Both CBV and CBN 156 | 157 | ones 158 | 1 : ones 159 | 1 : 1 : ones 160 | 1 : 1 : 1 : ...... 161 | 162 | CBV 163 | head ones 164 | head (1 : ones) 165 | head (1 : 1 : ones) 166 | head (1 : 1 : 1 : .......) 167 | 168 | CBN 169 | head ones 170 | head (1 : ones) 171 | 1 172 | 173 | take 3 ones 174 | [1, 1, 1] 175 | 176 | filter (<= 5) [1..] will not terminate 177 | 178 | takeWhile (<= 5) [1..] will terminate 179 | 180 | -} 181 | 182 | -- Strict Application (using eager evaluation) 183 | 184 | {- 185 | 186 | use the $! function 187 | 188 | square $! (1 + 2) 189 | square $! 3 190 | square 3 191 | 3 * 3 192 | 9 193 | 194 | -} 195 | -------------------------------------------------------------------------------- /Chapter1Ex.hs: -------------------------------------------------------------------------------- 1 | module Chapter1Ex where 2 | 3 | -- 1. Give another possible calculation for the result of double (double 2). 4 | 5 | double x = x + x 6 | 7 | {- 8 | 9 | double (double 2) 10 | double (2 + 2) 11 | (2 + 2) + (2 + 2) 12 | 4 + (2 + 2) 13 | 4 + 4 14 | 8 15 | 16 | -} 17 | 18 | -- 2. Show that sum [x] = x for any number x. 19 | 20 | sum' [] = 0 21 | sum' (x : xs) = x + sum xs 22 | 23 | {- 24 | 25 | sum [8, 15, 76, 81, 5] 26 | 8 + sum [15, 76, 81, 5] 27 | 8 + (15 + sum [76, 81, 5]) 28 | 8 + (15 + (76 + sum [81, 5])) 29 | 8 + (15 + (76 + (81 + sum [5]))) 30 | 8 + (15 + (76 + (81 + (5 + sum [])))) 31 | 8 + (15 + (76 + (81 + (5 + (0))))) 32 | 185 33 | 34 | -} 35 | 36 | -- 3. Define a function product that produces the product of a list of numbers, and show using your definition that product [2, 3, 4] = 24. 37 | 38 | product' [] = 1 39 | product' (x : xs) = x * product xs 40 | 41 | {- 42 | 43 | product [2, 3, 4] 44 | 2 * product [3, 4] 45 | 2 * (3 * product [4]) 46 | 2 * (3 * (4 * product [])) 47 | 2 * (3 * (4 * (1))) 48 | 24 49 | 50 | -} 51 | 52 | -- 4. How should the definition of the function qsort be modified so that it produces a reverse sorted version of a list? 53 | 54 | qsort [] = [] 55 | qsort (x : xs) = qsort left ++ [x] ++ qsort right 56 | where left = [l | l <- xs, l <= x] 57 | right = [r | r <- xs, r > x] 58 | 59 | rqsort [] = [] 60 | rqsort (x : xs) = rqsort left ++ [x] ++ rqsort right 61 | where left = [l | l <- xs, l >= x] 62 | right = [r | r <- xs, r < x] 63 | 64 | {- 65 | 66 | qsort [2, 9, 1, 3, 10] 67 | (qsort [1]) ++ [2] ++ (qsort [9, 3, 10]) 68 | ([] ++ [1] ++ []) ++ [2] ++ ((qsort [3]) ++ [9] ++ (qsort [10])) 69 | ([] ++ [1] ++ []) ++ [2] ++ (([] ++ [3] ++ []) ++ [9] ++ ([] ++ [10] ++ [])) 70 | 71 | -} 72 | 73 | -- 5. What would be the effect of replacing <= by < in the definition of qsort? Hint: consider the example qsort [2, 2, 3, 1, 1]. 74 | 75 | xqsort [] = [] 76 | xqsort (x : xs) = xqsort left ++ [x] ++ xqsort right 77 | where left = [l | l <- xs, l < x] 78 | right = [r | r <- xs, r > x] 79 | 80 | {- 81 | 82 | xqsort [2, 2, 3, 1, 1] 83 | (xqsort [1]) ++ [2] ++ (xqsort [3]) 84 | ([] ++ [1] ++ []) ++ [2] ++ ([] ++ [3] ++ []) 85 | 86 | -} 87 | 88 | -- elements would be sorted, but some duplicate elements will be omitted 89 | -------------------------------------------------------------------------------- /Chapter2.hs: -------------------------------------------------------------------------------- 1 | module Chapter2 where 2 | 3 | -- discuss Karate Kid Movie 4 | 5 | -- discuss Prelude 6 | 7 | -- repl: 2 + 3 8 | -- repl: 2 - 3 9 | -- repl: 2 * 3 10 | -- repl: 7 `div` 2 11 | -- repl: 2 ^ 3 12 | 13 | -- emdas 14 | 15 | -- repl: head [1, 2, 3, 4, 5] 16 | -- repl: tail [1, 2, 3, 4, 5] 17 | -- repl: [1, 2, 3, 4, 5] !! 2 18 | -- repl: take 3 [1, 2, 3, 4, 5] 19 | -- repl: drop 3 [1, 2, 3, 4, 5] 20 | -- repl: length [1, 2, 3, 4, 5] 21 | -- repl: sum [1, 2, 3, 4, 5] 22 | -- repl: product [1, 2, 3, 4, 5] 23 | -- repl: [1, 2, 3] ++ [4, 5] 24 | -- repl: reverse [1, 2, 3, 4, 5] 25 | 26 | -- repl: 1 `div` 0 27 | -- repl: head [] 28 | 29 | -- discuss function application with accordance to mathematics 30 | -- f(a, b) + c d 31 | -- f a b + c * d 32 | -- femdas 33 | -- f a + b means (f a) + b 34 | 35 | {- 36 | 37 | Math 38 | f(x) 39 | f(x, y) 40 | f(g(x)) 41 | f(x, g(y)) 42 | f(x)g(y) 43 | 44 | Haskell 45 | f x 46 | f x y 47 | f (g x) 48 | f x (g y) 49 | f x * g y 50 | 51 | also compare with other languages 52 | 53 | discuss working with a text editor and ghci 54 | discuss common ghci commands 55 | 56 | :load or :l 57 | :reload or :r 58 | :edit :e 59 | :type :t 60 | :? 61 | :quit or :q 62 | 63 | discuss naming requirements 64 | 65 | functions starts with lowercase letters 66 | but can be follwed by zero or more letters (upper and lower), 67 | digits, underscores and quotes 68 | 69 | you cannot use keywords as function names or values 70 | case 71 | class 72 | data 73 | default 74 | deriving 75 | do 76 | else 77 | if 78 | import 79 | in 80 | infix 81 | infixl 82 | infixr 83 | instance 84 | let 85 | module 86 | newtype 87 | of 88 | then 89 | type 90 | where 91 | 92 | discuss layout rule 93 | 94 | -} 95 | 96 | a = b + c 97 | where b = 1 98 | c = 2 99 | d = a * 2 100 | 101 | -- discuss comments (single line and multi line) 102 | 103 | -- dicuss book, installation and fpcomplete 104 | -------------------------------------------------------------------------------- /Chapter2Ex.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE NoImplicitPrelude #-} 2 | 3 | module Chapter2Ex where 4 | 5 | import Prelude (div, error, otherwise, undefined, (+), (++), (-), 6 | (==), (>)) 7 | 8 | -- 1. Parenthesise the following arithmetic expressions: 9 | 10 | {- 11 | 12 | 2 ^ 3 * 4 13 | (2 ^ 3) * 4 14 | 15 | 2 * 3 + 4 * 5 16 | (2 ∗ 3) + (4 ∗ 5) 17 | 18 | 2 + 3 * 4 ^ 5 19 | 2 + (3 * (4 ^ 5)) 20 | 21 | -} 22 | 23 | -- 2. Work through the examples from this chapter using ghci. 24 | 25 | {- 26 | 27 | -} 28 | 29 | -- 3. The script below contains three syntactic errors. Correct these errors and then check that your script works properly using ghci. 30 | 31 | {- 32 | 33 | N = a ’div’ length xs 34 | where 35 | a = 10 36 | xs = [1, 2, 3, 4, 5] 37 | 38 | -} 39 | 40 | n = a `div` length xs 41 | where a = 10 42 | xs = [1, 2, 3, 4, 5] 43 | 44 | -- 4. Show how the library function last that selects the last element of a non-empty list could be defined in terms of the library functions introduced in this chapter. Can you think of another possible definition? 45 | 46 | length [] = 0 47 | length (x : xs) = 1 + length xs 48 | 49 | [] !! n = error "invalid index" 50 | (x : xs) !! 0 = x 51 | (x : xs) !! n | n > 0 = xs !! (n - 1) 52 | | otherwise = error "invalid index" 53 | 54 | last' xs = xs !! (length xs - 1) 55 | 56 | {- 57 | 58 | last' [1, 2, 3, 4, 5] 59 | [1, 2, 3, 4, 5] !! (length [1, 2, 3, 4, 5] - 1) 60 | [1, 2, 3, 4, 5] !! ((1 + length [2, 3, 4, 5]) - 1) 61 | [1, 2, 3, 4, 5] !! ((1 + (1 + length [3, 4, 5])) - 1) 62 | [1, 2, 3, 4, 5] !! ((1 + (1 + (1 + length [4, 5]))) - 1) 63 | [1, 2, 3, 4, 5] !! ((1 + (1 + (1 + (1 + length [5])))) - 1) 64 | [1, 2, 3, 4, 5] !! ((1 + (1 + (1 + (1 + (1 + length []))))) - 1) 65 | [1, 2, 3, 4, 5] !! ((1 + (1 + (1 + (1 + (1 + (0)))))) - 1) 66 | [2, 3, 4, 5] !! (((1 + (1 + (1 + (1 + (1 + (0)))))) - 1) - 1) 67 | [3, 4, 5] !! ((((1 + (1 + (1 + (1 + (1 + (0)))))) - 1) - 1) - 1) 68 | [4, 5] !! (((((1 + (1 + (1 + (1 + (1 + (0)))))) - 1) - 1) - 1) - 1) 69 | [5] !! ((((((1 + (1 + (1 + (1 + (1 + (0)))))) - 1) - 1) - 1) - 1) - 1) 70 | [5] !! 0 71 | 5 72 | 73 | -} 74 | 75 | head [] = error "empty list" 76 | head (x : xs) = x 77 | 78 | reverse [] = [] 79 | reverse (x : xs) = reverse xs ++ [x] 80 | 81 | last'' xs = head (reverse xs) 82 | 83 | {- 84 | 85 | last'' [1, 2, 3, 4, 5] 86 | head (reverse [1, 2, 3, 4, 5]) 87 | head (reverse [2, 3, 4, 5] ++ [1]) 88 | head ((reverse [3, 4, 5] ++ [2]) ++ [1]) 89 | head (((reverse [4, 5] ++ [3]) ++ [2]) ++ [1]) 90 | head ((((reverse [5] ++ [4]) ++ [3]) ++ [2]) ++ [1]) 91 | head (((((reverse [] ++ [5]) ++ [4]) ++ [3]) ++ [2]) ++ [1]) 92 | head (((((([]) ++ [5]) ++ [4]) ++ [3]) ++ [2]) ++ [1]) 93 | head [5, 4, 3, 2, 1] 94 | 5 95 | 96 | -} 97 | 98 | last''' [] = error "empty list" 99 | last''' [x] = x 100 | last''' (x : xs) = last''' xs 101 | 102 | {- 103 | 104 | last''' [1, 2, 3, 4, 5] 105 | last''' [2, 3, 4, 5] 106 | last''' [3, 4, 5] 107 | last''' [4, 5] 108 | last''' [5] 109 | 5 110 | 111 | -} 112 | 113 | -- 5. Show how the library function init that removes the last element from a non-empty list could similarly be defined in two different ways. 114 | 115 | take n [] = [] 116 | take 0 xs = xs 117 | take 1 (x : xs) = [x] 118 | take n (x : xs) = x : take (n - 1) xs 119 | 120 | init' xs = take (length xs - 1) xs 121 | 122 | {- 123 | 124 | init' [1, 2, 3, 4, 5] 125 | take (length [1, 2, 3, 4, 5] - 1) [1, 2, 3, 4, 5] 126 | take ((1 + length [2, 3, 4, 5]) - 1) [1, 2, 3, 4, 5] 127 | take ((1 + (1 + length [3, 4, 5])) - 1) [1, 2, 3, 4, 5] 128 | take ((1 + (1 + (1 + length [4, 5]))) - 1) [1, 2, 3, 4, 5] 129 | take ((1 + (1 + (1 + (1 + length [5])))) - 1) [1, 2, 3, 4, 5] 130 | take ((1 + (1 + (1 + (1 + (1 + length []))))) - 1) [1, 2, 3, 4, 5] 131 | take ((1 + (1 + (1 + (1 + (1 + (0)))))) - 1) [1, 2, 3, 4, 5] 132 | take 4 [1, 2, 3, 4, 5] 133 | 1 : (take 3 [2, 3, 4, 5]) 134 | 1 : (2 : (take 2 [3, 4, 5])) 135 | 1 : (2 : (3 : (take 1 [4, 5]))) 136 | 1 : (2 : (3 : ([4]))) 137 | [1, 2, 3, 4] 138 | 139 | -} 140 | 141 | drop n [] = [] 142 | drop 0 xs = xs 143 | drop 1 (x : xs) = xs 144 | drop n (x : xs) = drop (n - 1) xs 145 | 146 | init'' xs = reverse (drop 1 (reverse xs)) 147 | 148 | {- 149 | 150 | init'' [1, 2, 3, 4, 5] 151 | reverse (drop 1 (reverse [1, 2, 3, 4, 5])) 152 | reverse (drop 1 (reverse [2, 3, 4, 5] ++ [1])) 153 | reverse (drop 1 ((reverse [3, 4, 5] ++ [2]) ++ [1])) 154 | reverse (drop 1 (((reverse [4, 5] ++ [3]) ++ [2]) ++ [1])) 155 | reverse (drop 1 ((((reverse [5] ++ [4]) ++ [3]) ++ [2]) ++ [1])) 156 | reverse (drop 1 ((((([] ++ [5]) ++ [4]) ++ [3]) ++ [2]) ++ [1])) 157 | reverse (drop 1 [5, 4, 3, 2, 1]) 158 | reverse [4, 3, 2, 1] 159 | (reverse [3, 2, 1]) ++ [4] 160 | ((reverse [2, 1] ++ [3]) ++ [4]) 161 | (((reverse [1] ++ [2]) ++ [3]) ++ [4]) 162 | ((((reverse [] ++ [1]) ++ [2]) ++ [3]) ++ [4]) 163 | ((((([]) ++ [1]) ++ [2]) ++ [3]) ++ [4]) 164 | [1, 2, 3, 4] 165 | 166 | -} 167 | 168 | init''' [] = error "empty list" 169 | init''' [x] = [] 170 | init''' (x : xs) = x : init''' xs 171 | 172 | {- 173 | 174 | init''' [1, 2, 3, 4, 5] 175 | 1 : (init''' [2, 3, 4, 5]) 176 | 1 : (2 : (init''' [3, 4, 5])) 177 | 1 : (2 : (3 : init''' [4, 5])) 178 | 1 : (2 : (3 : (4 : init''' [5]))) 179 | 1 : (2 : (3 : (4 : []))) 180 | [1, 2, 3, 4] 181 | 182 | -} 183 | -------------------------------------------------------------------------------- /Chapter3.hs: -------------------------------------------------------------------------------- 1 | module Chapter3 where 2 | 3 | {- 4 | 5 | WAVE!!! 6 | 7 | Types and Classes 8 | 9 | Type - ia a collection of related values 10 | 11 | type Bool has two values 12 | True and False 13 | 14 | repl> :i Bool 15 | repl> :t True 16 | repl> :t False 17 | 18 | repl> :t not 19 | repl> not True 20 | repl> not False 21 | 22 | :: 23 | 24 | Basic Types 25 | 26 | Bool 27 | True and False 28 | 29 | Char 30 | 'a', 'A', '3', '_' 31 | 32 | String 33 | [Char] 34 | "mike" "xyber" 35 | 36 | Int 37 | -9223372036854775808 to 9223372036854775807 38 | 39 | Integer 40 | no limit 41 | 42 | Float 43 | single-precision floating-point 44 | 45 | Double 46 | double-precision floating-point 47 | 48 | List Types 49 | a sequence of elements of the same type 50 | can be of any length/size 51 | [False, True, False] :: [Bool] 52 | ['a', 'b', 'c', 'd'] :: [Char] or String 53 | "abcd" 54 | ["one", "two", "three"] :: [String] or [[Char]] 55 | 56 | Tuple Types 57 | sequence of elements of diffrent types 58 | fixed length/size 59 | (False, True) :: (Bool, Bool) 60 | (False, 'a', 1) :: (Bool, Char, Int) 61 | ("Mike", True, 'a') = (String, Bool, Char) 62 | 63 | Function Types 64 | mapping of arguments of 1 type to the result of another/same type 65 | not :: Bool -> Bool 66 | isDigit :: Char -> Bool 67 | 68 | WAVE!!! 69 | 70 | Curried Functions 71 | a function with n arguments return another function with n - 1 argument 72 | 73 | -} 74 | 75 | add :: Int -> Int -> Int 76 | -- can also be expressed as Int -> (Int -> Int) 77 | add x y = x + y 78 | addTwo = add 2 79 | 80 | {- 81 | 82 | function add(x) { 83 | return function(y) { 84 | return x + y; 85 | }; 86 | } 87 | 88 | OR 89 | 90 | function add(x, y) { 91 | return x + y; 92 | } 93 | 94 | var addTwo = _.partial(add, 2); 95 | 96 | -} 97 | 98 | mult :: Int -> Int -> Int -> Int-> Int 99 | -- Int -> (Int -> (Int -> Int)) 100 | mult x y z a = x * y * z * a 101 | multThree = mult 3 102 | 103 | {- 104 | 105 | function mult(x) { 106 | return function(y) { 107 | return function(z) { 108 | return x * y * z; 109 | }; 110 | }; 111 | } 112 | 113 | OR 114 | 115 | function mult(x, y ,z) { 116 | return x * y * z; 117 | } 118 | 119 | var multThree = _.partial(mult, 3) 120 | 121 | 122 | 123 | 124 | Polymorphic Types 125 | a type is polymorphic if there is more than one type it can have 126 | repl> :t length 127 | repl> :t head 128 | repl> :t tail 129 | repl> :t take 130 | repl> :t zip 131 | 132 | 133 | 134 | Overloaded Functions 135 | functions that can perform same operation that has same type 136 | repl> :i Num 137 | repl> :t (+) 138 | repl> :t (*) 139 | repl> :t (-) 140 | repl> :t negate 141 | repl> :t abs 142 | repl> :t signum 143 | 144 | 145 | Basic Classes 146 | collection of types that support certain overloaded functions 147 | much like an Interface in OOP 148 | 149 | Eq 150 | equality types 151 | repl> :i Eq 152 | repl> :t (==) 153 | repl> :t (/=) 154 | 155 | Ord 156 | oredered types 157 | repl> :i Ord 158 | repl> :t (>) 159 | repl> :t (>=) 160 | repl> :t (<) 161 | repl> :t (<=) 162 | repl> :t min 163 | repl> :t max 164 | 165 | Show 166 | showable types 167 | converts any value to a String 168 | much like the toString() method in Java in its own Interface 169 | repl> :i Show 170 | repl> :t show 171 | 172 | Read 173 | readable types 174 | reads a String converts to its proper type 175 | repl> :i Read 176 | repl> :t read 177 | 178 | Num 179 | numeric types 180 | types that support basic numeric operations 181 | repl> :i Num 182 | repl> :t (+) 183 | repl> :t (*) 184 | repl> :t (-) 185 | repl> :t negate 186 | repl> :t abs 187 | repl> :t signum 188 | 189 | Integral 190 | integral types 191 | extends from Num, supports int division and integer remainder 192 | repl> :i Integral 193 | 194 | Fractional 195 | frational types 196 | also extends from Num, supports fractional division and reciprocation 197 | repl> :i Fractional 198 | 199 | 200 | -} 201 | -------------------------------------------------------------------------------- /Chapter3Ex.hs: -------------------------------------------------------------------------------- 1 | module Chapter3Ex where 2 | 3 | {- 4 | 1. What are the types of the following values? 5 | 6 | ['a', 'b', 'c'] 7 | [Char] or String 8 | 9 | ('a', 'b', 'c') 10 | (Char, Char, Char) 11 | 12 | [(False, '0'), (True, '1')] 13 | [(Bool, Char)] 14 | 15 | ([False, True], ['0', '1']) 16 | ([Bool], [Char]) 17 | ([Bool], String) 18 | 19 | [tail, init, reverse] 20 | [[a] -> [a]] 21 | 22 | 23 | 2. What are the types of the following functions? 24 | -} 25 | 26 | tail' :: [a] -> [a] 27 | tail' [] = error "empty" 28 | tail' (x : xs) = xs 29 | 30 | head' :: [a] -> a 31 | head' [] = error "empty" 32 | head' (x : xs) = x 33 | 34 | second xs = head' (tail' xs) 35 | -- second :: [a] -> a 36 | 37 | swap (x, y) = (y, x) 38 | -- swap :: (a, b) -> (b, a) 39 | 40 | pair x y = (x, y) 41 | -- pair :: a -> b -> (a, b) 42 | 43 | double x = x * 2 44 | -- double :: Num a => a -> a 45 | 46 | reverse' :: [a] -> [a] 47 | reverse' [] = [] 48 | reverse' (x : xs) = reverse xs ++ [x] 49 | 50 | palindrome xs = reverse' xs == xs 51 | -- palindrome :: Eq a => [a] -> Bool 52 | 53 | twice f x = f (f x) 54 | -- twice :: (a -> b) -> a -> b 55 | 56 | {- 57 | 58 | 3. Check your answers to the preceding two questions using ghci. 59 | 60 | 4. Why is it not feasible in general for function types to be instances of the Eq 61 | class? When is it feasible? Hint: two functions of the same type are equal if 62 | they always return equal results for equal arguments. 63 | 64 | Why? 65 | Because of the Halting Problem 66 | 67 | When? 68 | If someone solved the Halting Problem 69 | 70 | -} 71 | 72 | -- considering a machine with infinite resources and not affected by external factors 73 | 74 | fnHaltsImmediately :: Int -> Int 75 | fnHaltsImmediately n = n + 3 76 | 77 | fnHaltsForSomeTime :: Int -> Int 78 | fnHaltsForSomeTime n | (foldl (+) 0 [1..n]) > 0 = n + 3 79 | | otherwise = n + 3 80 | 81 | fnDoesNotHalt :: Int -> Int 82 | fnDoesNotHalt n = fnDoesNotHalt n 83 | 84 | willFnHalt :: (Int -> Int) -> Int -> Bool 85 | willFnHalt f n | f n > 0 = True 86 | | otherwise = True 87 | -------------------------------------------------------------------------------- /Chapter4.hs: -------------------------------------------------------------------------------- 1 | module Chapter4 where 2 | 3 | import Prelude hiding ((&&)) 4 | 5 | {- 6 | 7 | WAVE!!!! :D 8 | 9 | Defining Functions 10 | 11 | -} 12 | 13 | isDigit' :: Char -> Bool 14 | isDigit' c = (c >= '0') && (c <= '9') 15 | 16 | even' :: Integral a => a -> Bool 17 | even' x = x `mod` 2 == 0 18 | 19 | splitAt' :: Int -> [a] -> ([a], [a]) 20 | splitAt' n xs = (take n xs, drop n xs) 21 | 22 | {- 23 | 24 | Conditional Expressions 25 | 26 | -} 27 | 28 | abs' :: Int -> Int 29 | abs' x = if x >= 0 then x else (-x) 30 | 31 | 32 | signum' :: Int -> Int 33 | signum' n = if n < 0 34 | then (-1) 35 | else if n == 0 36 | then 0 37 | else 1 38 | {- 39 | 40 | Guarded Equations 41 | 42 | -} 43 | 44 | abs'' :: Int -> Int 45 | abs'' n | n == 0 = 0 46 | | n > 0 = n 47 | | otherwise = (-n) 48 | 49 | signum'' :: Int -> Int 50 | signum'' n | n < 0 = (-1) 51 | | n == 0 = 0 52 | | n > 0 = 1 53 | 54 | {- 55 | 56 | Pattern Matching 57 | 58 | -} 59 | 60 | not' :: Bool -> Bool 61 | not' True = False 62 | not' False = True 63 | 64 | (&&) :: Bool -> Bool -> Bool 65 | True && True = True 66 | True && False = False 67 | False && True = False 68 | False && False = False 69 | 70 | --or 71 | 72 | ands :: Bool -> Bool -> Bool 73 | True `ands` True = True 74 | _ `ands` _ = False 75 | 76 | --or 77 | 78 | ands2 :: Bool -> Bool -> Bool 79 | True `ands2` x = x 80 | False `ands2` _ = False 81 | 82 | {- 83 | 84 | Tuple Patterns 85 | 86 | -} 87 | 88 | fst' :: (a, b) -> a 89 | fst' (x, _) = x 90 | 91 | snd' :: (a, b) -> b 92 | snd' (_, x) = x 93 | 94 | {- 95 | 96 | List Patterns 97 | 98 | -} 99 | 100 | test :: [Char] -> Bool 101 | test ['a', _, _] = True 102 | test _ = False 103 | 104 | {- 105 | 106 | matching on cons 107 | 108 | [1, 2, 3] 109 | 1 : [2, 3] 110 | 1 : 2 : [3] 111 | 1 : 2 : 3 : [] 112 | 113 | -} 114 | 115 | test' :: [Char] -> Bool 116 | test' ('a' : _) = True 117 | test' _ = False 118 | 119 | null' :: [a] -> Bool 120 | null' [] = True 121 | null' (_ : _) = False 122 | 123 | head' :: [a] -> a 124 | head' (x : _) = x 125 | head' [] = error "empty" 126 | 127 | tail' :: [a] -> [a] 128 | tail' [] = error "empty" 129 | tail' (_ : xs) = xs 130 | 131 | {- 132 | 133 | Lambda Expressions 134 | Anonymous Functions 135 | "functions with no name" 136 | 137 | -} 138 | 139 | double :: Int -> Int 140 | double = \ x -> x + x 141 | 142 | {- 143 | 144 | var double = function(x) { 145 | return x + x; 146 | }; 147 | 148 | -} 149 | 150 | 151 | add :: Int -> Int -> Int 152 | add x y = x + y 153 | 154 | add' :: Int -> Int -> Int 155 | add' y = \ x -> x + y 156 | 157 | add'' :: Int -> Int -> Int 158 | add'' = \ x -> \ y -> x + y 159 | 160 | {- 161 | 162 | Sections 163 | same as currying but you could curry on both args on a infix op 164 | 165 | -} 166 | -------------------------------------------------------------------------------- /Chapter4Ex.hs: -------------------------------------------------------------------------------- 1 | module Chapter4Ex where 2 | 3 | import Prelude hiding ((&&), (||)) 4 | 5 | {- 6 | 1. Using library functions, define a function halve :: [ a ] -> ([ a ], [ a ]) that 7 | splits an even-lengthed list into two halves. For example: 8 | -} 9 | 10 | halve :: [a] -> ([a], [a]) 11 | halve xs | even (length xs) = splitAt (length xs `div` 2) xs 12 | | otherwise = error "odd number list" 13 | 14 | {- 15 | 2. Consider a function safetail :: [ a ] → [ a ] that behaves as the library func- 16 | tion tail , except that safetail maps the empty list to itself, whereas tail 17 | produces an error in this case. Define safetail using: 18 | a. conditional expression 19 | b. guarded equation 20 | c. pattern matching 21 | Hint: make use of the library function null . 22 | -} 23 | 24 | tail' :: [a] -> [a] 25 | tail' [] = error "empty list" 26 | tail' (x : xs) = xs 27 | 28 | -- conditional expression 29 | 30 | safetail :: [a] -> [a] 31 | safetail xs = if null xs 32 | then [] 33 | else tail' xs 34 | 35 | {- 36 | safetail [1, 2, 3, 4, 5] 37 | tail' [1, 2, 3, 4, 5] 38 | [2, 3, 4, 5] 39 | 40 | safetail [] 41 | [] 42 | -} 43 | 44 | -- guarded equation 45 | 46 | safetail' :: [a] -> [a] 47 | safetail' xs | null xs = [] 48 | | otherwise = tail' xs 49 | 50 | {- 51 | safetail [1, 2, 3, 4, 5] 52 | tail' [1, 2, 3, 4, 5] 53 | [2, 3, 4, 5] 54 | 55 | safetail [] 56 | [] 57 | -} 58 | 59 | -- pattern matching 60 | 61 | safetail'' :: [a] -> [a] 62 | safetail'' [] = [] 63 | safetail'' (_ : xs) = xs 64 | 65 | {- 66 | safetail'' [1, 2, 3, 4, 5] 67 | [2, 3, 4, 5] 68 | 69 | safetail'' [] 70 | [] 71 | -} 72 | 73 | {- 74 | 3. In a similar way to &&, show how the logical disjunction operator || can be 75 | defined in four different ways using pattern matching. 76 | -} 77 | 78 | (||) :: Bool -> Bool -> Bool 79 | True || True = True 80 | True || False = True 81 | False || True = True 82 | False || False = False 83 | 84 | {- 85 | 4. Redefine the following version of the conjunction operator using conditional 86 | expressions rather than pattern matching: 87 | True && True = True 88 | _ && _ = False 89 | -} 90 | 91 | (&&) :: Bool -> Bool -> Bool 92 | x && y = if x == True 93 | then if y == True 94 | then True 95 | else False 96 | else False 97 | 98 | {- 99 | 5. Do the same for the following version, and note the difference in the number 100 | of conditional expressions required: 101 | True && b = b 102 | False && _ = False 103 | -} 104 | 105 | (&&&) :: Bool -> Bool -> Bool 106 | x &&& y = if x == True 107 | then y 108 | else False 109 | 110 | {- 111 | 6. Show how the curried function definition mult x y z = x ∗ y ∗ z can be 112 | understood in terms of lambda expressions. 113 | -} 114 | 115 | mult :: Num a => a -> a -> a -> a 116 | mult x y z = x * y * z 117 | 118 | mult' :: Num a => a -> a -> a -> a 119 | mult' y z = \ x -> x * y * z 120 | 121 | mult'' :: Num a => a-> a -> a -> a 122 | mult'' z = \ x -> \ y -> x * y * z 123 | 124 | mult''' :: Num a => a -> a -> a -> a 125 | mult''' = \ x -> \ y -> \ z -> x * y * z 126 | 127 | {- 128 | 129 | function mult(x, y, z) { 130 | return x * y * z; 131 | } 132 | 133 | 134 | function mult(y, z) { 135 | return function(x) { 136 | return x * y * z; 137 | }; 138 | } 139 | 140 | function mult(z) { 141 | return function(x) { 142 | return function(y) { 143 | return x * y * z; 144 | }; 145 | }; 146 | } 147 | 148 | function mult() { 149 | return function(x) { 150 | return function(y) { 151 | return function(z) { 152 | return x * y * z; 153 | }; 154 | }; 155 | }; 156 | } 157 | 158 | -} 159 | -------------------------------------------------------------------------------- /Chapter5.hs: -------------------------------------------------------------------------------- 1 | module Chapter5 where 2 | 3 | {- 4 | 5 | WAVE!!! 6 | 7 | List Comprehensions 8 | 9 | Similarites with Set Comprehensions/Builder Notation in Mathematics 10 | 11 | -} 12 | 13 | a = [ x ^ 2 | x <- [0..9] ] 14 | 15 | b = [ (x, y) | x <- [1..3], y <- [4,5] ] 16 | 17 | c = [ (x, y) | y <- [4, 5], x <- [1..3] ] 18 | 19 | d = [ x * y | x <- [1..3], y <- [4,5] ] 20 | 21 | e = [ (x, y) | x <- [1..3], y <- [x..5] ] 22 | 23 | concat' :: [[a]] -> [a] 24 | concat' xss = [x | xs <- xss, x <- xs] 25 | 26 | firsts :: [(a, b)] -> [a] 27 | firsts ps = [x | (x, _) <- ps] 28 | 29 | length' :: [a] -> Int 30 | length' xs = sum [1 | _ <- xs] 31 | 32 | {- 33 | 34 | Guards/Filters 35 | 36 | -} 37 | 38 | factors :: Int -> [Int] 39 | factors n = [x | x <- [1..n], n `mod` x == 0] 40 | 41 | {- 42 | 43 | Prime Numbers 44 | is a natural number greater than 1 that 45 | has no positive divisors other than 1 and itself 46 | 47 | -} 48 | 49 | isPrime :: Int -> Bool 50 | isPrime n = factors n == [1, n] 51 | 52 | primes :: Int -> [Int] 53 | primes n = [x | x <- [2..n], isPrime x] 54 | 55 | find' :: Eq a => a -> [(a, b)] -> [b] 56 | find' k xs = [s | (f, s) <- xs, f == k] 57 | 58 | {- 59 | 60 | The zip function 61 | 62 | -} 63 | 64 | zip' :: [a] -> [b] -> [(a, b)] 65 | zip' [] [] = [] 66 | zip' [] (_ : _) = [] 67 | zip' (_ : _) [] = [] 68 | zip' (x : xs) (y : ys) = (x, y) : zip xs ys 69 | 70 | zip'' :: [a] -> [b] -> [(a, b)] 71 | zip'' (x : xs) (y : ys) = (x, y) : zip'' xs ys 72 | zip'' _ _ = [] 73 | 74 | {- 75 | 76 | zip [1, 2, 3, 4, 5] ["mike", "rai", "rex"] 77 | (1, "mike") : zip [2, 3, 4, 5] ["rai", "rex"] 78 | (1, "mike") : ((2, "rai") : zip [3, 4, 5] ["rex"]) 79 | (1, "mike") : ((2, "rai") : ((3, "rex") : zip [4, 5] [])) 80 | (1, "mike") : ((2, "rai") : ((3, "rex") : [])) 81 | 82 | -} 83 | 84 | pairs :: [a] -> [(a, a)] 85 | pairs xs = zip xs (tail xs) 86 | 87 | {- 88 | 89 | pairs [1, 2, 3, 4, 5] 90 | zip [1, 2, 3, 4, 5] (tail [1, 2, 3, 4, 5]) 91 | zip [1, 2, 3, 4, 5] [2, 3, 4, 5] 92 | (1, 2) : zip [2, 3, 4, 5] [3, 4, 5] 93 | (1, 2) : (2, 3) : zip [3, 4, 5] [4, 5] 94 | (1, 2) : (2, 3) : (3, 4) : zip [4, 5] [5] 95 | (1, 2) : (2, 3) : (3, 4) : (4, 5) : zip [5] [] 96 | (1, 2) : (2, 3) : (3, 4) : (4, 5) : [] 97 | 98 | -} 99 | 100 | and' :: [Bool] -> Bool 101 | and' [] = True 102 | and' (x : xs) = x && and' xs 103 | 104 | {- 105 | 106 | and [True, False, True] 107 | True && and [False, True] 108 | True && False && and [True] 109 | True && False && True && and [] 110 | True && False && True && True 111 | 112 | -} 113 | 114 | isSorted :: Ord a => [a] -> Bool 115 | isSorted xs = and' [x <= y | (x, y) <- pairs xs] 116 | 117 | positions :: Eq a => a -> [a] -> [Int] 118 | positions x xs = [s | (f, s) <- zip xs [0..(length xs - 1)], f == x] 119 | 120 | {- 121 | 122 | String Comprehensions 123 | 124 | -} 125 | 126 | f = "abcde" !! 2 127 | 128 | g = take 3 "abcde" 129 | 130 | h = length "abcde" 131 | 132 | i = zip "abc" [1..4] 133 | 134 | isLower :: Char -> Bool 135 | isLower c = (c >= 'a') && (c <= 'z') 136 | 137 | countLowers :: String -> Int 138 | countLowers xs = length [x | x <- xs, isLower x] 139 | 140 | countLetters :: Char -> String -> Int 141 | countLetters c xs = length [x | x <- xs, x == c] 142 | 143 | -- continue to Caesar Cipher 144 | -------------------------------------------------------------------------------- /Chapter5Ex.hs: -------------------------------------------------------------------------------- 1 | module Chapter5Ex where 2 | 3 | {- 4 | 5 | 1. Using a list comprehension, give an expression that calculates the sum 6 | 1 ^ 2 + 2 ^ 2 + . . . 100 ^ 2 of the first one hundred integer squares. 7 | 8 | -} 9 | 10 | sumOf100 = sum [x ^ 2 | x <- [1..100]] 11 | 12 | 13 | {- 14 | 15 | (for { 16 | x <- List() 17 | } yield x ^ 2).sum() 18 | 19 | -} 20 | 21 | {- 22 | 23 | 2. In a similar way to the function length , show how the library function 24 | replicate :: Int → a → [ a ] that produces a list of identical elements can 25 | be defined using a list comprehension. For example: 26 | > replicate 3 True 27 | [ True , True , True ] 28 | 29 | -} 30 | 31 | lcReplicate :: Int -> a -> [a] 32 | lcReplicate n x = [x | _ <- [1..n]] 33 | 34 | {- 35 | 36 | 3. A triple (x, y, z) of positive integers is pythagorean if x ^ 2 + y ^ 2 = z ^ 2 . Using 37 | a list comprehension, define a function pyths :: Int → [( Int , Int , Int )] that 38 | returns the list of all pythagorean triples whose components are at most a 39 | given limit. For example: 40 | > pyths 10 41 | [(3, 4, 5), (4, 3, 5), (6, 8, 10), (8, 6, 10)] 42 | 43 | -} 44 | 45 | pyths :: Int -> [(Int, Int, Int)] 46 | pyths n = [(x, y, z) | x <- [1..n], y <- [1..n], z <- [1..n], x ^ 2 + y ^ 2 == z ^ 2] 47 | 48 | {- 49 | 50 | 4. A positive integer is perfect if it equals the sum of its factors, excluding the 51 | number itself. Using a list comprehension and the function factors , define a 52 | function perfects :: Int → [ Int ] that returns the list of all perfect numbers 53 | up to a given limit. For example: 54 | > perfects 500 55 | [6, 28, 496] 56 | 57 | -} 58 | 59 | factors :: Int -> [Int] 60 | factors n = [x | x <- [1..n], n `mod` x == 0] 61 | 62 | isPerfect :: Int -> Bool 63 | isPerfect n = let facs = factors n 64 | in sum (init facs) == last facs 65 | 66 | perfects :: Int -> [Int] 67 | perfects n = [x | x <- [1..n], isPerfect x] 68 | 69 | {- 70 | 71 | 5. Show how the single comprehension [(x, y) | x <- [1, 2, 3], y <- 72 | [4, 5, 6]] with two generators can be re-expressed using two comprehen- 73 | sions with single generators. Hint: make use of the library function concat 74 | and nest one comprehension within the other. 75 | 76 | -} 77 | 78 | comp2 :: [(Int, Int)] 79 | comp2 = concat [[(x, y) | y <- [4, 5, 6]] | x <- [1, 2, 3]] 80 | 81 | {- 82 | 83 | 6. Redefine the function positions using the function find. 84 | 85 | -} 86 | 87 | find :: Eq a => a -> [(a, b)] -> [b] 88 | find k ps = [s | (f, s) <- ps, f == k] 89 | 90 | positions :: Eq a => a -> [a] -> [Int] 91 | positions k xs = find k (zip xs [0..(length xs - 1)]) 92 | 93 | {- 94 | 95 | 7. The scalar product of two lists of integers xs and ys of length n is given by 96 | the sum of the products of corresponding integers: 97 | [Please see the formula in the book] 98 | In a similar manner to the function chisqr , show how a list comprehension 99 | can be used to define a function scalarproduct :: [ Int ] → [ Int ] → Int that 100 | returns the scalar product of two lists. For example: 101 | > scalarproduct [1, 2, 3] [4, 5, 6] 102 | 32 103 | 104 | -} 105 | 106 | -- Scalar Product is also known as Dot Product 107 | 108 | dotp :: [Int] -> [Int] -> Int 109 | dotp xs ys = sum [x * y | (x, y) <- zip xs ys] 110 | 111 | {- 112 | 113 | 8. Modify the Caesar cipher program to also handle upper-case letters. 114 | 115 | -} 116 | 117 | 118 | {- 119 | 120 | 9. Crack it :D 121 | 122 | -} 123 | -------------------------------------------------------------------------------- /Chapter6.hs: -------------------------------------------------------------------------------- 1 | module Chapter6 where 2 | 3 | import Prelude hiding ((++)) 4 | 5 | {- 6 | 7 | WAVE!!!!! 8 | 9 | Recursions 10 | 11 | a function that calls itself 12 | because of immutability (no state mutation), recursion is the only way to 'loop' 13 | 14 | -} 15 | 16 | sum' :: Num a => [a] -> a 17 | sum' [] = 0 18 | sum' (x : xs) = x + sum' xs 19 | 20 | product' :: Num a => [a] -> a 21 | product' [] = 1 22 | product' (x : xs) = x * product xs 23 | 24 | factorial :: Int -> Int 25 | factorial n = product' [1..n] 26 | 27 | {- 28 | 29 | Recursion on Lists 30 | 31 | -} 32 | 33 | length' :: [a] -> Int 34 | length' [] = 0 35 | length' (_ : xs) = 1 + length' xs 36 | 37 | (++) :: [a] -> [a] -> [a] 38 | [] ++ ys = ys 39 | (x : xs) ++ ys = x : (xs ++ ys) 40 | 41 | reverse' :: [a] -> [a] 42 | reverse' [] = [] 43 | reverse' (x : xs) = reverse' xs ++ [x] 44 | 45 | insert :: Ord a => a -> [a] -> [a] 46 | insert x [] = [x] 47 | insert x (y : ys) | x <= y = x : y : ys 48 | | otherwise = y : insert x ys 49 | 50 | isort :: Ord a => [a] -> [a] 51 | isort [] = [] 52 | isort (x : xs) = insert x (isort xs) 53 | 54 | {- 55 | 56 | Multiple Arguments 57 | 58 | -} 59 | 60 | zip' :: [a] -> [b] -> [(a, b)] 61 | zip' (x : xs) (y: ys) = (x, y) : zip xs ys 62 | zip' _ _ = [] 63 | 64 | take' :: Int -> [a] -> [a] 65 | take' _ [] = [] 66 | take' n (x : xs) | n <= 0 = [] 67 | | otherwise = x : take' (n - 1) xs 68 | 69 | drop' :: Int -> [a] -> [a] 70 | drop' _ [] = [] 71 | drop' n list@(_ : xs) | n <= 0 = list 72 | | otherwise = drop' (n - 1) xs 73 | 74 | {- 75 | 76 | Multiple Recursion 77 | 78 | -} 79 | 80 | 81 | fib :: Int -> Int 82 | fib 0 = 0 83 | fib 1 = 1 84 | fib n = fib (n - 1) + fib (n - 2) 85 | 86 | qsort :: Ord a => [a] -> [a] 87 | qsort [] = [] 88 | qsort (x : xs) = qsort left ++ [x] ++ qsort right 89 | where left = [l | l <- xs, l <= x] 90 | right = [r | r <- xs, r > x] 91 | 92 | {- 93 | 94 | Mutual Recursion 95 | 2 or more functions that call each other recursively 96 | -} 97 | 98 | -- taking even postions on the list 99 | evens :: [a] -> [a] 100 | evens [] = [] 101 | evens (x : xs) = x : odds xs 102 | 103 | 104 | -- taking odd positions on the list 105 | odds :: [a] -> [a] 106 | odds [] = [] 107 | odds (_ : xs) = evens xs 108 | 109 | {- 110 | 111 | Advice on reursions 112 | 113 | 1. Define the type 114 | 2. Enumerate the cases 115 | 3. Define the simple case 116 | 4. Define other cases 117 | 5. Generalize and Simplify 118 | 119 | -} 120 | -------------------------------------------------------------------------------- /Chapter6Ex.hs: -------------------------------------------------------------------------------- 1 | module Chapter6Ex where 2 | 3 | import Prelude hiding (and, concat, drop, elem, init, last, length, 4 | replicate, sum, take) 5 | 6 | {- 7 | 8 | 1. Define the exponentiation operator ^ for non-negative integers using the 9 | same pattern of recursion as the multiplication operator ∗, and show how 10 | 2 ^ 3 is evaluated using your definition. 11 | 12 | -} 13 | 14 | (<^>) :: Int -> Int -> Int 15 | n <^> 0 = 1 16 | n <^> 1 = n 17 | n <^> e | n > 1 && e > 1 = n * (n <^> (e - 1)) 18 | | otherwise = error "negative num" 19 | 20 | {- 21 | 22 | 2. Using the definitions given in this chapter, show how length [1, 2, 3], 23 | drop 3 [1, 2, 3, 4, 5], and init [1, 2, 3] are evaluated. 24 | 25 | -} 26 | 27 | length :: [a] -> Int 28 | length [] = 0 29 | length (_ : xs) = 1 + length xs 30 | 31 | {- 32 | 33 | length [1, 2, 3] 34 | 1 + length [2, 3] 35 | 1 + (1 + length [3]) 36 | 1 + (1 + (1 + length [])) 37 | 1 + (1 + (1 + 0)) 38 | 1 + (1 + 1) 39 | 1 + 2 40 | 3 41 | -} 42 | 43 | drop :: Int -> [a] -> [a] 44 | drop 0 xs = xs 45 | drop _ [] = [] 46 | drop n (x : xs) | n > 0 = drop (n - 1) xs 47 | | otherwise = [] 48 | 49 | {- 50 | 51 | drop 3 [1, 2, 3, 4, 5] 52 | drop (3 - 1) [2, 3, 4, 5] 53 | drop 2 [2, 3, 4, 5] 54 | drop (2 - 1) [3, 4, 5] 55 | drop 1 [3, 4, 5] 56 | drop (1 - 1) [4, 5] 57 | drop 0 [4, 5] 58 | [4, 5] 59 | 60 | -} 61 | 62 | init :: [a] -> [a] 63 | init [] = error "empty list" 64 | init [x] = [] 65 | init (x : xs) = x : init xs 66 | 67 | {- 68 | 69 | init [1, 2, 3] 70 | 1 : init [2, 3] 71 | 1 : (2 : init [3]) 72 | 1 : (2 : []) 73 | 1 : [2] 74 | [1, 2] 75 | 76 | -} 77 | 78 | {- 79 | 80 | 3. Without looking at the definitions from the standard prelude, define the 81 | following library functions using recursion. 82 | 83 | – Decide if all logical values in a list are True : 84 | and :: [Bool] -> Bool 85 | 86 | -} 87 | 88 | and :: [Bool] -> Bool 89 | and [] = True 90 | and (x : xs) = x && and xs 91 | 92 | {- 93 | 94 | and [True, False, True] 95 | True && and [False, True] 96 | True && (False && and [True]) 97 | True && (False && (True && and [])) 98 | True && (False && (True && True)) 99 | True && (False && True) 100 | True && False 101 | False 102 | 103 | -} 104 | 105 | {- 106 | 107 | – Concatenate a list of lists: 108 | concat :: [[a]] -> [a] 109 | 110 | -} 111 | 112 | concat :: [[a]] -> [a] 113 | concat [] = [] 114 | concat (x : xs) = x ++ concat xs 115 | 116 | {- 117 | 118 | concat [[1, 2], [3, 4, 5], [6]] 119 | [1, 2] ++ concat [[3, 4, 5], [6]] 120 | [1, 2] ++ ([3, 4, 5] ++ concat [[6]]) 121 | [1, 2] ++ ([3, 4, 5] ++ ([6] ++ concat [])) 122 | [1, 2] ++ ([3, 4, 5] ++ ([6] ++ [])) 123 | [1, 2] ++ ([3, 4, 5] ++ [6]) 124 | [1, 2] ++ [3, 4, 5, 6] 125 | [1, 2, 3, 4, 5, 6] 126 | 127 | -} 128 | 129 | {- 130 | 131 | – Produce a list with n identical elements: 132 | replicate :: Int -> a -> [a] 133 | 134 | -} 135 | 136 | replicate :: Int -> a -> [a] 137 | replicate 0 _ = [] 138 | replicate 1 x = [x] 139 | replicate n x | n > 0 = x : replicate (n - 1) x 140 | | otherwise = [] 141 | 142 | {- 143 | 144 | replicate 3 5 145 | 5 : replicate (3 - 1) 5 146 | 5 : replicate 2 5 147 | 5 : (5 : replicate (2 - 1) 5) 148 | 5 : (5 : replicate 1 5) 149 | 5 : (5 : [5]) 150 | 5 : [5, 5] 151 | [5, 5, 5] 152 | 153 | -} 154 | 155 | {- 156 | 157 | – Select the nth element of a list: 158 | (!!) :: [a] -> Int -> a 159 | 160 | -} 161 | 162 | nth :: [a] -> Int -> a 163 | [] `nth` _ = error "empty list" 164 | (x : xs) `nth` n | n == 0 = x 165 | | n > 0 = xs `nth` (n - 1) 166 | | otherwise = error "negative num" 167 | 168 | {- 169 | 170 | [1, 2, 3, 4, 5] `nth` 3 171 | [2, 3, 4, 5] `nth` (3 - 1) 172 | [2, 3, 4, 5] `nth` 2 173 | [3, 4, 5] `nth` (2 - 1) 174 | [3, 4, 5] `nth` 1 175 | [4, 5] `nth` (1 - 1) 176 | [4, 5] `nth` 0 177 | 4 178 | 179 | -} 180 | 181 | {- 182 | 183 | – Decide if a value is an element of a list: 184 | elem :: Eq a => a -> [a] -> Bool 185 | 186 | -} 187 | 188 | elem :: Eq a => a -> [a] -> Bool 189 | elem _ [] = False 190 | elem n (x : xs) | n == x = True 191 | | otherwise = elem n xs 192 | 193 | {- 194 | 195 | elem 3 [1, 2, 3, 4, 5] 196 | elem 3 [2, 3, 4, 5] 197 | elem 3 [3, 4, 5] 198 | True 199 | 200 | -} 201 | 202 | {- 203 | 204 | Note: most of these functions are in fact defined in the prelude using other 205 | library functions, rather than using explicit recursion. 206 | 207 | -} 208 | 209 | {- 210 | 211 | 4. Define a recursive function merge :: Ord a => [a] -> [a] -> [a] that 212 | merges two sorted lists to give a single sorted list. For example: 213 | > merge [2, 5, 6] [1, 3, 4] 214 | [1, 2, 3, 4, 5, 6] 215 | 216 | Note: your definition should not use other functions on sorted lists such as 217 | insert or isort , but should be defined using explicit recursion. 218 | 219 | -} 220 | 221 | merge :: Ord a => [a] -> [a] -> [a] 222 | merge [] [] = [] 223 | merge [] ys = ys 224 | merge xs [] = xs 225 | merge list1@(x: xs) list2@(y : ys) | x <= y = x : merge xs list2 226 | | otherwise = y : merge list1 ys 227 | 228 | {- 229 | 230 | merge [2, 5, 6] [1, 3, 4] 231 | 1 : merge [2, 5, 6] [3, 4] 232 | 1 : (2 : merge [5, 6] [3, 4]) 233 | 1 : (2 : (3 : merge [5, 6] [4])) 234 | 1 : (2 : (3 : (4 : merge [5, 6] []))) 235 | 1 : (2 : (3 : (4 : [5, 6]))) 236 | 1 : (2 : (3 : [4, 5, 6])) 237 | 1 : (2 : [3, 4, 5, 6]) 238 | 1 : [2, 3, 4, 5, 6] 239 | [1, 2, 3, 4, 5, 6] 240 | 241 | -} 242 | 243 | {- 244 | 245 | 5. Using merge , define a recursive function msort :: Ord a => [a] -> [a] that 246 | implements merge sort, in which the empty list and singleton lists are already 247 | sorted, and any other list is sorted by merging together the two lists that 248 | result from sorting the two halves of the list separately. 249 | 250 | Hint: first define a function halve :: [a] -> ([a], [a]) that splits a list into 251 | two halves whose lengths differ by at most one. 252 | 253 | -} 254 | 255 | halve :: [a] -> ([a], [a]) 256 | halve xs = splitAt (length xs `div` 2) xs 257 | 258 | msort :: Ord a => [a] -> [a] 259 | msort [] = [] 260 | msort [x] = [x] 261 | msort xs = merge (msort f) (msort s) 262 | where (f, s) = halve xs 263 | 264 | {- 265 | 266 | msort [2, 5, 6, 1, 3, 4] 267 | merge [2, 5, 6] [1, 3, 4] 268 | ....same as above.... 269 | 270 | -} 271 | 272 | {- 273 | 274 | 6. Using the five-step process, define the library functions that calculate the 275 | sum of a list of numbers, take a given number of elements from the start of 276 | a list, and select the last element of a non-empty list. 277 | 278 | -} 279 | 280 | {- 281 | 282 | sum 283 | 284 | 1. define the type 285 | 286 | sum :: [Int] -> Int 287 | 288 | 2. enumerate the cases 289 | 290 | sum [] 291 | sum [x] 292 | sum [x, y] 293 | sum (x : xs) 294 | 295 | 3. define the simple cases 296 | 297 | sum [] = 0 298 | sum [x] = x 299 | sum [x, y] = x + y 300 | sum (x : xs) = ... 301 | 302 | 4. define other cases 303 | 304 | sum [] = 0 305 | sum [x] = x 306 | sum [x, y] = x + y 307 | sum (x : xs) = x + sum xs 308 | 309 | 5. generalize and simplify 310 | 311 | sum [] = 0 312 | sum (x : xs) = x + sum xs 313 | 314 | -} 315 | 316 | sum :: [Int] -> Int 317 | sum [] = 0 318 | sum (x : xs) = x + sum xs 319 | 320 | {- 321 | 322 | take 323 | 324 | 1. define the type 325 | 326 | take :: Int -> [a] -> [a] 327 | 328 | 2. enumerate the cases 329 | 330 | take n [] 331 | take 0 xs 332 | take n (x : xs) 333 | 334 | 3. define simple cases 335 | 336 | take n [] = [] 337 | take 0 xs = [] 338 | take n (x : xs) = ... 339 | 340 | 4. define other cases 341 | 342 | take n [] = [] 343 | take 0 xs = [] 344 | take n (x : xs) | n > 0 = x : take (n - 1) xs 345 | | otherwise = [] 346 | 347 | 5. generalize and simplify 348 | 349 | take 0 _ = [] 350 | take _ [] = [] 351 | take n (x : xs) | n > 0 = x : take (n - 1) xs 352 | | otherwise = [] 353 | 354 | -} 355 | 356 | take :: Int -> [a] -> [a] 357 | take 0 _ = [] 358 | take _ [] = [] 359 | take n (x : xs) | n > 0 = x : take (n - 1) xs 360 | | otherwise = [] 361 | 362 | {- 363 | 364 | last 365 | 366 | 1. define the type 367 | 368 | last :: [a] -> a 369 | 370 | 2. enumerate the cases 371 | 372 | last [] 373 | last [x] 374 | last (x : xs) 375 | 376 | 3. define simple cases 377 | 378 | last [] = error "empty" 379 | last [x] = x 380 | last (x : xs) = .... 381 | 382 | 4. define other cases 383 | 384 | last [] = error "empty" 385 | last [x] = x 386 | last (x : xs) = last xs 387 | 388 | 5. generalize and simplify 389 | 390 | last [] = error "empty" 391 | last [x] = x 392 | last (x : xs) = last xs 393 | 394 | -} 395 | 396 | last :: [a] -> a 397 | last [] = error "empty" 398 | last [x] = x 399 | last (x : xs) = last xs 400 | -------------------------------------------------------------------------------- /Chapter7.hs: -------------------------------------------------------------------------------- 1 | module Chapter7 where 2 | 3 | import Prelude hiding (and, filter, foldl, foldr, length, map, odd, 4 | or, product, reverse, sum, (.)) 5 | 6 | {- 7 | 8 | Higher Order Functions 9 | 10 | encapsulates common code into functions 11 | reusability 12 | DRY - don't repeat yourself 13 | 14 | -} 15 | 16 | add :: Int -> Int -> Int 17 | add x y = x + y 18 | 19 | --means 20 | 21 | add' :: Int -> (Int -> Int) 22 | add' = \ x -> (\ y -> x + y) 23 | 24 | {- 25 | 26 | function add(x) { 27 | return function(y) { return x + y;}; 28 | } 29 | 30 | -} 31 | 32 | twice :: (a -> a) -> a -> a 33 | twice f x = f (f x) 34 | 35 | qsort :: Ord a => (a -> a -> Bool) -> [a] -> [a] 36 | qsort _ [] = [] 37 | qsort f (x : xs) = qsort f left ++ [x] ++ qsort f right 38 | where left = [l | l <- xs, f l x || l == x] 39 | right = [r | r <- xs, not (f r x)] 40 | 41 | fqsort :: Ord a => [a] -> [a] 42 | fqsort = qsort (<) 43 | 44 | rqsort :: Ord a => [a] -> [a] 45 | rqsort = qsort (>) 46 | 47 | insert :: Ord a => (a -> a -> Bool) -> a -> [a] -> [a] 48 | insert _ x [] = [x] 49 | insert f x (y : ys) | f x y || x == y = x : y : ys 50 | | otherwise = y : insert f x ys 51 | 52 | finsert :: Ord a => a -> [a] -> [a] 53 | finsert = insert (<) 54 | 55 | rinsert :: Ord a => a -> [a] -> [a] 56 | rinsert = insert (>) 57 | 58 | isort :: Ord a => (a -> [a] -> [a]) -> [a] -> [a] 59 | isort _ [] = [] 60 | isort f (x : xs) = f x (isort f xs) 61 | 62 | fisort :: Ord a => [a] -> [a] 63 | fisort = isort finsert 64 | 65 | risort :: Ord a => [a] -> [a] 66 | risort = isort rinsert 67 | 68 | {- 69 | 70 | Processing Lists 71 | 72 | -} 73 | 74 | -- The map function 75 | 76 | map :: (a -> b) -> [a] -> [b] 77 | map f xs = [f x | x <- xs] 78 | 79 | map' :: (a -> b) -> [a] -> [b] 80 | map' _ [] = [] 81 | map' f (x : xs) = f x : map' f xs 82 | 83 | {- 84 | 85 | map (+1) [1, 3, 5, 7] 86 | (+1) 1 : map (+1) [3, 5, 7] 87 | (+1) 1 : ((+1) 3 : map (+1) [5, 7]) 88 | (+1) 1 : ((+1) 3 : ((+1) 5 : map (+1) [7])) 89 | (+1) 1 : ((+1) 3 : ((+1) 5 : ((+1) 7 : map (+1) []))) 90 | (+1) 1 : ((+1) 3 : ((+1) 5 : ((+1) 7 : []))) 91 | (+1) 1 : ((+1) 3 : ((+1) 5 : (8 : []))) 92 | (+1) 1 : ((+1) 3 : ((+1) 5 : [8])) 93 | (+1) 1 : ((+1) 3 : (6 : [8] )) 94 | (+1) 1 : ((+1) 3 : [6, 8]) 95 | (+1) 1 : (4 : [6, 8]) 96 | (+1) 1 : [4, 6, 8] 97 | 2 : [4, 6, 8] 98 | [2, 4, 6, 8] 99 | 100 | map isDigit ['a', '1', 'b', '2'] 101 | isDigit 'a' : map isDigit ['1', 'b', '2'] 102 | isDigit 'a' : (isDigit '1' : map isDigit ['b', '2']) 103 | isDigit 'a' : (isDigit '1' : (isDigit 'b' : map isDigit ['2'])) 104 | isDigit 'a' : (isDigit '1' : (isDigit 'b' : (isDigit '2' : map isDigit []))) 105 | isDigit 'a' : (isDigit '1' : (isDigit 'b' : (isDigit '2' : []))) 106 | isDigit 'a' : (isDigit '1' : (isDigit 'b' : (True : []))) 107 | isDigit 'a' : (isDigit '1' : (isDigit 'b' : [True])) 108 | isDigit 'a' : (isDigit '1' : (False : [True])) 109 | isDigit 'a' : (isDigit '1' : [False, True]) 110 | isDigit 'a' : (True : [False, True]) 111 | isDigit 'a' : [True, False, True] 112 | False : [True, False, True] 113 | [False, True, False, True] 114 | 115 | map reverse ["abc", "def", "ghi"] 116 | reverse "abc" : map reverse ["def", "ghi"] 117 | reverse "abc" : (reverse "def" : map reverse ["ghi"]) 118 | reverse "abc" : (reverse "def" : (reverse "ghi" : map reverse [])) 119 | reverse "abc" : (reverse "def" : (reverse "ghi" : [])) 120 | reverse "abc" : (reverse "def" : ("ihg" : [])) 121 | reverse "abc" : (reverse "def" : ["ihg"]) 122 | reverse "abc" : ("fed" : ["ihg"]) 123 | reverse "abc" : ["fed", "ihg"] 124 | "cba" : ["fed", "ihg"] 125 | ["cba", "fed", "ihg"] 126 | 127 | -} 128 | 129 | -- The filter function 130 | 131 | filter :: (a -> Bool) -> [a] -> [a] 132 | filter f xs = [x | x <- xs, f x] 133 | 134 | filter' :: (a -> Bool) -> [a] -> [a] 135 | filter' _ [] = [] 136 | filter' f (x : xs) | f x = x : filter' f xs 137 | | otherwise = filter' f xs 138 | 139 | {- 140 | 141 | filter even [1..10] 142 | filter even [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 143 | filter even [2, 3, 4, 5, 6, 7, 8, 9, 10] 144 | 2 : filter even [3, 4, 5, 6, 7, 8, 9, 10] 145 | 2 : filter even [4, 5, 6, 7, 8, 9, 10] 146 | 2 : (4 : filter even [5, 6, 7, 8, 9, 10]) 147 | 2 : (4 : filter even [6, 7, 8, 9, 10]) 148 | 2 : (4 : (6 : filter even [7, 8, 9, 10])) 149 | 2 : (4 : (6 : filter even [8, 9, 10])) 150 | 2 : (4 : (6 : (8 : filter even [9, 10]))) 151 | 2 : (4 : (6 : (8 : filter even [10]))) 152 | 2 : (4 : (6 : (8 : (10 : filter even [])))) 153 | 2 : (4 : (6 : (8 : (10 : [])))) 154 | 2 : (4 : (6 : (8 : [10]))) 155 | 2 : (4 : (6 : [8, 10])) 156 | 2 : (4 : [6, 8, 10]) 157 | 2 : [4, 6, 8, 10] 158 | [2, 4, 6, 8, 10] 159 | 160 | filter (>5) [1..10] 161 | filter (>5) [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 162 | filter (>5) [2, 3, 4, 5, 6, 7, 8, 9, 10] 163 | filter (>5) [3, 4, 5, 6, 7, 8, 9, 10] 164 | filter (>5) [4, 5, 6, 7, 8, 9, 10] 165 | filter (>5) [5, 6, 7, 8, 9, 10] 166 | filter (>5) [6, 7, 8, 9, 10] 167 | 6 : filter (>5) [7, 8, 9, 10] 168 | 6 : (7 : filter (>5) [8, 9, 10]) 169 | 6 : (7 : (8 : filter (>5) [9, 10])) 170 | 6 : (7 : (8 : (9 : filter (>5) [10]))) 171 | 6 : (7 : (8 : (9 : (10 : filter (>5) [])))) 172 | 6 : (7 : (8 : (9 : (10 : [])))) 173 | 6 : (7 : (8 : (9 : [10]))) 174 | 6 : (7 : (8 : [9, 10])) 175 | 6 : (7 : [8, 9, 10]) 176 | 6 : [7, 8, 9, 10] 177 | [6, 7, 8, 9, 10] 178 | 179 | filter (/= ' ') "abc def ghi" 180 | 'a' : filter (/= ' ') "bc def ghi" 181 | 'a' : ('b' : filter (/= ' ') "c def ghi") 182 | 'a' : ('b' : ('c' : filter (/= ' ') " def ghi")) 183 | 'a' : ('b' : ('c' : filter (/= ' ') "def ghi")) 184 | 'a' : ('b' : ('c' : ('d' : filter (/= ' ') "ef ghi"))) 185 | 'a' : ('b' : ('c' : ('d' : ('e' : filter (/= ' ') "f ghi")))) 186 | 'a' : ('b' : ('c' : ('d' : ('e' : ('f' : filter (/= ' ') " ghi"))))) 187 | 'a' : ('b' : ('c' : ('d' : ('e' : ('f' : filter (/= ' ') "ghi"))))) 188 | 'a' : ('b' : ('c' : ('d' : ('e' : ('f' : ('g' : filter (\= ' ') "hi")))))) 189 | 'a' : ('b' : ('c' : ('d' : ('e' : ('f' : ('g' : ('h' : filter (/= ' ') "i"))))))) 190 | 'a' : ('b' : ('c' : ('d' : ('e' : ('f' : ('g' : ('h' : ('i' : filter (/= ' ') [])))))))) 191 | 'a' : ('b' : ('c' : ('d' : ('e' : ('f' : ('g' : ('h' : ('i' : [])))))))) 192 | 'a' : ('b' : ('c' : ('d' : ('e' : ('f' : ('g' : ('h' : ['i']))))))) 193 | 'a' : ('b' : ('c' : ('d' : ('e' : ('f' : ('g' : ['h', 'i'])))))) 194 | 'a' : ('b' : ('c' : ('d' : ('e' : ('f' : ['g', 'h', 'i']))))) 195 | 'a' : ('b' : ('c' : ('d' : ('e' : ['f', 'g', 'h', 'i'])))) 196 | 'a' : ('b' : ('c' : ('d' : ['e', 'f', 'g', 'h', 'i']))) 197 | 'a' : ('b' : ('c' : ['d', 'e', 'f', 'g', 'h', 'i'])) 198 | 'a' : ('b' : ['c', 'd', 'e', 'f', 'g', 'h', 'i']) 199 | 'a' : ['b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'] 200 | ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'] 201 | "abcdefghi" 202 | 203 | -} 204 | 205 | -- The foldr function 206 | 207 | length :: [Int] -> Int 208 | length [] = 0 209 | length (x : xs) = 1 + length xs 210 | 211 | sum :: [Int] -> Int 212 | sum [] = 0 213 | sum (x : xs) = x + sum xs 214 | 215 | product :: [Int] -> Int 216 | product [] = 1 217 | product (x : xs) = x * product xs 218 | 219 | or :: [Bool] -> Bool 220 | or [] = False 221 | or (x : xs) = x || or xs 222 | 223 | and :: [Bool] -> Bool 224 | and [] = True 225 | and (x : xs) = x && and xs 226 | 227 | reverse :: [a] -> [a] 228 | reverse [] = [] 229 | reverse (x : xs) = reverse xs ++ [x] 230 | 231 | {- 232 | 233 | The pattern 234 | 235 | f [] = v 236 | f (x : xs) = x [*] f xs 237 | 238 | -} 239 | 240 | foldr :: (a -> b -> b) -> b -> [a] -> b 241 | foldr _ v [] = v 242 | foldr f v (x : xs) = f x (foldr f v xs) 243 | 244 | 245 | 246 | add1ToSeed :: a -> Int -> Int 247 | add1ToSeed _ s = 1 + s 248 | 249 | length' :: [a] -> Int 250 | length' = foldr add1ToSeed 0 251 | 252 | {- 253 | 254 | length [1, 2, 3] 255 | foldr add1ToSeed 0 [1, 2, 3] 256 | add1ToSeed 1 (foldr add1ToSeed 0 [2, 3]) 257 | add1ToSeed 1 (add1ToSeed 2 (foldr add1ToSeed 0 [3])) 258 | add1ToSeed 1 (add1ToSeed 2 (add1ToSeed 3 (foldr add1ToSeed 0 []))) 259 | add1ToSeed 1 (add1ToSeed 2 (add1ToSeed 3 0)) 260 | add1ToSeed 1 (add1ToSeed 2 (1 + 0)) 261 | add1ToSeed 1 (add1ToSeed 2 1) 262 | add1ToSeed 1 (1 + 1) 263 | add1ToSeed 1 2 264 | 1 + 2 265 | 3 266 | 267 | -} 268 | 269 | sum' :: [Int] -> Int 270 | sum' = foldr (+) 0 271 | 272 | {- 273 | 274 | sum [1, 2, 3] 275 | foldr (+) 0 [1, 2, 3] 276 | (+) 1 (foldr (+) 0 [2, 3]) 277 | (+) 1 ((+) 2 (foldr (+) 0 [3])) 278 | (+) 1 ((+) 2 ((+) 3 (foldr (+) 0 []))) 279 | (+) 1 ((+) 2 ((+) 3 0)) 280 | 1 + (2 + (3 + 0)) 281 | 1 + (2 + 3) 282 | 1 + 5 283 | 6 284 | 285 | -} 286 | 287 | product' :: [Int] -> Int 288 | product' = foldr (*) 1 289 | 290 | {- 291 | 292 | product [1, 2, 3] 293 | foldr (*) 1 [1, 2, 3] 294 | (*) 1 (foldr (*) 1 [2, 3]) 295 | (*) 1 ((*) 2 (foldr (*) 1 [3])) 296 | (*) 1 ((*) 2 ((*) 3 (foldr (*) 1 []))) 297 | (*) 1 ((*) 2 ((*) 3 1)) 298 | 1 * (2 * (3 * 1)) 299 | 1 * (2 * 3) 300 | 1 * 6 301 | 6 302 | 303 | -} 304 | 305 | or' :: [Bool] -> Bool 306 | or' = foldr (||) False 307 | 308 | {- 309 | 310 | or [True, False, True] 311 | foldr (||) False [True, False, True] 312 | (||) True (foldr (||) False [False, True]) 313 | (||) True ((||) False (foldr (||) False [True])) 314 | (||) True ((||) False ((||) True (foldr (||) False []))) 315 | (||) True ((||) False ((||) True False)) 316 | True || (False || (True || False)) 317 | True || (False || True) 318 | True || True 319 | True 320 | 321 | -} 322 | 323 | and' :: [Bool] -> Bool 324 | and' = foldr (&&) True 325 | 326 | {- 327 | 328 | and [True, False, True] 329 | foldr (&&) True [True, False, True] 330 | (&&) True (foldr (&&) True [False, True]) 331 | (&&) True ((&&) False (foldr (&&) True [True])) 332 | (&&) True ((&&) False ((&&) True (foldr (&&) True []))) 333 | (&&) True ((&&) False ((&&) True True)) 334 | True && (False && (True && True)) 335 | True && (False && True) 336 | True && False 337 | False 338 | 339 | -} 340 | 341 | snoc :: a -> [a] -> [a] 342 | snoc i s = s ++ [i] 343 | 344 | reverse' :: [a] -> [a] 345 | reverse' = foldr snoc [] 346 | 347 | {- 348 | 349 | reverse [1, 2, 3] 350 | foldr snoc [] [1, 2, 3] 351 | snoc 1 (foldr snoc [] [2, 3]) 352 | snoc 1 (snoc 2 (foldr snoc [] [3])) 353 | snoc 1 (snoc 2 (snoc 3 (foldr snoc [] []))) 354 | snoc 1 (snoc 2 (snoc 3 [])) 355 | snoc 1 (snoc 2 ([] ++ [3])) 356 | snoc 1 (snoc 2 [3]) 357 | snoc 1 ([3] ++ [2]) 358 | snoc 1 [3, 2] 359 | [3, 2] ++ [1] 360 | [3, 2, 1] 361 | 362 | -} 363 | 364 | -- The foldl function 365 | 366 | length'' :: [a] -> Int 367 | length'' = length_ 0 368 | where length_ v [] = v 369 | length_ v (x : xs) = length_ (v + 1) xs 370 | 371 | {- 372 | 373 | length [1, 2, 3] 374 | length_ 0 [1, 2, 3] 375 | length_ (0 + 1) [2, 3] 376 | length_ ((0 + 1) + 1) [3] 377 | length_ (((0 + 1) + 1) + 1) [] 378 | (((0 + 1) + 1) + 1) 379 | ((1 + 1) + 1) 380 | (2 + 1) 381 | 3 382 | 383 | -} 384 | 385 | sum'' :: [Int] -> Int 386 | sum'' = sum_ 0 387 | where sum_ v [] = v 388 | sum_ v (x : xs) = sum_ (v + x) xs 389 | 390 | {- 391 | 392 | sum [1, 2, 3] 393 | sum_ (0 + 1) [2, 3] 394 | sum_ ((0 + 1) + 2) [3] 395 | sum_ (((0 + 1) + 2) + 3) [] 396 | (((0 + 1) + 2) + 3) 397 | ((1 + 2) + 3) 398 | (3 + 3) 399 | 6 400 | 401 | -} 402 | 403 | product'' :: [Int] -> Int 404 | product'' = product_ 1 405 | where product_ v [] = v 406 | product_ v (x : xs) = product_ (v * x) xs 407 | 408 | {- 409 | 410 | product [1, 2, 3] 411 | product_ (1 * 1) [2, 3] 412 | product_ ((1 * 1) * 2) [3] 413 | product_ (((1 * 1) * 2) * 3) [] 414 | (((1 * 1) * 2) * 3) 415 | ((1 * 2) * 3) 416 | (2 * 3) 417 | 6 418 | 419 | -} 420 | 421 | or'' :: [Bool] -> Bool 422 | or'' = or_ False 423 | where or_ v [] = v 424 | or_ v (x : xs) = or_ (v || x) xs 425 | 426 | {- 427 | 428 | or [True, False, True] 429 | or_ (False || True) [False, True] 430 | or_ ((False || True) || False) [True] 431 | or_ (((False || True) || False) || True) [] 432 | (((False || True) || False) || True) 433 | ((True || False) || True) 434 | (True || True) 435 | True 436 | 437 | -} 438 | 439 | and'' :: [Bool] -> Bool 440 | and'' = and_ True 441 | where and_ v [] = v 442 | and_ v (x : xs) = and_ (v && x) xs 443 | 444 | {- 445 | 446 | and [True, False, True] 447 | and_ (True && True) [False, True] 448 | and_ ((True && True) && False) [True] 449 | and_ (((True && True) && False) && True) [] 450 | (((True && True) && False) && True) 451 | ((True && False) && True) 452 | (False && True) 453 | False 454 | 455 | -} 456 | 457 | reverse'' :: [a] -> [a] 458 | reverse'' = rev_ [] 459 | where rev_ v [] = v 460 | rev_ v (x : xs) = rev_ ([x] ++ v) xs 461 | 462 | {- 463 | 464 | reverse [1, 2, 3] 465 | rev_ ([1] ++ []) [2, 3] 466 | rev_ ([2] ++ ([1] ++ [])) [3] 467 | rev_ ([3] ++ ([2] ++ ([1] ++ []))) [] 468 | ([3] ++ ([2] ++ ([1] ++ []))) 469 | ([3] ++ ([2] ++ [1])) 470 | ([3] ++ [2, 1]) 471 | [3, 2, 1] 472 | 473 | -} 474 | 475 | {- 476 | 477 | The pattern 478 | 479 | f v [] = v 480 | f v (x : xs) = f (v [*] x) xs 481 | 482 | -} 483 | 484 | foldl :: (a -> b -> a) -> a -> [b] -> a 485 | foldl _ v [] = v 486 | foldl f v (x : xs) = foldl f (f v x) xs 487 | 488 | length''' :: [a] -> Int 489 | length''' = foldl (\ s _ -> 1 + s) 0 490 | 491 | sum''' :: [Int] -> Int 492 | sum''' = foldl (+) 0 493 | 494 | product''' :: [Int] -> Int 495 | product''' = foldl (*) 1 496 | 497 | or''' :: [Bool] -> Bool 498 | or''' = foldl (||) False 499 | 500 | and''' :: [Bool] -> Bool 501 | and''' = foldl (&&) True 502 | 503 | reverse''' :: [a] -> [a] 504 | reverse''' = foldl (\ s i -> [i] ++ s) [] 505 | 506 | {- 507 | 508 | The composition operator 509 | 510 | -} 511 | 512 | (.) :: (b -> c) -> (a -> b) -> (a -> c) 513 | f . g = \ x -> f (g x) 514 | 515 | {- 516 | 517 | function compose(f, g) { 518 | return function(x) { 519 | return f(g(x)); 520 | }; 521 | } 522 | 523 | -} 524 | 525 | notNull :: [a] -> Bool 526 | notNull = not . null 527 | 528 | odd :: Int -> Bool 529 | odd = not . even 530 | 531 | twice' :: (a -> a) -> a -> a 532 | twice' f = f . f 533 | 534 | sumSqrEven :: [Int] -> Int 535 | sumSqrEven = sum . map (^2) . filter even 536 | -------------------------------------------------------------------------------- /Chapter7Ex.hs: -------------------------------------------------------------------------------- 1 | module Chapter7Ex where 2 | 3 | {- 4 | 5 | 1. Show how the list comprehension [ f x | x <- xs, p x ] can be re-expressed 6 | using the higher-order functions map and filter. 7 | 8 | 2. Without looking at the definitions from the standard prelude, define the 9 | higher-order functions all , any , takeWhile , and dropWhile . 10 | 11 | 3. Redefine the functions map f and filter p using foldr . 12 | 13 | 4. Using foldl , define a function dec2int :: [ Int ] -> Int that converts a decimal 14 | number into an integer. For example: 15 | > dec2int [2, 3, 4, 5] 16 | 2345 17 | 18 | 5. Explain why the following definition is invalid: 19 | sumsqreven = compose [sum, map (^2), filter even ] 20 | 21 | -} 22 | 23 | compose :: [a -> a] -> (a -> a) 24 | compose = foldr (.) id 25 | -------------------------------------------------------------------------------- /Chapter9.hs: -------------------------------------------------------------------------------- 1 | module Chapter9 where 2 | 3 | {- 4 | 5 | Interactive Programs (IO monad) 6 | 7 | to interact with the outside world (with side effects) 8 | 9 | In the early days, Haskell cant deal with IO 10 | 11 | Input --> Program --> Output 12 | 13 | getChar :: IO Char 14 | 15 | putChar :: Char -> IO () 16 | 17 | return :: a -> IO a 18 | 19 | getLine :: IO String 20 | getLine = do x <- getChar 21 | if x == '\n' 22 | then return [] 23 | else do xs <- getLine 24 | return (x : xs) 25 | 26 | putStr :: String -> IO () 27 | putStr [] = return () 28 | putStr (x : xs) = do putChar x 29 | putStr xs 30 | 31 | putStrLn :: String -> IO () 32 | putStrLn xs = do putStr x 33 | putChar '\n' 34 | 35 | -} 36 | 37 | strLen :: IO () 38 | strLen = do putStr "Enter a string: " 39 | xs <- getLine 40 | putStrLn ("The string has " ++ (show (length xs)) ++ " characters") 41 | 42 | strLen' :: IO () 43 | strLen' = putStr "Enter a string: " >>= 44 | (\ _ -> getLine >>= 45 | (\ xs -> putStrLn ("The string has " ++ (show (length xs)) ++ " characters"))) 46 | -------------------------------------------------------------------------------- /CountdownProblem.hs: -------------------------------------------------------------------------------- 1 | module CountdownProblem where 2 | 3 | import Data.List 4 | 5 | {- 6 | 7 | Countdown is a popular quiz programme that has been running on British 8 | television since 1982, and includes a numbers game that we shall refer to as 9 | the countdown problem. The essence of the problem is as follows: 10 | 11 | Given a sequence of numbers and a target number, attempt to construct an 12 | expression whose value is the target, by combining one or more numbers from the 13 | sequence using addition, subtraction, multiplication, division. 14 | 15 | Example 16 | 17 | Using a list of numbers 18 | 19 | [1, 3, 7, 10, 25, 50] 20 | 21 | and four basic math operations 22 | 23 | * / + - 24 | 25 | construct an expression whose value is 765 26 | 27 | Rules 28 | 29 | All numbers, including intermediate results must be positive integers 30 | 31 | Each number from the list can only be used once 32 | 33 | -} 34 | 35 | data Op = Add | Sub | Mul | Div 36 | deriving Show 37 | 38 | data Expr = Val Int | App Op Expr Expr 39 | deriving Show 40 | 41 | applyOp :: Op -> Int -> Int -> Int 42 | applyOp Add x y = x + y 43 | applyOp Sub x y = x - y 44 | applyOp Mul x y = x * y 45 | applyOp Div x y = x `div` y 46 | 47 | isValid :: Op -> Int -> Int -> Bool 48 | isValid Add _ _ = True 49 | isValid Sub x y = x > y 50 | isValid Mul _ _ = True 51 | isValid Div x y = x `mod` y == 0 52 | 53 | evalExpr :: Expr -> [Int] 54 | evalExpr (Val n) = [n | n > 0] 55 | evalExpr (App o e1 e2) = [applyOp o x y | x <- evalExpr e1 56 | , y <- evalExpr e2 57 | , isValid o x y] 58 | 59 | getChoices :: [Int] -> [[Int]] 60 | getChoices ns = nub $ subsequences ns ++ permutations ns 61 | 62 | getValues :: Expr -> [Int] 63 | getValues (Val n) = [n] 64 | getValues (App _ e1 e2) = getValues e1 ++ getValues e2 65 | 66 | isSolution :: Expr -> [Int] -> Int -> Bool 67 | isSolution e ns t = getValues e `elem` getChoices ns && evalExpr e == [t] 68 | 69 | split :: [Int] -> [([Int], [Int])] 70 | split ns = [splitAt len ns | len <- [1.. (length ns - 1)]] 71 | 72 | combineExprs :: Expr -> Expr -> [Expr] 73 | combineExprs e1 e2 = [App o e1 e2 | o <- [Add, Sub, Mul, Div]] 74 | 75 | getExprs :: [Int] -> [Expr] 76 | getExprs [] = [] 77 | getExprs [n] = [Val n] 78 | getExprs ns = [e | (f, s) <- split ns 79 | , l <- getExprs f 80 | , r <- getExprs s 81 | , e <- combineExprs l r] 82 | 83 | getSolutions :: [Int] -> Int -> [Expr] 84 | getSolutions ns t = [e | ns' <- getChoices ns 85 | , e <- getExprs ns' 86 | , evalExpr e == [t]] 87 | 88 | -- 89 | 90 | type Result = (Expr, Int) 91 | 92 | getResults :: [Int] -> [Result] 93 | getResults ns = [(e, t) | e <- getExprs ns 94 | , t <- evalExpr e] 95 | 96 | combineResults :: Result -> Result -> [Result] 97 | combineResults (e1, t1) (e2, t2) = [(App o e1 e2, applyOp o t1 t2) 98 | | o <- [Add, Sub, Mul, Div] 99 | , isValid o t1 t2] 100 | 101 | getResults' :: [Int] -> [Result] 102 | getResults' [] = [] 103 | getResults' [n] = [(Val n, n) | n > 0] 104 | getResults' ns = [res | (f, s) <- split ns 105 | , r1 <- getResults' f 106 | , r2 <- getResults' s 107 | , res <- combineResults r1 r2] 108 | 109 | getSolutions' :: [Int] -> Int -> [Expr] 110 | getSolutions' ns t = [e | ns' <- getChoices ns 111 | , (e, t') <- getResults' ns' 112 | , t == t'] 113 | 114 | -- 115 | 116 | isValid' :: Op -> Int -> Int -> Bool 117 | isValid' Add x y = x <= y 118 | isValid' Sub x y = x > y 119 | isValid' Mul x y = x <= y && x /= 1 && y /= 1 120 | isValid' Div x y = x `mod` y == 0 && y /= 1 121 | 122 | combineResults' :: Result -> Result -> [Result] 123 | combineResults' (e1, t1) (e2, t2) = [(App o e1 e2, applyOp o t1 t2) 124 | | o <- [Add, Sub, Mul, Div] 125 | , isValid' o t1 t2] 126 | 127 | getResults'' :: [Int] -> [Result] 128 | getResults'' [] = [] 129 | getResults'' [n] = [(Val n, n) | n > 0] 130 | getResults'' ns = [res | (f, s) <- split ns 131 | , r1 <- getResults'' f 132 | , r2 <- getResults'' s 133 | , res <- combineResults' r1 r2] 134 | 135 | getSolutions'' :: [Int] -> Int -> [Expr] 136 | getSolutions'' ns t = [e | ns' <- getChoices ns 137 | , (e, t') <- getResults'' ns' 138 | , t == t'] 139 | -------------------------------------------------------------------------------- /CreditCardValidator.hs: -------------------------------------------------------------------------------- 1 | module CreditCardValidator where 2 | 3 | -- Ex1 4 | 5 | lastDigit :: Integer -> Integer 6 | lastDigit n | n > 0 = last $ toDigits n 7 | | otherwise = 0 8 | 9 | dropLastDigit :: Integer -> Integer 10 | dropLastDigit n | n >= 10 = read $ 11 | init $ 12 | foldr ((++) . show) "" $ 13 | toDigits n 14 | | otherwise = 0 15 | 16 | -- Ex2 17 | 18 | toDigits :: Integer -> [Integer] 19 | toDigits n | n >= 0 = map (\ x -> read [x] :: Integer) $ show n 20 | | otherwise = error "less than zero" 21 | 22 | toDigitsRev :: Integer -> [Integer] 23 | toDigitsRev n | n >= 0 = reverse $ toDigits n 24 | | otherwise = error "less than zero" 25 | 26 | -- Ex3 27 | 28 | doubleEveryOther :: [Integer] -> [Integer] 29 | doubleEveryOther ns = reverse $ 30 | map (\ (f, s) -> if even f then s * 2 else s) $ 31 | zip [1..(length ns)] (reverse ns) 32 | 33 | doubleEveryOther' :: [Integer] -> [Integer] 34 | doubleEveryOther' ns = map (\ (f, s) -> if even f then s * 2 else s) $ 35 | zip [1..(length ns)] ns 36 | 37 | -- Ex4 38 | 39 | sumDigits :: [Integer] -> Integer 40 | sumDigits [] = 0 41 | sumDigits [x] | x > 9 = sumDigits $ toDigits x 42 | | otherwise = x 43 | sumDigits ns = foldr (\ x acc -> acc + sumDigits (toDigits x)) 0 ns 44 | 45 | -- Ex5 46 | 47 | validate :: Integer -> Bool 48 | validate n = sumDigits (doubleEveryOther $ toDigits n) `mod` 10 == 0 49 | 50 | validate' :: Integer -> Bool 51 | validate' n | n >= 0 = sumDigits (doubleEveryOther' $ toDigitsRev n) `mod` 10 == 0 52 | | otherwise = error "less than zero" 53 | 54 | numValid :: [Integer] -> Integer 55 | numValid xs = sum . map (\ _ -> 1) $ filter validate' xs 56 | 57 | 58 | creditcards :: [Integer] 59 | creditcards = [ 4716347184862961, 60 | 4532899082537349, 61 | 4485429517622493, 62 | 4320635998241421, 63 | 4929778869082405, 64 | 5256283618614517, 65 | 5507514403575522, 66 | 5191806267524120, 67 | 5396452857080331, 68 | 5567798501168013, 69 | 6011798764103720, 70 | 6011970953092861, 71 | 6011486447384806, 72 | 6011337752144550, 73 | 6011442159205994, 74 | 4916188093226163, 75 | 4916699537435624, 76 | 4024607115319476, 77 | 4556945538735693, 78 | 4532818294886666, 79 | 5349308918130507, 80 | 5156469512589415, 81 | 5210896944802939, 82 | 5442782486960998, 83 | 5385907818416901, 84 | 6011920409800508, 85 | 6011978316213975, 86 | 6011221666280064, 87 | 6011285399268094, 88 | 6011111757787451, 89 | 4024007106747875, 90 | 4916148692391990, 91 | 4916918116659358, 92 | 4024007109091313, 93 | 4716815014741522, 94 | 5370975221279675, 95 | 5586822747605880, 96 | 5446122675080587, 97 | 5361718970369004, 98 | 5543878863367027, 99 | 6011996932510178, 100 | 6011475323876084, 101 | 6011358905586117, 102 | 6011672107152563, 103 | 6011660634944997, 104 | 4532917110736356, 105 | 4485548499291791, 106 | 4532098581822262, 107 | 4018626753711468, 108 | 4454290525773941, 109 | 5593710059099297, 110 | 5275213041261476, 111 | 5244162726358685, 112 | 5583726743957726, 113 | 5108718020905086, 114 | 6011887079002610, 115 | 6011119104045333, 116 | 6011296087222376, 117 | 6011183539053619, 118 | 6011067418196187, 119 | 4532462702719400, 120 | 4420029044272063, 121 | 4716494048062261, 122 | 4916853817750471, 123 | 4327554795485824, 124 | 5138477489321723, 125 | 5452898762612993, 126 | 5246310677063212, 127 | 5211257116158320, 128 | 5230793016257272, 129 | 6011265295282522, 130 | 6011034443437754, 131 | 6011582769987164, 132 | 6011821695998586, 133 | 6011420220198992, 134 | 4716625186530516, 135 | 4485290399115271, 136 | 4556449305907296, 137 | 4532036228186543, 138 | 4916950537496300, 139 | 5188481717181072, 140 | 5535021441100707, 141 | 5331217916806887, 142 | 5212754109160056, 143 | 5580039541241472, 144 | 6011450326200252, 145 | 6011141461689343, 146 | 6011886911067144, 147 | 6011835735645726, 148 | 6011063209139742, 149 | 379517444387209, 150 | 377250784667541, 151 | 347171902952673, 152 | 379852678889749, 153 | 345449316207827, 154 | 349968440887576, 155 | 347727987370269, 156 | 370147776002793, 157 | 374465794689268, 158 | 340860752032008, 159 | 349569393937707, 160 | 379610201376008, 161 | 346590844560212, 162 | 376638943222680, 163 | 378753384029375, 164 | 348159548355291, 165 | 345714137642682, 166 | 347556554119626, 167 | 370919740116903, 168 | 375059255910682, 169 | 373129538038460, 170 | 346734548488728, 171 | 370697814213115, 172 | 377968192654740, 173 | 379127496780069, 174 | 375213257576161, 175 | 379055805946370, 176 | 345835454524671, 177 | 377851536227201, 178 | 345763240913232 179 | ] 180 | -------------------------------------------------------------------------------- /Hangman.hs: -------------------------------------------------------------------------------- 1 | module Hangman where 2 | 3 | import System.Random 4 | 5 | main :: IO () 6 | main = do runGame "batman" 5 7 | 8 | runGame :: String -> Int -> IO () 9 | runGame wtg n | n > 0 = do putStrLn "Guess the word: " 10 | gw <- getLine 11 | if wtg == gw 12 | then putStrLn "You guessed it right!!! :D" 13 | else do putStrLn "You guessed it wrong... :(" 14 | runGame wtg (n - 1) 15 | | otherwise = putStrLn "GAME OVER..." 16 | -------------------------------------------------------------------------------- /Monads.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE NoImplicitPrelude #-} 2 | 3 | module Monads where 4 | 5 | import Prelude (Int, Show, String) 6 | 7 | {- 8 | 9 | Monads 10 | 11 | - A monad is a way to structure computations in terms of values and sequences of computations using those values. Monads allow the programmer to build up computations using sequential building blocks, which can themselves be sequences of computations. 12 | 13 | - its just another design pattern 14 | 15 | 16 | 17 | It basically follows these 3 functions 18 | 19 | return :: Monad m => a -> m a 20 | bind :: Monad m => m a -> (a -> m b) -> m b 21 | -- the other function is the one passed to bind 22 | 23 | It must abide by these 3 laws 24 | 25 | Left identity 26 | 27 | Right Identity 28 | 29 | Associativity 30 | 31 | -} 32 | 33 | class Monad m where 34 | return :: a -> m a 35 | bind :: m a -> (a -> m b) -> m b 36 | 37 | -- Identity Monad 38 | 39 | data Id a = Id a 40 | deriving Show 41 | 42 | instance Monad Id where 43 | return x = Id x 44 | (Id x) `bind` f = f x 45 | 46 | -- Maybe Monad 47 | 48 | data Maybe a = Nothing | Just a 49 | deriving Show 50 | 51 | instance Monad Maybe where 52 | return x = Just x 53 | (Just x) `bind` f = f x 54 | Nothing `bind` _ = Nothing 55 | 56 | -- Either Monad 57 | 58 | data Either a b = Left a | Right b 59 | deriving Show 60 | 61 | instance Monad (Either a) where 62 | return x = Right x 63 | (Right x) `bind` f = f x 64 | (Left x) `bind` _ = Left x 65 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #programming-in-haskell 2 | 3 | ##Programming in Haskell by Graham Hutton 4 | 5 | ###Based on the book, FP Lectures on Channel 9 and FP course on edX.org 6 | -------------------------------------------------------------------------------- /Scratch.hs: -------------------------------------------------------------------------------- 1 | module Scratch where 2 | 3 | import Prelude hiding ((&&), (||)) 4 | 5 | f :: (a -> a) -> a 6 | f g = undefined 7 | 8 | remove :: Int -> [a] -> [a] 9 | remove n xs = take n xs ++ drop (n + 1) xs 10 | 11 | funct :: Int -> [a] -> [a] 12 | funct x xs = take (x + 1) xs ++ drop x xs 13 | 14 | e3 x = x * 2 15 | 16 | e4 (x, y) = x 17 | 18 | e6 x y = x * y 19 | 20 | e10 (x, y) = [x, y] 21 | 22 | e11 :: (Char, Bool) 23 | e11 = ('\a', True) 24 | 25 | e13 :: Int -> Int -> Int 26 | e13 x y = x + y * y 27 | -------------------------------------------------------------------------------- /Setup.hs: -------------------------------------------------------------------------------- 1 | import Distribution.Simple 2 | main = defaultMain 3 | -------------------------------------------------------------------------------- /programming-in-haskell.cabal: -------------------------------------------------------------------------------- 1 | -- Initial programming-in-haskell.cabal generated by cabal init. For 2 | -- further documentation, see http://haskell.org/cabal/users-guide/ 3 | 4 | name: programming-in-haskell 5 | version: 0.1.0.0 6 | -- synopsis: 7 | -- description: 8 | -- license: 9 | license-file: LICENSE 10 | author: Michael Angelo Calimlim 11 | maintainer: macalimlim@gmail.com 12 | -- copyright: 13 | -- category: 14 | build-type: Simple 15 | -- extra-source-files: 16 | cabal-version: >=1.10 17 | 18 | library 19 | -- exposed-modules: 20 | -- other-modules: 21 | -- other-extensions: 22 | build-depends: base >=4.7 && <4.8 23 | -- hs-source-dirs: 24 | default-language: Haskell98 --------------------------------------------------------------------------------