-
-
Save amadiyawa/2b65a57554b21b24feb638dee5eb6573 to your computer and use it in GitHub Desktop.
Revisions
-
mikehaertl revised this gist
Aug 10, 2012 . No changes.There are no files selected for viewing
-
mikehaertl revised this gist
Aug 8, 2012 . 1 changed file with 15 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -892,6 +892,20 @@ f . g = \x -> f (g x) ```haskell map (\x -> negate (abs x)) [5,-3,-6,7,-3,2,-19,24] map (\xs -> negate (sum (tail xs))) [[1..5],[3..6],[1..7]] sum (replicate 5 (max 6.7 8.9)) replicate 100 (product (map (*3) (zipWith max [1,2,3,4,5] [4,5,6,7,8]))) -- same with function composition map (negate . abs) [5,-3,-6,7,-3,2,-19,24] map (negate . sum . tail) [[1..5],[3..6],[1..7]] sum . replicate 5 . max 6.7 $ 8.9 replicate 100 . product . map (*3) . zipWith max [1,2,3,4,5] $ [4,5,6,7,8] ``` * A common use case for function composition is defining function in so called *point free* style. It's when we write `sum' = foldl (+) 0` instead of `sum' xs = foldl (+) 0 xs` (omitting the `xs`). ```haskell fn x = ceiling (negate (tan (cos (max 50 x)))) -- in point free style fn = ceiling . negate . tan . cos . max 50 ``` -
mikehaertl revised this gist
Aug 8, 2012 . 1 changed file with 43 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -840,6 +840,8 @@ sum = foldl1 (+) reverse' :: [a] -> [a] reverse' = foldl (\acc x -> x : acc) [] -- alternative reverse' = foldl (flip (:)) [] product' :: (Num a) => [a] -> a product' = foldr1 (*) @@ -852,4 +854,44 @@ sum = foldl1 (+) last' :: [a] -> a last' = foldl1 (\_ x -> x) ``` * **scanl** and **scanr** are like `foldl` and `foldr` but they also give all intermediate results back ```haskell scanl (+) 0 [3,5,2,1] ([0,3,8,10,11]) scanr (+) 0 [3,5,2,1] ([11,8,3,1,0]) scanl1 (\acc x -> if x > acc then x else acc) [3,2,9,2,1] ([3,3,9,9,9]) scanl (flip (:)) [] [3,2,1] ([[],[3],[2,3],[1,2,3]]) ``` * *How many elements does it take for the sum of the roots of all natural numbers to exceed 1000?* ```haskell sqrtSums :: Int sqrtSums = length (takeWhile (<1000) (scanl1 (+) (map sqrt [1..]))) + 1 ``` * The **function application** function **$** looks like ```haskell ($) :: (a -> b) -> a -> b f $ x = f x ``` It has lowest precedencde and thus can often be used instead of parentheses: `sum $ map sqrt [1..130]` instead of `sum (map sqrt [1..130])` or `sum $ filter (> 10) $ map (*2) [2..10]` instead of `sum (filter (> 10) (map (*2) [2..10]))`. It also allows to map function application to a list of functions like `map ($ 3) [(4+), (10*), (^2), sqrt]`. * **Function composition** is done with the **.** function. If called with two functions `f` and `g` it returns a new function. This function is like calling `f` with argument `x` and then `g` with that result: `f( g(x) )`. ```haskell (.) :: (b -> c) -> (a -> b) -> a -> c f . g = \x -> f (g x) ``` ```haskell map (\x -> negate (abs x)) [5,-3,-6,7,-3,2,-19,24] -- with function composition map (negate . abs) [5,-3,-6,7,-3,2,-19,24] ``` -
mikehaertl revised this gist
Aug 8, 2012 . 1 changed file with 13 additions and 13 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -835,21 +835,21 @@ sum = foldl1 (+) * Fold examples ```haskell maximum' :: (Ord a) => [a] -> a maximum' = foldr1 (\x acc -> if x > acc then x else acc) reverse' :: [a] -> [a] reverse' = foldl (\acc x -> x : acc) [] product' :: (Num a) => [a] -> a product' = foldr1 (*) filter' :: (a -> Bool) -> [a] -> [a] filter' p = foldr (\x acc -> if p x then x : acc else acc) [] head' :: [a] -> a head' = foldr1 (\x _ -> x) last' :: [a] -> a last' = foldl1 (\_ x -> x) ``` -
mikehaertl revised this gist
Aug 8, 2012 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -837,7 +837,7 @@ sum = foldl1 (+) ```haskell maximum' :: (Ord a) => [a] -> a maximum' = foldr1 (\x acc -> if x > acc then x else acc) reverse' :: [a] -> [a] reverse' = foldl (\acc x -> x : acc) [] -
mikehaertl revised this gist
Aug 8, 2012 . 1 changed file with 39 additions and 3 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -796,9 +796,9 @@ separated parameters, and a `->` that points at the function body: Sometimes lambdas are used even if that is not neccessary, like `map (\x -> x + 3) [1,6,3,2]` instead of more readable `map (+3) [1,6,3,2]`. * **Folds** take a binary function a start value and a list as parameter. The binary function is called with the accumulator and the first (or last) element from the list and produces a new accumulator. Then it's called again with this new accumulator and the next list element. Whenever you want to traverse a list to return something, chances are you want a fold. * **foldl** or **left fold** folds up a list from the left side. ```haskell sum' :: (Num a) => [a] -> a @@ -812,8 +812,44 @@ sum' :: (Num a) => [a] -> a sum' = foldl (+) 0 ``` ```haskell elem' :: (Eq a) => a -> [a] -> Bool elem' y ys = foldl (\acc x -> if x == y then True else acc) False ys ``` * **foldr** does a **right fold**. Here the parameters to the binary function are flipped. ```haskell map' :: (a -> b) -> [a] -> [b] map' f xs = foldr (\x acc -> f x : acc) [] xs ``` We could also use `foldl` with the function `\acc x -> acc ++ [f x]`. But `++` is much more expensive than `:`. Right folds are usually used to build up lists. Right folds also work with infinite lists whereas left folds don't. * **foldl1** and **foldr1** work like `foldl` and `foldr` but use the first (or last) list element as starting value. They don't work with emtpy lists. ```haskell sum = foldl1 (+) ``` * Fold examples ```haskell maximum' :: (Ord a) => [a] -> a maximum' = foldr1 (\x acc -> if x > acc then x else acc) reverse' :: [a] -> [a] reverse' = foldl (\acc x -> x : acc) [] product' :: (Num a) => [a] -> a product' = foldr1 (*) filter' :: (a -> Bool) -> [a] -> [a] filter' p = foldr (\x acc -> if p x then x : acc else acc) [] head' :: [a] -> a head' = foldr1 (\x _ -> x) last' :: [a] -> a last' = foldl1 (\_ x -> x) ``` -
mikehaertl revised this gist
Aug 7, 2012 . 1 changed file with 25 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -789,7 +789,31 @@ separated parameters, and a `->` that points at the function body: zipWith (\a b -> (a * 30 + 3) / b) [5,4,3,2,1] [1,2,3,4,5] map (\(a,b) -> a + b) [(1,2),(3,5),(6,3),(2,6),(2,5)] flip' f = \x y -> f y x ``` Sometimes lambdas are used even if that is not neccessary, like `map (\x -> x + 3) [1,6,3,2]` instead of more readable `map (+3) [1,6,3,2]`. * **Folds** take a binary function a start value and a list as parameter. The binary function is called with the accumulator and the first (or last) element from the list and produces a new accumulator. Then it's called again with this new accumulator and the next list element. **foldl** or **left fold** folds up a list from the left side. ```haskell sum' :: (Num a) => [a] -> a sum' xs = foldl (\acc x -> acc + x) 0 xs ``` In the beginning the binary function is called with `acc` value `0` and the first list element. The lambda function `(\acc x -> acc + x)` is the same as `(+)` and we can omit `xs` because `foo a = bar b a` can be written as `foo = bar b`: ```haskell sum' :: (Num a) => [a] -> a sum' = foldl (+) 0 ``` ``` elem' :: (Eq a) => a -> [a] -> Bool elem' y ys = foldl (\acc x -> if x == y then True else acc) False ys ``` -
mikehaertl revised this gist
Aug 6, 2012 . 1 changed file with 0 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -789,7 +789,6 @@ separated parameters, and a `->` that points at the function body: zipWith (\a b -> (a * 30 + 3) / b) [5,4,3,2,1] [1,2,3,4,5] map (\(a,b) -> a + b) [(1,2),(3,5),(6,3),(2,6),(2,5)] ``` Sometimes lambdas are used even if that is not neccessary, like `map (\x -> x + 3) [1,6,3,2]` -
mikehaertl revised this gist
Aug 6, 2012 . 1 changed file with 4 additions and 4 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -783,12 +783,12 @@ sum (takeWhile (<10000) [n^2 | n <- [1..], odd (n^2)]) separated parameters, and a `->` that points at the function body: ```haskell numLongChains :: Int numLongChains = length (filter (\xs -> length xs > 15) (map chain [1..100])) zipWith (\a b -> (a * 30 + 3) / b) [5,4,3,2,1] [1,2,3,4,5] map (\(a,b) -> a + b) [(1,2),(3,5),(6,3),(2,6),(2,5)] ``` -
mikehaertl revised this gist
Aug 5, 2012 . 1 changed file with 17 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -777,4 +777,20 @@ sum (takeWhile (<10000) [n^2 | n <- [1..], odd (n^2)]) numLongChains :: Int numLongChains = length (filter isLong (map chain [1..100])) where isLong xs = length xs > 15 ``` * **Lambdas** are anonymous functions. They are defined with a `\`, followed by space separated parameters, and a `->` that points at the function body: ```haskell numLongChains :: Int numLongChains = length (filter (\xs -> length xs > 15) (map chain [1..100])) zipWith (\a b -> (a * 30 + 3) / b) [5,4,3,2,1] [1,2,3,4,5] map (\(a,b) -> a + b) [(1,2),(3,5),(6,3),(2,6),(2,5)] ``` Sometimes lambdas are used even if that is not neccessary, like `map (\x -> x + 3) [1,6,3,2]` instead of more readable `map (+3) [1,6,3,2]`. -
mikehaertl revised this gist
Aug 5, 2012 . 1 changed file with 27 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -751,3 +751,30 @@ let notNull x = not (null x) in filter notNull [[1,2,3],[],[2,2]] ([[1,2,3],[2 in smallerSorted ++ [x] ++ biggerSorted ``` * The **takeWhile** function takes a predicate function and a list. It returns elements from the list until the predicate becomes `False`. Sum of all odd squares that are smaller than `10000` ```haskell sum (takeWhile (<10000) (filter odd (map (^2) [1..]))) ``` Alternative with list comprehension ```haskell sum (takeWhile (<10000) [n^2 | n <- [1..], odd (n^2)]) ``` * Example: The Collatz sequence starts at any number. If the number is even, it's divided by `2`. If it is odd it is multiplied by `3` and `1` is added. In any case the chain continues at this new number until the sequence reaches `1`. Question: For all starting numbers between 1 and 100, how many chains have a length greater than 15? ```haskell chain :: (Integral a) => a -> [a] chain 1 = [1] chain n | even n = n:chain (n `div` 2) | odd n = n:chain (n*3 + 1) numLongChains :: Int numLongChains = length (filter isLong (map chain [1..100])) where isLong xs = length xs > 15 ``` -
mikehaertl revised this gist
Aug 5, 2012 . 1 changed file with 66 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -126,7 +126,7 @@ someString = "Some string" [20,19..15] ([20,19,18,17,16,15]) ``` * List related functions - `head [5,4,3]` : first element of a list (`5`) - `tail [5,4,3]` : tail without head (`[4,3]`) @@ -197,7 +197,7 @@ someString = "Some string" [("Johnny", "Walker", 38), ("Kate", "Middleton", 27)] ``` * Tuple related functions - `fst (8,11)` : returns first component of a pair (`8`) - `snd (9,"Hey")` : returns second component of a pair (`"Hey"`) @@ -686,4 +686,68 @@ zipWith' (+) [4,2,5,6] [2,6,2,3] ([6,8,7,9]) zipWith' max [6,3,2,1] [7,3,1,5] ([7,3,2,5]) zipWith' (++) ["foo ", "bar "] ["fighters", "hoppers"] (["foo fighters", "bar hoppers"]) zipWith' (*) (replicate 5 2) [1..] ([2,4,6,8,10]) zipWith' (zipWith'(*)) [ [1,2], [3,4] ] [ [2,3], [4,5] ] ([[2,6],[12,20]]) ``` * `flip` takes a function and returns a function where the first two parameters are flipped ```haskell flip' :: (a -> b -> c) -> (b -> a -> c) flip' f = g where g x y = f y x ``` Or even shorter ```haskell flip' :: (a -> b -> c) -> b -> a -> c flip' f y x = f x y ``` ```haskell zipWith (flip' div) [2,2..] [10,8,6,4,2] ( [5,4,3,2,1] ) ``` * The **map** function takes a function and a list and returns a list with the function applied to every element ```haskell map :: (a -> b) -> [a] -> [b] map _ [] = [] map f (x:xs) = f x : map f xs ``` ```haskell map (+3) [1,5,3,1,6] ([4,8,6,4,9]) map (++ "!") ["BIFF", "BANG"] (["BIFF!","BANG!"]) map (replicate 2) [3..6] ([[3,3],[4,4],[5,5],[6,6]]) map (map (^2)) [[1,2],[3,4,5]] ([[1,4],[9,16,25]]) map fst [(1,2),(3,5)] ([1,3]) ``` * The **filter** function takes a function that filters elements from a list ```haskell filter :: (a -> bool) -> [a] -> [a] filter _ [] = [] filter p (x:xs) | p x = x : filter p xs | otherwhise = filter p xs ``` ```haskell filter (>3) [1,5,3,6] ([5,6]) filter even [1..10] ([1,2,4,6,8,10]) let notNull x = not (null x) in filter notNull [[1,2,3],[],[2,2]] ([[1,2,3],[2,2]]) ``` Alternative quicksort implementation ```haskell quicksort :: (Ord a) => [a] -> [a] quicksort [] = [] quicksort (x:xs) = let smallerSorted = quicksort (filter (<=x) xs) biggerSorted = quicksort (filter (>x) xs) in smallerSorted ++ [x] ++ biggerSorted ``` -
mikehaertl revised this gist
Aug 4, 2012 . 1 changed file with 45 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -630,16 +630,60 @@ multWithEighteen = multTwoWithNine 2 multWithEighteen 10 (180) ``` A function that compares the argument with `100` could be written like: ```haskell compareWithHundred :: (Num a, Ord a) => a -> Ordering compareWithHundred x = compare 100 x ``` The part `compare 100` returns a function that takes a number and compares it with `100`. The above thus can be rewritten as ```haskell compareWithHundred :: (Num a, Ord a) => a -> Ordering compareWithHundred = compare 100 ``` * More examples ```haskell divideByTen :: (Floating a) => a -> a divideByTen = (/10) ``` ```haskell isUpperAlphanum :: Char -> Bool isUpperAlphanum = (`elem` ['A'..'Z']) ``` * The type declaration of functions that take functions look different ```haskell applyTwice :: (a -> a) -> a -> a applyTwice f x = f (f x) ``` ```haskell applyTwice (+3) 10 (13) applyTwice (++ " HAHA") "HEY" ("HEY HAHA HAHA") applyTwice ("HAHA " ++) "HEY" ("HAHA HAHA HEY") applyTwice (multThree 2 2) 9 (144) applyTwice (3:) [1] ([3,3,1]) ``` * `zipWith` takes a function and two lists and applies the function on each two items of both lists to get a new list ```haskell zipWith' :: (a -> b -> c) -> [a] -> [b] -> [c] zipWith' _ [] _ = [] zipWith' _ _ [] = [] zipWith' f (x:xs) (y:ys) = f x y : zipWith' f xs ys ``` ```haskell zipWith' (+) [4,2,5,6] [2,6,2,3] ([6,8,7,9]) zipWith' max [6,3,2,1] [7,3,1,5] ([7,3,2,5]) zipWith' (++) ["foo ", "bar "] ["fighters", "hoppers"] (["foo fighters", "bar hoppers"]) zipWith' (*) (replicate 5 2) [1..] ([2,4,6,8,10]) ``` -
mikehaertl revised this gist
Aug 4, 2012 . 1 changed file with 31 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -612,3 +612,34 @@ max :: (Ord a) => a -> (a -> a) ``` It takes an `a` and returns a function, which takes another `a` and returns an `a`. * If a function is callaed with not all parameters we get back a **partially applied** function. ```haskell multThree :: (Num a) => a -> a -> a -> a multThree x y z = x * y * z ``` When we do `multThree 3 5 9` it's actually `((multThree 3) 5) 9` or `multThree :: (Num a) => a -> (a -> (a -> a))`. First `multThree 3` is applied, which returns a function. This function takes a single argument and returns another function. This other function again takes a single argument and returns the parameter multiplied by `15`. This allows us to do things like ```haskell multTwoWithNine = multThree 9 multTwoWithNine 2 3 (54) multWithEighteen = multTwoWithNine 2 multWithEighteen 10 (180) ``` ```haskell compareWithHundred :: (Num a, Ord a) => a -> Ordering compareWithHundred x = compare 100 x ``` The part `compare 100` returns. It returns a function that takes a number and compares it with `100`. The above thus can be rewritten as ```haskell compareWithHundred :: (Num a, Ord a) => a -> Ordering compareWithHundred = compare 100 ``` -
mikehaertl revised this gist
Aug 4, 2012 . 1 changed file with 1 addition and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -609,5 +609,6 @@ be written in two equivalent ways: ```haskell max :: (Ord a) => a -> a -> a max :: (Ord a) => a -> (a -> a) ``` It takes an `a` and returns a function, which takes another `a` and returns an `a`. -
mikehaertl revised this gist
Aug 4, 2012 . 1 changed file with 10 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -266,7 +266,7 @@ from the declaration: * Related functions - ``5 `compare` 3`` : takes two `Ord` members of same type and returns a `Ordering` (`GT`) - `show 3` : takes a `Show` and returns a `String` (`"3"`) - `read "True"` : takes a `Read` and returns a `Read` (`True`) - `succ LT` : takes a `Enum` and returns next element (`GT`) @@ -602,3 +602,12 @@ These calls are equivalent: max 4 5 (max 4) 5 ``` * A space between two things ist simply **function application**. The type of `max` can be written in two equivalent ways: ```haskell max :: (Ord a) => a -> a -> a max :: (Ord a) => a -> (a -> a) It takes an `a` and returns a function, which takes another `a` and returns an `a`. -
mikehaertl revised this gist
Aug 4, 2012 . 1 changed file with 53 additions and 53 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -113,14 +113,14 @@ someString = "Some string" * List ranges are defined with `..`: ```haskell [1..20] ['a'..'z'] ``` * Ranges can define a step size ```haskell [2,4..20] ([2,4,6,8,10,12,16,18,20]) [3,6..20] ([3,6,9,12,15,18]) [20,19..15] ([20,19,18,17,16,15]) @@ -148,50 +148,50 @@ someString = "Some string" * **List comprehensions** are similar to mathematical equations ```haskell [x*2 | x <- [1..5]] ([2,4,6,8,10]) ``` * **Predicates** are conditions for list comprehensions ```haskell [x*2 | x <- [1..5], x*2 >= 5] ([6,8,10]) ``` * There can be more than one predicates ```haskell [ x | x <- [10..20], x /= 10, x /= 15, x /= 19] ``` * Comprehensions can be put inside a function ```haskell boomBangs xs = [if x < 10 then "BOOM!" else "BANG!" | x <- xs, odd x] ``` * Comprehensions can draw from several lists, which multiplies the lengths ```haskell [ x*y | x <- [2,3], y <- [3,4,5]] ([6,8,10,9,12,15]) ``` * `_` is a dummy placeholder for a unused value ```haskell length' xs = sum [1 | _ <- xs] ``` * List comprehensions can be nested ```haskell let xxs = [[1,2,3],[2,3,4],[4,5]] [ [x | x <- xs, even x] | xs <- xxs] ([[2],[2,4],[4]] ``` * **Tuples** can contain several types, but for the type of two Tuples to be the same, the number and types of their elements must match ```haskell (1,2) [(1,2), (3,2), (4,9)] [("Johnny", "Walker", 38), ("Kate", "Middleton", 27)] @@ -211,7 +211,7 @@ someString = "Some string" * Use `:t` to get a type of something ```haskell :t 'a' ('a' :: Char) :t "HELLO" ("HELLO" :: [Char]) :t (True, 'a') ( (True,'a') :: (Bool, Char) ) @@ -220,7 +220,7 @@ someString = "Some string" * All functions should use a **type declaration** with `::` ("has type of"). Multiple arguments are also separeted with `->` just like the type declaration itself. ```haskell removeUppercase :: [Char] -> [Char] removeUppercase :: String -> String (same as above) addThree :: Int -> Int -> Int -> Int @@ -241,7 +241,7 @@ Multiple arguments are also separeted with `->` just like the type declaration i * **Type variables** can be used in function declarations. They stand for a type. Without a class constraint they mean "any type" ```haskell :t head (head :: [a] -> a) :t fst (fst :: (a, b) -> a) ``` @@ -250,7 +250,7 @@ Without a class constraint they mean "any type" it implements that class' behavior. The `=>` symbol separates the **class constraint** from the declaration: ```haskell :t (==) ( (==) :: (Eq a) => a -> a -> Bool ) ``` @@ -277,7 +277,7 @@ from the declaration: * *Type annotations* define the type of ambiguous expressions ```haskell (read "5" :: Float) * 4 ``` @@ -289,44 +289,44 @@ from the declaration: matches a specified pattern. The first matching pattern is executed. There should always be a catch-all pattern at the end ```haskell lucky :: (Integral a) => a -> String lucky 7 = "LUCKY NUMBER SEVEN!" lucky x = "Sorry, you're out of luck, pal!" ``` ```haskell factorial :: (Integral a) => a -> a factorial 0 = 1 factorial n = n * factorial (n - 1) ``` ```haskell addVectors :: (Num a) => (a, a) -> (a, a) -> (a, a) addVectors (x1, y1) (x2, y2) = (x1 + x2, y1 + y2) ``` ```haskell head' :: [a] -> a head' [] = error "Can't call head on an empty list, dummy!" head' (x:_) = x ``` ```haskell tell :: (Show a) => [a] -> String tell [] = "The list is empty" tell (x:[]) = "The list has one element: " ++ show x tell (x:y:[]) = "The list has two elements: " ++ show x ++ " and " ++ show y tell (x:y:_) = "This list is long. The first two elements are: " ++ show x ++ " and " ++ show y ``` ```haskell length' :: (Num b) => [a] -> b length' [] = 0 length' (_:xs) = 1 + length' xs ``` ```haskell sum' :: (Num a) => [a] -> a sum' [] = 0 sum' (x:xs) = x + sum' xs @@ -335,7 +335,7 @@ be a catch-all pattern at the end * The **as pattern** is used to reference the "whole thing": Put a name followed by `@` in front of the pattern: ```haskell capital :: String -> String capital "" = "Empty string, whoops!" capital all@(x:xs) = "The first letter of " ++ all ++ " is " ++ [x] @@ -344,7 +344,7 @@ in front of the pattern: * **Guards** are similar to if statements and check for boolean conditions. There's no `=` after the function name: ```haskell bmiTell :: (RealFloat a) => a -> String bmiTell bmi | bmi <= 18.5 = "You're underweight, you emo, you!" @@ -358,7 +358,7 @@ evaluation falls through to the next pattern * Guards can have as many parameters as we want ```haskell bmiTell :: (RealFloat a) => a -> a -> String bmiTell weight height | weight / height ^ 2 <= 18.5 = "You're underweight, you emo, you!" @@ -367,14 +367,14 @@ evaluation falls through to the next pattern | otherwise = "You're a whale, congratulations!" ``` ```haskell max' :: (Ord a) => a -> a -> a max' a b | a > b = a | otherwise = b ``` ```haskell myCompare :: (Ord a) => a -> a -> Ordering a `myCompare` b | a > b = GT @@ -385,7 +385,7 @@ evaluation falls through to the next pattern * Guards can use a **where** block to define functions that are only visible inside the guard function ```haskell bmiTell :: (RealFloat a) => a -> a -> String bmiTell weight height | bmi <= skinny = "You're underweight, you emo, you!" @@ -400,30 +400,30 @@ guard function * Combined with a patteren match ```haskell ... where bmi = weight / height ^ 2 (skinny, normal, fat) = (18.5, 25.0, 30.0) ``` * More Examples ```haskell initials :: String -> String -> String initials firstname lastname = [f] ++ ". " ++ [l] ++ "." where (f:_) = firstname (l:_) = lastname ``` ```haskell calcBmis :: (RealFloat a) => [(a, a)] -> [a] calcBmis xs = [bmi w h | (w, h) <- xs] where bmi weight height = weight / height ^ 2 ``` * **Let bindings** are similar to where bindings. Their form is `let <bindings> in <expression>`. ```haskell cylinder :: (RealFloat a) => a -> a -> a cylinder r h = let sideArea = 2 * pi * r * h @@ -434,61 +434,61 @@ guard function * The difference between let bindings and where bindings is that let bindings are expressions, just like if statements: ```haskell 4 * (if 10 > 5 then 10 else 0) + 2 (42) ``` ```haskell 4 * (let a = 9 in a + 1) + 2 (42) ``` * Let bindings can be used to introduce functions in a local scope ```haskell [let square x = x * x in (square 5, square 3, square 2)] ( [(25,9,4)] ) ``` * To let bind several variables they get separated by a semicolon ```haskell (let a = 100; b = 200; c = 300 in a*b*c, let foo="Hey "; bar = "there!" in foo ++ bar) ``` * Let bindings can be used with pattern matching ```haskell (let (a,b,c) = (1,2,3) in a+b+c) * 100 (600) ``` * Let bindings can be used in list comprehensions ```haskell calcBmis :: (RealFloat a) => [(a, a)] -> [a] calcBmis xs = [bmi | (w, h) <- xs, let bmi = w / h ^ 2] ``` * Predicates come after the let binding ```haskell calcBmis :: (RealFloat a) => [(a, a)] -> [a] calcBmis xs = [bmi | (w, h) <- xs, let bmi = w / h ^ 2, bmi >= 25.0] ``` * **Case expressions** are very similar to pattern matching: ```haskell head' :: [a] -> a head' [] = error "No head for empty lists!" head' (x:_) = x ``` ```haskell head' :: [a] -> a head' xs = case xs of [] -> error "No head for empty lists!" (x:_) -> x ``` ```haskell case expression of pattern -> result pattern -> result pattern -> result @@ -498,7 +498,7 @@ expressions, just like if statements: * Pattern matching can only be used with function definitions. Cases expressions work everywhere ```haskell describeList :: [a] -> String describeList xs = "The list is " ++ case xs of [] -> "empty." [x] -> "a singleton list." @@ -511,7 +511,7 @@ work everywhere * Try to start with the edge cases ```haskell maximum' :: (Ord a) => [a] -> a maximum' [] = error "maximum of empty list" maximum' [x] = x @@ -521,47 +521,47 @@ work everywhere where maxTail = maximum' xs ``` ```haskell maximum' :: (Ord a) => [a] -> a maximum' [] = error "maximum of empty list" maximum' [x] = x maximum' (x:xs) = max x (maximum' xs) ``` ```haskell replicate' :: (Num i, Ord i) => i -> a -> [a] replicate' n x | n <= 0 = [] | otherwhise = x:replicate' (n-1) x ``` ```haskell take' :: (Num i, Ord i) => i -> [a] -> [a] take' n _ | n <= 0 = [] take' _ [] = [] take' n (x:xs) = x : take' (n-1) xs ``` ```haskell reverse' :: [a] -> [a] reverse' [] = [] reverse' (x:xs) = reverse' xs ++ [x] ``` ```haskell repeat' :: a -> [a] repeat' x = x:repeat' x ``` ```haskell zip' :: [a] -> [b] -> [(a,b)] zip' _ [] = [] zip' [] _ = [] zip' (x:xs) (y:ys) = (x,y):zip' xs ys ``` ```haskell elem' :: (Eq a) => a -> [a] -> Bool elem' a [] = False elem' a (x:xs) @@ -575,7 +575,7 @@ work everywhere > list in front (and those values are sorted), then comes the head of the list in the middle > and then come all the values that are bigger than the head (they're also sorted) ```haskell quicksort :: (Ord a) => [a] -> [a] quicksort [] = [] quicksort (x:xs) = @@ -598,7 +598,7 @@ than one argument: Calling `max 4 5` creates a function which takes *one* argume returns `4` if the argument is smaller and the argument itself if it is bigger than `4`. These calls are equivalent: ```haskell max 4 5 (max 4) 5 ``` -
mikehaertl revised this gist
Aug 4, 2012 . 1 changed file with 3 additions and 3 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -74,9 +74,9 @@ doubleUs x y = x*2 + y*2 * `if` have a `then` and always require a `else` ```haskell doubleSmallNumber x = if x > 100 then x else x*2 ``` * `if` is also an expression -
mikehaertl revised this gist
Aug 4, 2012 . 1 changed file with 3 additions and 3 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -74,9 +74,9 @@ doubleUs x y = x*2 + y*2 * `if` have a `then` and always require a `else` ```haskell doubleSmallNumber x = if x > 100 then x else x*2 ``` * `if` is also an expression -
mikehaertl revised this gist
Aug 4, 2012 . 1 changed file with 16 additions and 16 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -26,7 +26,7 @@ l: myfunctions.hs * Interactive GHC is started with `ghci` * Simple arithmetic: ```haskell 2 + 15 49 * 100 1892 - 1472 @@ -37,13 +37,13 @@ l: myfunctions.hs * Surround negative numbers with brackets: ```haskell 5 * (-3) ``` * Boolean algebra with `True`, `False`, `not`, `&&`and `||` ```haskell not (True && True) ``` @@ -59,21 +59,21 @@ not (True && True) * Prefix functions can be written as infix with backticks: ```haskell div 92 10 92 `div` 10 ``` * Functions are defined with `=` ```haskell doubleMe x = x + x doubleUs x y = x*2 + y*2 ``` * `if` have a `then` and always require a `else` ```haskell doubleSmallNumber x = if x > 100 then x else x*2 @@ -83,30 +83,30 @@ doubleSmallNumber x = if x > 100 * **Lists** are collections of homogenous elements: all elements have the same type ```haskell lostNumbers = [4,8,15,16,23,42] someString = "Some string" ``` * Use `++` to put two lists together (goes through the complete list!) ```haskell [1,2,3,4] ++ [6,7,8] "Hello" ++ " " ++ "world" ``` * Use `:` to prepend LHS to RHS list ```haskell 'A':" SMALL CAT" 1:[2,3,4,5] 1:2:3:[] ``` * Use `!!` to get an element by index (0 based, index must exist) ```haskell "Steve Buscemi" !! 6 ``` * Use `<`, `<=`, `>` and `>=` to lexographically compare lists -
mikehaertl revised this gist
Aug 4, 2012 . 1 changed file with 20 additions and 20 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -15,8 +15,8 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou * GHC is the most widely used Haskell compiler * To load a file you do: ```haskell l: myfunctions.hs ``` *** @@ -26,7 +26,7 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou * Interactive GHC is started with `ghci` * Simple arithmetic: ``` 2 + 15 49 * 100 1892 - 1472 @@ -37,14 +37,14 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou * Surround negative numbers with brackets: ``` 5 * (-3) ``` * Boolean algebra with `True`, `False`, `not`, `&&`and `||` ``` not (True && True) ``` * Test for equality with `==` and inequality with `/=` @@ -59,33 +59,33 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou * Prefix functions can be written as infix with backticks: ``` div 92 10 92 `div` 10 ``` * Functions are defined with `=` ``` doubleMe x = x + x doubleUs x y = x*2 + y*2 ``` * `if` have a `then` and always require a `else` ``` doubleSmallNumber x = if x > 100 then x else x*2 ``` * `if` is also an expression * **Lists** are collections of homogenous elements: all elements have the same type ``` lostNumbers = [4,8,15,16,23,42] someString = "Some string" ``` * Use `++` to put two lists together (goes through the complete list!) -
mikehaertl revised this gist
Aug 4, 2012 . 1 changed file with 36 additions and 19 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -27,12 +27,12 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou * Simple arithmetic: ``` 2 + 15 49 * 100 1892 - 1472 5 / 2 50 * 100 - 4999 50 * (100 - 4999) ``` * Surround negative numbers with brackets: @@ -217,7 +217,8 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou :t (True, 'a') ( (True,'a') :: (Bool, Char) ) ``` * All functions should use a **type declaration** with `::` ("has type of"). Multiple arguments are also separeted with `->` just like the type declaration itself. ``` removeUppercase :: [Char] -> [Char] @@ -237,14 +238,17 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou - Tuples, as mentioned in chapter 2 - `Ordering` : Can be `GT`, `LT` or `EQ` * **Type variables** can be used in function declarations. They stand for a type. Without a class constraint they mean "any type" ``` :t head (head :: [a] -> a) :t fst (fst :: (a, b) -> a) ``` * **Typeclasses** are like interfaces for types. If a type is part of a typeclass it implements that class' behavior. The `=>` symbol separates the **class constraint** from the declaration: ``` :t (==) ( (==) :: (Eq a) => a -> a -> Bool ) @@ -281,7 +285,9 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou # 4. Syntax in Functions * Functions can be defined with **pattern matching**. Patterns make sure that the input matches a specified pattern. The first matching pattern is executed. There should always be a catch-all pattern at the end ``` lucky :: (Integral a) => a -> String @@ -326,15 +332,17 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou sum' (x:xs) = x + sum' xs ``` * The **as pattern** is used to reference the "whole thing": Put a name followed by `@` in front of the pattern: ``` capital :: String -> String capital "" = "Empty string, whoops!" capital all@(x:xs) = "The first letter of " ++ all ++ " is " ++ [x] ``` * **Guards** are similar to if statements and check for boolean conditions. There's no `=` after the function name: ``` bmiTell :: (RealFloat a) => a -> String @@ -345,7 +353,8 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou | otherwise = "You're a whale, congratulations!" ``` * Guards can be combined with patterns: If all guards of a function evaluate to `False`, evaluation falls through to the next pattern * Guards can have as many parameters as we want @@ -373,7 +382,8 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou | otherwise = LT ``` * Guards can use a **where** block to define functions that are only visible inside the guard function ``` bmiTell :: (RealFloat a) => a -> a -> String @@ -421,7 +431,8 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou in sideArea + 2 * topArea ``` * The difference between let bindings and where bindings is that let bindings are expressions, just like if statements: ``` 4 * (if 10 > 5 then 10 else 0) + 2 (42) @@ -484,7 +495,8 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou ... ``` * Pattern matching can only be used with function definitions. Cases expressions work everywhere ``` describeList :: [a] -> String @@ -572,14 +584,19 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou in smallerSorted ++ [x] ++ biggerSorted ``` *** # 6. Higher order functions * **Higher order functions** take other functions as parameters and return functions themselves (which is what makes up the ultimate *haskell experience*) * Functions in haskell only take *one* argument * **Curried functions** are used to give the impression that a function can have more than one argument: Calling `max 4 5` creates a function which takes *one* argument and returns `4` if the argument is smaller and the argument itself if it is bigger than `4`. These calls are equivalent: ``` max 4 5 -
mikehaertl revised this gist
Aug 4, 2012 . 1 changed file with 35 additions and 19 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -3,6 +3,8 @@ Learn you a Haskell - In a nutshell This is a summary of the "Learn You A Haskell" online book under http://learnyouahaskell.com/chapters. *** # 1. Introduction * Haskell is a functional programming language. @@ -17,6 +19,8 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou l: myfunctions.hs ``` *** # 2. Starting Out * Interactive GHC is started with `ghci` @@ -77,7 +81,7 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou * `if` is also an expression * **Lists** are collections of homogenous elements: all elements have the same type ``` lostNumbers = [4,8,15,16,23,42] @@ -142,13 +146,13 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou - `take 10 (repeat 5)` : repeat the element (`[5,5,5,5,5,5,5,5,5,5]`) - `replicate 3 10` : repeat the element a number of times (`[10,10,10]`) * **List comprehensions** are similar to mathematical equations ``` [x*2 | x <- [1..5]] ([2,4,6,8,10]) ``` * **Predicates** are conditions for list comprehensions ``` [x*2 | x <- [1..5], x*2 >= 5] ([6,8,10]) @@ -185,7 +189,7 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou [ [x | x <- xs, even x] | xs <- xxs] ([[2],[2,4],[4]] ``` * **Tuples** can contain several types, but for the type of two Tuples to be the same, the number and types of their elements must match ``` (1,2) @@ -199,10 +203,11 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou - `snd (9,"Hey")` : returns second component of a pair (`"Hey"`) - `zip [1..3] ['a'..'c']` : combine two lists to a list of tuples ( `[(1,'a'), (2,'b'), (3,'c')]` ) *** # 3. Types and Typeclasses * **Types** always start with an uppercase letter * Use `:t` to get a type of something @@ -212,7 +217,7 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou :t (True, 'a') ( (True,'a') :: (Bool, Char) ) ``` * All functions should use a **type declaration** with `::` ("has type of"). Multiple arguments are also separeted with `->` just like the type declaration itself. ``` removeUppercase :: [Char] -> [Char] @@ -232,14 +237,14 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou - Tuples, as mentioned in chapter 2 - `Ordering` : Can be `GT`, `LT` or `EQ` * **Type variables** can be used in function declarations. They stand for a type. Without a class constraint they mean "any type" ``` :t head (head :: [a] -> a) :t fst (fst :: (a, b) -> a) ``` * **Typeclasses** are like interfaces for types. If a type is part of a typeclass it implements that class' behavior. The `=>` symbol separates the *class constraint* from the declaration: ``` :t (==) ( (==) :: (Eq a) => a -> a -> Bool ) @@ -272,10 +277,11 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou (read "5" :: Float) * 4 ``` *** # 4. Syntax in Functions * Functions can be defined with **pattern matching**. Patterns make sure that the input matches a specified pattern. The first matching pattern is executed. There should always be a catch-all pattern at the end ``` lucky :: (Integral a) => a -> String @@ -320,15 +326,15 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou sum' (x:xs) = x + sum' xs ``` * The **as pattern** is used to reference the "whole thing": Put a name followed by `@` in front of the pattern: ``` capital :: String -> String capital "" = "Empty string, whoops!" capital all@(x:xs) = "The first letter of " ++ all ++ " is " ++ [x] ``` * **Guards** are similar to if statements and check for boolean conditions. There's no `=` after the function name: ``` bmiTell :: (RealFloat a) => a -> String @@ -367,7 +373,7 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou | otherwise = LT ``` * Guards can use a **where** block to define functions that are only visible inside the guard function ``` bmiTell :: (RealFloat a) => a -> a -> String @@ -405,7 +411,7 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou where bmi weight height = weight / height ^ 2 ``` * **Let bindings** are similar to where bindings. Their form is `let <bindings> in <expression>`. ``` cylinder :: (RealFloat a) => a -> a -> a @@ -457,7 +463,7 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou calcBmis xs = [bmi | (w, h) <- xs, let bmi = w / h ^ 2, bmi >= 25.0] ``` * **Case expressions** are very similar to pattern matching: ``` head' :: [a] -> a @@ -487,8 +493,9 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou xs -> "a longer list." ``` *** # 5. Recursion * Try to start with the edge cases @@ -550,7 +557,11 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou | otherwise = a `elem'` xs ``` * Quicksort can be implemented very elegantly. The main algorithm is > A sorted list is a list that has all the values smaller than (or equal to) the head of the > list in front (and those values are sorted), then comes the head of the list in the middle > and then come all the values that are bigger than the head (they're also sorted) ``` quicksort :: (Ord a) => [a] -> [a] @@ -564,8 +575,13 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou # 5. Higher order functions * **Higher order functions** take other functions as parameters and return functions themselves (which is what makes up the ultimate *haskell experience*) * Functions in haskell only take *one* argument * **Curried functions** are used to give the impression that a function can have more than one argument: Calling `max 4 5` creates a function which takes *one* argument and returns `4` if the argument is smaller and the argument itself if it is bigger than `4`. These calls are equivalent: ``` max 4 5 (max 4) 5 ``` -
mikehaertl revised this gist
Aug 4, 2012 . 1 changed file with 11 additions and 5 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,5 +1,5 @@ Learn you a Haskell - In a nutshell ----------------------------------- This is a summary of the "Learn You A Haskell" online book under http://learnyouahaskell.com/chapters. @@ -44,8 +44,8 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou ``` * Test for equality with `==` and inequality with `/=` * **infix** functions like `*` stand between the operators * Most functions are **prefix** functions: - `succ 8` : successor (`9`) - `min 3 4` : minimum of 2 values (`3`) @@ -562,4 +562,10 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou ``` # 5. Higher order functions * Higher order functions take other functions as parameters and return functions themselves (which is what makes up the ultimate *haskell experience*) * Functions in haskell only take *one* argument * *Curried functions* -
mikehaertl revised this gist
Aug 4, 2012 . 1 changed file with 3 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -13,7 +13,7 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou * GHC is the most widely used Haskell compiler * To load a file you do: ```haskell l: myfunctions.hs ``` @@ -22,12 +22,14 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou * Interactive GHC is started with `ghci` * Simple arithmetic: ``` 2 + 15 49 * 100 1892 - 1472 5 / 2 50 * 100 - 4999 50 * (100 - 4999) ``` * Surround negative numbers with brackets: -
mikehaertl revised this gist
Aug 4, 2012 . 1 changed file with 1 addition and 3 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -22,14 +22,12 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou * Interactive GHC is started with `ghci` * Simple arithmetic: 2 + 15 49 * 100 1892 - 1472 5 / 2 50 * 100 - 4999 50 * (100 - 4999) * Surround negative numbers with brackets: @@ -137,7 +135,7 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou - `minimum [5,4,3,2,1]` : minimum of orderable list (`1`) - `sum [5,4,3]` : sum of number list (`12`) - `product [5,4,3]` : product of number list (`60`) - ``4 `elem` [5,4,3]`` : wether element is in list, usually infixed (`True`) - `take 10 (cycle [1,2,3])` : repeat the list elements (`[1,2,3,1,2,3,1,2,3,1]`) - `take 10 (repeat 5)` : repeat the element (`[5,5,5,5,5,5,5,5,5,5]`) - `replicate 3 10` : repeat the element a number of times (`[10,10,10]`) -
mikehaertl revised this gist
Aug 4, 2012 . 1 changed file with 66 additions and 65 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -9,12 +9,13 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou * "what it is" over "what to do" * Haskell is *lazy* - no calculation until a result is used * Statically typed - errors are caught on compile time * Type inference - it auto-detects the right type e.g. for `a = 5 + 4` * GHC is the most widely used Haskell compiler * To load a file you do: ``` l: myfunctions.hs ``` # 2. Starting Out @@ -46,11 +47,11 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou * *infix* functions like `*` stand between the operators * Most functions are *prefix* functions: - `succ 8` : successor (`9`) - `min 3 4` : minimum of 2 values (`3`) - `max 4 5` : maximum of 2 values (`5`) - `div 13 6` : integral division of 2 integers (`2`) - `odd 5` : wether number is odd (`True`) * Prefix functions can be written as infix with backticks: @@ -76,7 +77,7 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou * `if` is also an expression * *Lists* are homogenous collections: all elements have the same type ``` lostNumbers = [4,8,15,16,23,42] @@ -90,7 +91,7 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou "Hello" ++ " " ++ "world" ``` * Use `:` to prepend LHS to RHS list ``` 'A':" SMALL CAT" @@ -123,25 +124,25 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou * List methods - `head [5,4,3]` : first element of a list (`5`) - `tail [5,4,3]` : tail without head (`[4,3]`) - `last [5,4,3]` : last element of a list (`3`) - `init [5,4,3]` : list without tail (`[5,4]`) - `length [5,4,3]` : number of elements (`3`) - `null [5,4,3]` : wether list is empty (`False`) - `reverse [5,4,3]` : reverse list (`[3,4,5]`) - `take 3 [5,4,3,2,1]` : extract number of elements from list start (`[5,4,3]`) - `drop 3 [5,4,3,2,1]` : drop first elements of a list (`[2,1]`) - `maximum [5,4,3,2,1]` : maximum of orderable list (`5`) - `minimum [5,4,3,2,1]` : minimum of orderable list (`1`) - `sum [5,4,3]` : sum of number list (`12`) - `product [5,4,3]` : product of number list (`60`) - `4 \`elem\` [5,4,3]` : wether element is in list, usually infixed (`True`) - `take 10 (cycle [1,2,3])` : repeat the list elements (`[1,2,3,1,2,3,1,2,3,1]`) - `take 10 (repeat 5)` : repeat the element (`[5,5,5,5,5,5,5,5,5,5]`) - `replicate 3 10` : repeat the element a number of times (`[10,10,10]`) * *List comprehensions* are similar to mathematical equations ``` [x*2 | x <- [1..5]] ([2,4,6,8,10]) @@ -153,7 +154,7 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou [x*2 | x <- [1..5], x*2 >= 5] ([6,8,10]) ``` * There can be more than one predicates ``` [ x | x <- [10..20], x /= 10, x /= 15, x /= 19] @@ -184,7 +185,7 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou [ [x | x <- xs, even x] | xs <- xxs] ([[2],[2,4],[4]] ``` * *Tuples* can contain several types, but for the type of two Tuples to be the same, the number and types of their elements must match ``` (1,2) @@ -194,14 +195,14 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou * Tuple functions - `fst (8,11)` : returns first component of a pair (`8`) - `snd (9,"Hey")` : returns second component of a pair (`"Hey"`) - `zip [1..3] ['a'..'c']` : combine two lists to a list of tuples ( `[(1,'a'), (2,'b'), (3,'c')]` ) # 3. Types and Typeclasses * *Types* always start with an uppercase letter * Use `:t` to get a type of something @@ -211,7 +212,7 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou :t (True, 'a') ( (True,'a') :: (Bool, Char) ) ``` * All functions should use a *type declaration* with `::` ("has type of"). Multiple arguments are also separeted with `->` just like the type declaration itself. ``` removeUppercase :: [Char] -> [Char] @@ -222,50 +223,50 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou * Common types - `Int` : Integer - `Integer` : Integer (big) - `Float` : Floating point - `Double` : Floating point with double precision - `Bool` : Boolean - `Char` : Character - Tuples, as mentioned in chapter 2 - `Ordering` : Can be `GT`, `LT` or `EQ` * *Type variables* can be used in function declarations. They stand for a type. Without a class constraint they mean "any type" ``` :t head (head :: [a] -> a) :t fst (fst :: (a, b) -> a) ``` * *Typeclasses* are like interfaces for types. If a type is part of a typeclass it implements that class' behavior. The `=>` symbol separates the *class constraint* from the declaration: ``` :t (==) ( (==) :: (Eq a) => a -> a -> Bool ) ``` - `Eq` : supports equality testing - `Ord` : can have ordering - `Show` : can be presented as string - `Read` : can be read from a string - `Enum` : ordered type which can be enumerated - `Bounded` : have an upper and lower bound - `Num` : can act like a number - `Integral` : can act like an integral number - `Floating` : can act like a floating point number * Related functions - `5 \`compare\` 3` : takes two `Ord` members of same type and returns a `Ordering` (`GT`) - `show 3` : takes a `Show` and returns a `String` (`"3"`) - `read "True"` : takes a `Read` and returns a `Read` (`True`) - `succ LT` : takes a `Enum` and returns next element (`GT`) - `pred 'b'` : takes a `Enum` and returns previous element (`'a'`) - `minBound` :: Bool : takes a `Bounded` and returns lower bound (`False`) - `maxBound` :: Bool : takes a `Bounded` and returns lower bound (`True`) - `fromIntegral 5` : takes a `Integral` and returns a `Num` * *Type annotations* define the type of ambiguous expressions ``` (read "5" :: Float) * 4 @@ -274,7 +275,7 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou # 3. Syntax in Functions * Functions can be defined with *pattern matching*. Patterns make sure that the input matches a specified pattern. The first matching pattern is executed. There should always be a catch-all pattern at the end ``` lucky :: (Integral a) => a -> String @@ -338,7 +339,7 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou | otherwise = "You're a whale, congratulations!" ``` * Guards can be combined with patterns: If all guards of a function evaluate to `False`, evaluation falls through to the next pattern * Guards can have as many parameters as we want @@ -561,4 +562,4 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou ``` # 5. Higher order functions -
mikehaertl revised this gist
Aug 4, 2012 . 1 changed file with 124 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -21,20 +21,26 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou * Interactive GHC is started with `ghci` * Simple arithmetic: ``` 2 + 15 49 * 100 1892 - 1472 5 / 2 50 * 100 - 4999 50 * (100 - 4999) ``` * Surround negative numbers with brackets: ``` 5 * (-3) ``` * Boolean algebra with `True`, `False`, `not`, `&&`and `||` ``` not (True && True) ``` * Test for equality with `==` and inequality with `/=` * *infix* functions like `*` stand between the operators @@ -48,54 +54,72 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou * Prefix functions can be written as infix with backticks: ``` div 92 10 92 `div` 10 ``` * Functions are defined with `=` ``` doubleMe x = x + x doubleUs x y = x*2 + y*2 ``` * `if` have a `then` and always require a `else` ``` doubleSmallNumber x = if x > 100 then x else x*2 ``` * `if` is also an expression * Lists are *homogenous* (all elements have the same type): ``` lostNumbers = [4,8,15,16,23,42] someString = "Some string" ``` * Use `++` to put two lists together (goes through the complete list!) ``` [1,2,3,4] ++ [6,7,8] "Hello" ++ " " ++ "world" ``` * Use `:` to prepend LHS to RHS ``` 'A':" SMALL CAT" 1:[2,3,4,5] 1:2:3:[] ``` * Use `!!` to get an element by index (0 based, index must exist) ``` "Steve Buscemi" !! 6 ``` * Use `<`, `<=`, `>` and `>=` to lexographically compare lists * List ranges are defined with `..`: ``` [1..20] ['a'..'z'] ``` * Ranges can define a step size ``` [2,4..20] ([2,4,6,8,10,12,16,18,20]) [3,6..20] ([3,6,9,12,15,18]) [20,19..15] ([20,19,18,17,16,15]) ``` * List methods @@ -119,38 +143,54 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou * List comprehensions are similar to mathematical equations ``` [x*2 | x <- [1..5]] ([2,4,6,8,10]) ``` * *Predicates* are conditions for list comprehensions ``` [x*2 | x <- [1..5], x*2 >= 5] ([6,8,10]) ``` * There can be more predicates ``` [ x | x <- [10..20], x /= 10, x /= 15, x /= 19] ``` * Comprehensions can be put inside a function ``` boomBangs xs = [if x < 10 then "BOOM!" else "BANG!" | x <- xs, odd x] ``` * Comprehensions can draw from several lists, which multiplies the lengths ``` [ x*y | x <- [2,3], y <- [3,4,5]] ([6,8,10,9,12,15]) ``` * `_` is a dummy placeholder for a unused value ``` length' xs = sum [1 | _ <- xs] ``` * List comprehensions can be nested ``` let xxs = [[1,2,3],[2,3,4],[4,5]] [ [x | x <- xs, even x] | xs <- xxs] ([[2],[2,4],[4]] ``` * Tuples can contain several types, but for the type of two Tuples to be the same, the number and types of their elements must match ``` (1,2) [(1,2), (3,2), (4,9)] [("Johnny", "Walker", 38), ("Kate", "Middleton", 27)] ``` * Tuple functions @@ -165,16 +205,20 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou * Use `:t` to get a type of something ``` :t 'a' ('a' :: Char) :t "HELLO" ("HELLO" :: [Char]) :t (True, 'a') ( (True,'a') :: (Bool, Char) ) ``` * All functions should use a type declaration with `::` ("has type of"). Multiple arguments are also separeted with `->` just like the type declaration itself. ``` removeUppercase :: [Char] -> [Char] removeUppercase :: String -> String (same as above) addThree :: Int -> Int -> Int -> Int addThree x y z = x + y + z ``` * Common types @@ -189,12 +233,16 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou * Type variables can be used in function declarations. They mean "any type" ``` :t head (head :: [a] -> a) :t fst (fst :: (a, b) -> a) ``` * Typeclasses are like interfaces for types. If a type is part of a typeclass it implements that class' behavior. The `=>` symbol separates the *class constraint* from the declaration: ``` :t (==) ( (==) :: (Eq a) => a -> a -> Bool ) ``` - Eq : supports equality testing - Ord : can have ordering @@ -219,81 +267,108 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou * Type annotations define the type of ambiguous expressions ``` (read "5" :: Float) * 4 ``` # 3. Syntax in Functions * Functions can be defined with *Pattern Matching*. Patterns make sure that the input matches a specified pattern. The first matching pattern is executed. There should always be a catch-all pattern at the end ``` lucky :: (Integral a) => a -> String lucky 7 = "LUCKY NUMBER SEVEN!" lucky x = "Sorry, you're out of luck, pal!" ``` ``` factorial :: (Integral a) => a -> a factorial 0 = 1 factorial n = n * factorial (n - 1) ``` ``` addVectors :: (Num a) => (a, a) -> (a, a) -> (a, a) addVectors (x1, y1) (x2, y2) = (x1 + x2, y1 + y2) ``` ``` head' :: [a] -> a head' [] = error "Can't call head on an empty list, dummy!" head' (x:_) = x ``` ``` tell :: (Show a) => [a] -> String tell [] = "The list is empty" tell (x:[]) = "The list has one element: " ++ show x tell (x:y:[]) = "The list has two elements: " ++ show x ++ " and " ++ show y tell (x:y:_) = "This list is long. The first two elements are: " ++ show x ++ " and " ++ show y ``` ``` length' :: (Num b) => [a] -> b length' [] = 0 length' (_:xs) = 1 + length' xs ``` ``` sum' :: (Num a) => [a] -> a sum' [] = 0 sum' (x:xs) = x + sum' xs ``` * The *as pattern* is used to reference the "whole thing": Put a name followed by `@` in front of the pattern: ``` capital :: String -> String capital "" = "Empty string, whoops!" capital all@(x:xs) = "The first letter of " ++ all ++ " is " ++ [x] ``` * *Guards* are similar to if statements and check for boolean conditions. There's no `=` after the function name: ``` bmiTell :: (RealFloat a) => a -> String bmiTell bmi | bmi <= 18.5 = "You're underweight, you emo, you!" | bmi <= 25.0 = "You're supposedly normal. Pffft, I bet you're ugly!" | bmi <= 30.0 = "You're fat! Lose some weight, fatty!" | otherwise = "You're a whale, congratulations!" ``` * Guards can be combined with patterns: If all guards of a function evaluate to False, evaluation falls through to the next pattern * Guards can have as many parameters as we want ``` bmiTell :: (RealFloat a) => a -> a -> String bmiTell weight height | weight / height ^ 2 <= 18.5 = "You're underweight, you emo, you!" | weight / height ^ 2 <= 25.0 = "You're supposedly normal. Pffft, I bet you're ugly!" | weight / height ^ 2 <= 30.0 = "You're fat! Lose some weight, fatty!" | otherwise = "You're a whale, congratulations!" ``` ``` max' :: (Ord a) => a -> a -> a max' a b | a > b = a | otherwise = b ``` ``` myCompare :: (Ord a) => a -> a -> Ordering a `myCompare` b | a > b = GT | a == b = EQ | otherwise = LT ``` * Guards can use a `where` block to define functions that are only visible inside the guard function ``` bmiTell :: (RealFloat a) => a -> a -> String bmiTell weight height | bmi <= skinny = "You're underweight, you emo, you!" @@ -304,137 +379,186 @@ This is a summary of the "Learn You A Haskell" online book under http://learnyou skinny = 18.5 normal = 25.0 fat = 30.0 ``` * Combined with a patteren match ``` ... where bmi = weight / height ^ 2 (skinny, normal, fat) = (18.5, 25.0, 30.0) ``` * More Examples ``` initials :: String -> String -> String initials firstname lastname = [f] ++ ". " ++ [l] ++ "." where (f:_) = firstname (l:_) = lastname ``` ``` calcBmis :: (RealFloat a) => [(a, a)] -> [a] calcBmis xs = [bmi w h | (w, h) <- xs] where bmi weight height = weight / height ^ 2 ``` * *Let bindings* are similar to where bindings. Their form is `let <bindings> in <expression>`. ``` cylinder :: (RealFloat a) => a -> a -> a cylinder r h = let sideArea = 2 * pi * r * h topArea = pi * r ^2 in sideArea + 2 * topArea ``` * The difference between let bindings and where bindings is that let bindings are expressions, just like if statements: ``` 4 * (if 10 > 5 then 10 else 0) + 2 (42) ``` ``` 4 * (let a = 9 in a + 1) + 2 (42) ``` * Let bindings can be used to introduce functions in a local scope ``` [let square x = x * x in (square 5, square 3, square 2)] ( [(25,9,4)] ) ``` * To let bind several variables they get separated by a semicolon ``` (let a = 100; b = 200; c = 300 in a*b*c, let foo="Hey "; bar = "there!" in foo ++ bar) ``` * Let bindings can be used with pattern matching ``` (let (a,b,c) = (1,2,3) in a+b+c) * 100 (600) ``` * Let bindings can be used in list comprehensions ``` calcBmis :: (RealFloat a) => [(a, a)] -> [a] calcBmis xs = [bmi | (w, h) <- xs, let bmi = w / h ^ 2] ``` * Predicates come after the let binding ``` calcBmis :: (RealFloat a) => [(a, a)] -> [a] calcBmis xs = [bmi | (w, h) <- xs, let bmi = w / h ^ 2, bmi >= 25.0] ``` * *Case expressions* are very similar to pattern matching: ``` head' :: [a] -> a head' [] = error "No head for empty lists!" head' (x:_) = x ``` ``` head' :: [a] -> a head' xs = case xs of [] -> error "No head for empty lists!" (x:_) -> x ``` ``` case expression of pattern -> result pattern -> result pattern -> result ... ``` * Pattern matching can only be used with function definitions. Cases expressions work everywhere ``` describeList :: [a] -> String describeList xs = "The list is " ++ case xs of [] -> "empty." [x] -> "a singleton list." xs -> "a longer list." ``` # 4. Recursion * Try to start with the edge cases ``` maximum' :: (Ord a) => [a] -> a maximum' [] = error "maximum of empty list" maximum' [x] = x maximum' (x:xs) | x > maxTail = x | otherwise = maxTail where maxTail = maximum' xs ``` ``` maximum' :: (Ord a) => [a] -> a maximum' [] = error "maximum of empty list" maximum' [x] = x maximum' (x:xs) = max x (maximum' xs) ``` ``` replicate' :: (Num i, Ord i) => i -> a -> [a] replicate' n x | n <= 0 = [] | otherwhise = x:replicate' (n-1) x ``` ``` take' :: (Num i, Ord i) => i -> [a] -> [a] take' n _ | n <= 0 = [] take' _ [] = [] take' n (x:xs) = x : take' (n-1) xs ``` ``` reverse' :: [a] -> [a] reverse' [] = [] reverse' (x:xs) = reverse' xs ++ [x] ``` ``` repeat' :: a -> [a] repeat' x = x:repeat' x ``` ``` zip' :: [a] -> [b] -> [(a,b)] zip' _ [] = [] zip' [] _ = [] zip' (x:xs) (y:ys) = (x,y):zip' xs ys ``` ``` elem' :: (Eq a) => a -> [a] -> Bool elem' a [] = False elem' a (x:xs) | a == x = True | otherwise = a `elem'` xs ``` * Quicksort can be implemented very elegantly. The main algorithm is "a sorted list is a list that has all the values smaller than (or equal to) the head of the list in front (and those values are sorted), then comes the head of the list in the middle and then come all the values that are bigger than the head (they're also sorted)" ``` quicksort :: (Ord a) => [a] -> [a] quicksort [] = [] quicksort (x:xs) = let smallerSorted = quicksort [a | a <- xs, a <= x] biggerSorted = quicksort [a | a <- xs, a > x] in smallerSorted ++ [x] ++ biggerSorted ``` # 5. Higher order functions -
mikehaertl created this gist
Aug 4, 2012 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,440 @@ Haskell Overview ---------------- This is a summary of the "Learn You A Haskell" online book under http://learnyouahaskell.com/chapters. # 1. Introduction * Haskell is a functional programming language. * "what it is" over "what to do" * Haskell is *lazy* - no calculation until a result is used * Statically typed - errors are caught on compile time * Type inference - it auto-detects the right type e.g. for a = 5 + 4 * GHC is the most widely used Haskell compiler * To load a file you do: l: myfunctions.hs # 2. Starting Out * Interactive GHC is started with `ghci` * Simple arithmetic: 2 + 15 49 * 100 1892 - 1472 5 / 2 50 * 100 - 4999 50 * (100 - 4999) * Surround negative numbers with brackets: 5 * (-3) * Boolean algebra with `True`, `False`, `not`, `&&`and `||` not (True && True) * Test for equality with `==` and inequality with `/=` * *infix* functions like `*` stand between the operators * Most functions are *prefix* functions: - succ 8 : successor (9) - min 3 4 : minimum of 2 values (3) - max 4 5 : maximum of 2 values (5) - div 13 6 : integral division of 2 integers (2) - odd 5 : wether number is odd (True) * Prefix functions can be written as infix with backticks: div 92 10 92 `div` 10 * Functions are defined with `=` doubleMe x = x + x doubleUs x y = x*2 + y*2 * `if` have a `then` and always require a `else` doubleSmallNumber x = if x > 100 then x else x*2 * `if` is also an expression * Lists are *homogenous* (all elements have the same type): lostNumbers = [4,8,15,16,23,42] someString = "Some string" * Use `++` to put two lists together (goes through the complete list!) [1,2,3,4] ++ [6,7,8] "Hello" ++ " " ++ "world" * Use `:` to prepend LHS to RHS 'A':" SMALL CAT" 1:[2,3,4,5] 1:2:3:[] * Use `!!` to get an element by index (0 based, index must exist) "Steve Buscemi" !! 6 * Use `<`, `<=`, `>` and `>=` to lexographically compare lists * List ranges are defined with `..`: [1..20] ['a'..'z'] * Ranges can define a step size [2,4..20] ([2,4,6,8,10,12,16,18,20]) [3,6..20] ([3,6,9,12,15,18]) [20,19..15] ([20,19,18,17,16,15]) * List methods - head [5,4,3] : first element of a list (5) - tail [5,4,3] : tail without head ([4,3]) - last [5,4,3] : last element of a list (3) - init [5,4,3] : list without tail ([5,4]) - length [5,4,3] : number of elements (3) - null [5,4,3] : wether list is empty (False) - reverse [5,4,3] : reverse list ([3,4,5]) - take 3 [5,4,3,2,1] : extract number of elements from list start ([5,4,3]) - drop 3 [5,4,3,2,1] : drop first elements of a list ([2,1]) - maximum [5,4,3,2,1] : maximum of orderable list (5) - minimum [5,4,3,2,1] : minimum of orderable list (1) - sum [5,4,3] : sum of number list (12) - product [5,4,3] : product of number list (60) - 4 `elem` [5,4,3] : wether element is in list, usually infixed (True) - take 10 (cycle [1,2,3]) : repeat the list elements ([1,2,3,1,2,3,1,2,3,1]) - take 10 (repeat 5) : repeat the element ([5,5,5,5,5,5,5,5,5,5]) - replicate 3 10 : repeat the element a number of times ([10,10,10]) * List comprehensions are similar to mathematical equations [x*2 | x <- [1..5]] ([2,4,6,8,10]) * *Predicates* are conditions for list comprehensions [x*2 | x <- [1..5], x*2 >= 5] ([6,8,10]) * There can be more predicates [ x | x <- [10..20], x /= 10, x /= 15, x /= 19] * Comprehensions can be put inside a function boomBangs xs = [if x < 10 then "BOOM!" else "BANG!" | x <- xs, odd x] * Comprehensions can draw from several lists, which multiplies the lengths [ x*y | x <- [2,3], y <- [3,4,5]] ([6,8,10,9,12,15]) * `_` is a dummy placeholder for a unused value length' xs = sum [1 | _ <- xs] * List comprehensions can be nested let xxs = [[1,2,3],[2,3,4],[4,5]] [ [x | x <- xs, even x] | xs <- xxs] ([[2],[2,4],[4]] * Tuples can contain several types, but for the type of two Tuples to be the same, the number and types of their elements must match (1,2) [(1,2), (3,2), (4,9)] [("Johnny", "Walker", 38), ("Kate", "Middleton", 27)] * Tuple functions - fst (8,11) : returns first component of a pair (8) - snd (9,"Hey") : returns second component of a pair ("Hey") - zip [1..3] ['a'..'c'] : combine two lists to a list of tuples ( [(1,'a'), (2,'b'), (3,'c')] ) # 3. Types and Typeclasses * Types always start with an uppercase letter * Use `:t` to get a type of something :t 'a' ('a' :: Char) :t "HELLO" ("HELLO" :: [Char]) :t (True, 'a') ( (True,'a') :: (Bool, Char) ) * All functions should use a type declaration with `::` ("has type of"). Multiple arguments are also separeted with `->` just like the type declaration itself. removeUppercase :: [Char] -> [Char] removeUppercase :: String -> String (same as above) addThree :: Int -> Int -> Int -> Int addThree x y z = x + y + z * Common types - Int : Integer - Integer : Integer (big) - Float : Floating point - Double : Floating point with double precision - Bool : Boolean - Char : Character - Tuples, as mentioned in chapter 2 - Ordering : Can be `GT`, `LT` or `EQ` * Type variables can be used in function declarations. They mean "any type" :t head (head :: [a] -> a) :t fst (fst :: (a, b) -> a) * Typeclasses are like interfaces for types. If a type is part of a typeclass it implements that class' behavior. The `=>` symbol separates the *class constraint* from the declaration: :t (==) ( (==) :: (Eq a) => a -> a -> Bool ) - Eq : supports equality testing - Ord : can have ordering - Show : can be presented as string - Read : can be read from a string - Enum : ordered type which can be enumerated - Bounded : have an upper and lower bound - Num : can act like a number - Integral : can act like an integral number - Floating : can act like a floating point number * Related functions - 5 `compare` 3 : takes two `Ord` members of same type and returns a `Ordering` (GT) - show 3 : takes a `Show` and returns a `String` ("3") - read "True" : takes a `Read` and returns a `Read` (True) - succ LT : takes a `Enum` and returns next element (GT) - pred 'b' : takes a `Enum` and returns previous element ('a') - minBound :: Bool : takes a `Bounded` and returns lower bound (False) - maxBound :: Bool : takes a `Bounded` and returns lower bound (True) - fromIntegral 5 : takes a `Integral` and returns a `Num` * Type annotations define the type of ambiguous expressions (read "5" :: Float) * 4 # 3. Syntax in Functions * Functions can be defined with *Pattern Matching*. Patterns make sure that the input matches a specified pattern. The first matching pattern is executed. There should always be a catch-all pattern at the end lucky :: (Integral a) => a -> String lucky 7 = "LUCKY NUMBER SEVEN!" lucky x = "Sorry, you're out of luck, pal!" factorial :: (Integral a) => a -> a factorial 0 = 1 factorial n = n * factorial (n - 1) addVectors :: (Num a) => (a, a) -> (a, a) -> (a, a) addVectors (x1, y1) (x2, y2) = (x1 + x2, y1 + y2) head' :: [a] -> a head' [] = error "Can't call head on an empty list, dummy!" head' (x:_) = x tell :: (Show a) => [a] -> String tell [] = "The list is empty" tell (x:[]) = "The list has one element: " ++ show x tell (x:y:[]) = "The list has two elements: " ++ show x ++ " and " ++ show y tell (x:y:_) = "This list is long. The first two elements are: " ++ show x ++ " and " ++ show y length' :: (Num b) => [a] -> b length' [] = 0 length' (_:xs) = 1 + length' xs sum' :: (Num a) => [a] -> a sum' [] = 0 sum' (x:xs) = x + sum' xs * The *as pattern* is used to reference the "whole thing": Put a name followed by `@` in front of the pattern: capital :: String -> String capital "" = "Empty string, whoops!" capital all@(x:xs) = "The first letter of " ++ all ++ " is " ++ [x] * *Guards* are similar to if statements and check for boolean conditions. There's no `=` after the function name: bmiTell :: (RealFloat a) => a -> String bmiTell bmi | bmi <= 18.5 = "You're underweight, you emo, you!" | bmi <= 25.0 = "You're supposedly normal. Pffft, I bet you're ugly!" | bmi <= 30.0 = "You're fat! Lose some weight, fatty!" | otherwise = "You're a whale, congratulations!" * Guards can be combined with patterns: If all guards of a function evaluate to False, evaluation falls through to the next pattern * Guards can have as many parameters as we want bmiTell :: (RealFloat a) => a -> a -> String bmiTell weight height | weight / height ^ 2 <= 18.5 = "You're underweight, you emo, you!" | weight / height ^ 2 <= 25.0 = "You're supposedly normal. Pffft, I bet you're ugly!" | weight / height ^ 2 <= 30.0 = "You're fat! Lose some weight, fatty!" | otherwise = "You're a whale, congratulations!" max' :: (Ord a) => a -> a -> a max' a b | a > b = a | otherwise = b myCompare :: (Ord a) => a -> a -> Ordering a `myCompare` b | a > b = GT | a == b = EQ | otherwise = LT * Guards can use a `where` block to define functions that are only visible inside the guard function bmiTell :: (RealFloat a) => a -> a -> String bmiTell weight height | bmi <= skinny = "You're underweight, you emo, you!" | bmi <= normal = "You're supposedly normal. Pffft, I bet you're ugly!" | bmi <= fat = "You're fat! Lose some weight, fatty!" | otherwise = "You're a whale, congratulations!" where bmi = weight / height ^ 2 skinny = 18.5 normal = 25.0 fat = 30.0 * Combined with a patteren match ... where bmi = weight / height ^ 2 (skinny, normal, fat) = (18.5, 25.0, 30.0) * More Examples initials :: String -> String -> String initials firstname lastname = [f] ++ ". " ++ [l] ++ "." where (f:_) = firstname (l:_) = lastname calcBmis :: (RealFloat a) => [(a, a)] -> [a] calcBmis xs = [bmi w h | (w, h) <- xs] where bmi weight height = weight / height ^ 2 * *Let bindings* are similar to where bindings. Their form is `let <bindings> in <expression>`. cylinder :: (RealFloat a) => a -> a -> a cylinder r h = let sideArea = 2 * pi * r * h topArea = pi * r ^2 in sideArea + 2 * topArea * The difference between let bindings and where bindings is that let bindings are expressions, just like if statements: 4 * (if 10 > 5 then 10 else 0) + 2 (42) 4 * (let a = 9 in a + 1) + 2 (42) * Let bindings can be used to introduce functions in a local scope [let square x = x * x in (square 5, square 3, square 2)] ( [(25,9,4)] ) * To let bind several variables they get separated by a semicolon (let a = 100; b = 200; c = 300 in a*b*c, let foo="Hey "; bar = "there!" in foo ++ bar) * Let bindings can be used with pattern matching (let (a,b,c) = (1,2,3) in a+b+c) * 100 (600) * Let bindings can be used in list comprehensions calcBmis :: (RealFloat a) => [(a, a)] -> [a] calcBmis xs = [bmi | (w, h) <- xs, let bmi = w / h ^ 2] * Predicates come after the let binding calcBmis :: (RealFloat a) => [(a, a)] -> [a] calcBmis xs = [bmi | (w, h) <- xs, let bmi = w / h ^ 2, bmi >= 25.0] * *Case expressions* are very similar to pattern matching: head' :: [a] -> a head' [] = error "No head for empty lists!" head' (x:_) = x head' :: [a] -> a head' xs = case xs of [] -> error "No head for empty lists!" (x:_) -> x case expression of pattern -> result pattern -> result pattern -> result ... * Pattern matching can only be used with function definitions. Cases expressions work everywhere describeList :: [a] -> String describeList xs = "The list is " ++ case xs of [] -> "empty." [x] -> "a singleton list." xs -> "a longer list." # 4. Recursion * Try to start with the edge cases maximum' :: (Ord a) => [a] -> a maximum' [] = error "maximum of empty list" maximum' [x] = x maximum' (x:xs) | x > maxTail = x | otherwise = maxTail where maxTail = maximum' xs maximum' :: (Ord a) => [a] -> a maximum' [] = error "maximum of empty list" maximum' [x] = x maximum' (x:xs) = max x (maximum' xs) replicate' :: (Num i, Ord i) => i -> a -> [a] replicate' n x | n <= 0 = [] | otherwhise = x:replicate' (n-1) x take' :: (Num i, Ord i) => i -> [a] -> [a] take' n _ | n <= 0 = [] take' _ [] = [] take' n (x:xs) = x : take' (n-1) xs reverse' :: [a] -> [a] reverse' [] = [] reverse' (x:xs) = reverse' xs ++ [x] repeat' :: a -> [a] repeat' x = x:repeat' x zip' :: [a] -> [b] -> [(a,b)] zip' _ [] = [] zip' [] _ = [] zip' (x:xs) (y:ys) = (x,y):zip' xs ys elem' :: (Eq a) => a -> [a] -> Bool elem' a [] = False elem' a (x:xs) | a == x = True | otherwise = a `elem'` xs * Quicksort can be implemented very elegantly. The main algorithm is "a sorted list is a list that has all the values smaller than (or equal to) the head of the list in front (and those values are sorted), then comes the head of the list in the middle and then come all the values that are bigger than the head (they're also sorted)" quicksort :: (Ord a) => [a] -> [a] quicksort [] = [] quicksort (x:xs) = let smallerSorted = quicksort [a | a <- xs, a <= x] biggerSorted = quicksort [a | a <- xs, a > x] in smallerSorted ++ [x] ++ biggerSorted # 5. Higher order functions