Starting Out

Starting Out

@wusyong, 吳昱緯


{{% section %}}

Ready, set, go!

ghci> 2 + 15  
17  
ghci> 49 * 100  
4900  
ghci> 1892 - 1472  
420  
ghci> 5 / 2  
2.5  
ghci>  

Arithmetic

ghci> (50 * 100) - 4999  
1  
ghci> 50 * 100 - 4999  
1  
ghci> 50 * (100 - 4999)  
-244950  

Boolean

ghci> True && False  
False  
ghci> True && True  
True  
ghci> False || True  
True   
ghci> not False  
True  
ghci> not (True && True)  
False  

Boolean

ghci> 5 == 5  
True  
ghci> 1 == 0  
False  
ghci> 5 /= 5  
False  
ghci> 5 /= 4  
True  
ghci> "hello" == "hello"  
True  

Types still matter

ghci> 5 + "llama"
No instance for (Num [Char])  
arising from a use of `+' at <interactive>:1:0-9  
Possible fix: add an instance declaration for (Num [Char])  
In the expression: 5 + "llama"  
In the definition of `it': it = 5 + "llama"   

Functions

ghci> succ 8  
9
ghci> min 9 10  
9  
ghci> min 3.4 3.2  
3.2  
ghci> max 100 101  
101  

Function application has the highest precedence

ghci> succ 9 + max 5 4 + 1  
16  
ghci> (succ 9) + (max 5 4) + 1  
16   

{{% /section %}}


{{% section %}}

Baby's first functions

Create a baby.hs:

doubleMe x = x + x
ghci> :l baby  
[1 of 1] Compiling Main             ( baby.hs, interpreted )  
Ok, modules loaded: Main.  
ghci> doubleMe 9  
18  
ghci> doubleMe 8.3  
16.6   

More functions

Create a baby.hs:

doubleUs x y = x*2 + y*2
doubleUs x y = doubleMe x + doubleMe y   
ghci> :r
ghci> doubleUs 4 9  
26  
ghci> doubleUs 2.3 34.2  
73.0  
ghci> doubleUs 28 88 + doubleMe 123  
478     

If Statement

doubleSmallNumber x = if x > 100  
                        then x  
                        else x*2

' is valid character for function

doubleSmallNumber' x = (if x > 100 then x else x*2) + 1

However first character in function cant be upper case

conanO'Brien = "It's a-me, Conan O'Brien!"  

{{% /section %}}


{{% section %}}

An intro to lists

ghci> lostNumbers = [4,8,15,16,23,42]  
ghci> lostNumbers  
[4,8,15,16,23,42]

Strings are Lists

"hello"
['h','e','l','l','o']

++ operator

ghci> [1,2,3,4] ++ [9,10,11,12]  
[1,2,3,4,9,10,11,12]  
ghci> "hello" ++ " " ++ "world"  
"hello world"  
ghci> ['w','o'] ++ ['o','t']  
"woot" 

: operator (cons operator)

ghci> 'A':" SMALL CAT"  
"A SMALL CAT"  
ghci> 5:[1,2,3,4,5]  
[5,1,2,3,4,5]  

What lists actually present

  • [1,2,3] == 1:2:3:[]
  • [] means empty list
  • [], [[]] and [[],[],[]] are all different things.

!! operator

ghci> "Steve Buscemi" !! 6  
'B'  
ghci> [9.4,33.2,96.2,11.2,23.25] !! 1  
33.2

List can contain list

ghci> let b = [[1,2,3,4],[5,3,3,3],[1,2,2,3,4],[1,2,3]]  
ghci> b  
[[1,2,3,4],[5,3,3,3],[1,2,2,3,4],[1,2,3]]  
ghci> b ++ [[1,1,1,1]]  
[[1,2,3,4],[5,3,3,3],[1,2,2,3,4],[1,2,3],[1,1,1,1]]  
ghci> [6,6,6]:b  
[[6,6,6],[1,2,3,4],[5,3,3,3],[1,2,2,3,4],[1,2,3]]  
ghci> b !! 2  
[1,2,2,3,4] 

Order comparing

ghci> [3,2,1] > [2,1,0]  
True  
ghci> [3,2,1] > [2,10,100]  
True  
ghci> [3,4,2] > [3,4]  
True  
ghci> [3,4,2] > [2,4]  
True  
ghci> [3,4,2] == [3,4,2]  
True

head/tail/last/init

ghci> head [5,4,3,2,1]  
5  
ghci> tail [5,4,3,2,1]  
[4,3,2,1] 
ghci> last [5,4,3,2,1]  
1 
ghci> init [5,4,3,2,1]  
[5,4,3,2]
ghci> head []  
*** Exception: Prelude.head: empty list  

More basic functions

ghci> length [5,4,3,2,1]  
5 
ghci> null [1,2,3]  
False  
ghci> null []  
True 
ghci> reverse [5,4,3,2,1]  
[1,2,3,4,5] 
ghci> take 3 [5,4,3,2,1]  
[5,4,3]
ghci> take 5 [1,2]  
[1,2]  
ghci> take 0 [6,6,6]  
[] 

More basic functions

ghci> drop 3 [8,4,2,1,5,6]  
[1,5,6]  
ghci> drop 0 [1,2,3,4]  
[1,2,3,4]  
ghci> drop 100 [1,2,3,4]  
[]
ghci> minimum [8,4,2,1,5,6]  
1  
ghci> maximum [1,9,2,3,4]  
9
ghci> sum [5,2,1,6,3,2,5,7]  
31  
ghci> product [6,2,1,2]  
24  

More basic functions

ghci> 4 `elem` [3,4,5,6]  
True  
ghci> 10 `elem` [3,4,5,6]  
False  

{{% /section %}}


{{% section %}}

Texas ranges

ghci> [1..20]  
[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]  
ghci> ['a'..'z']  
"abcdefghijklmnopqrstuvwxyz"  
ghci> ['K'..'Z']  
"KLMNOPQRSTUVWXYZ"

Ranges can be specified the step

ghci> [2,4..20]  
[2,4,6,8,10,12,14,16,18,20]  
ghci> [3,6..20]  
[3,6,9,12,15,18]
-- Floating point can go wrong though
ghci> [0.1, 0.3 .. 1]  
[0.1,0.3,0.5,0.7,0.8999999999999999,1.0999999999999999] 

Inifinite lists

  • take 24 [13,26..] == [13,26..24*13]

Some functions to produce infinite lists

ghci> take 10 (cycle [1,2,3])  
[1,2,3,1,2,3,1,2,3,1]  
ghci> take 12 (cycle "LOL ")  
"LOL LOL LOL " 
ghci> take 10 (repeat 5)  
[5,5,5,5,5,5,5,5,5,5] 
ghci> replicate 3 10
[10,10,10]

{{% /section %}}


{{% section %}}

I'm a list comprehension

Set Comprehensions


list comprehension

ghci> [x*2 | x <- [1..10]]  
[2,4,6,8,10,12,14,16,18,20]
ghci> [x*2 | x <- [1..10], x*2 >= 12]  
[12,14,16,18,20]
ghci> [ x | x <- [50..100], x `mod` 7 == 3]  
[52,59,66,73,80,87,94]   

Filtering

boomBangs xs = [ if x < 10 then "BOOM!" else "BANG!" | x <- xs, odd x]   
ghci> boomBangs [7..13]  
["BOOM!","BOOM!","BANG!","BANG!"]
ghci> [ x | x <- [10..20], x /= 13, x /= 15, x /= 19]  
[10,11,12,14,16,17,18,20] 
ghci> [ x*y | x <- [2,5,10], y <- [8,10,11]]  
[16,20,22,40,50,55,80,100,110] 
ghci> [ x*y | x <- [2,5,10], y <- [8,10,11], x*y > 50]  
[55,80,100,110] 

List combination

ghci> let nouns = ["hobo","frog","pope"]  
ghci> let adjectives = ["lazy","grouchy","scheming"]  
ghci> [adjective ++ " " ++ noun | adjective <- adjectives, noun <- nouns]  
["lazy hobo","lazy frog","lazy pope","grouchy hobo","grouchy frog",  
"grouchy pope","scheming hobo","scheming frog","scheming pope"]

Practices

length' xs = sum [1 | _ <- xs]
removeNonUppercase st = [ c | c <- st, c `elem` ['A'..'Z']]
ghci> removeNonUppercase "Hahaha! Ahahaha!"  
"HA"  
ghci> removeNonUppercase "IdontLIKEFROGS"  
"ILIKEFROGS" 

Nested List Comprehensions

ghci> let xxs = [[1,3,5,2,3,1,2,4,5],[1,2,3,4,5,6,7,8,9],[1,2,4,2,1,6,3,1,3,2,3,6]]  
ghci> [ [ x | x <- xs, even x ] | xs <- xxs]  
[[2,2,4],[2,4,6,8],[2,4,2,6,2,6]]

{{% /section %}}


{{% section %}}

Tuples

  • (1,2), (3,4,5)
  • Tuple is viewed as type. So this will fail: [(1,2),(8,11,5),(4,5)]
  • Element in tuple can be homogenous: (1, "Hi")

2-Tuples functions

ghci> fst (8,11)  
8  
ghci> fst ("Wow", False)  
"Wow"
ghci> snd (8,11)  
11  
ghci> snd ("Wow", False)  
False

Some more functions

ghci> zip [1,2,3,4,5] [5,5,5,5,5]  
[(1,5),(2,5),(3,5),(4,5),(5,5)]  
ghci> zip [1 .. 5] ["one", "two", "three", "four", "five"]  
[(1,"one"),(2,"two"),(3,"three"),(4,"four"),(5,"five")]
ghci> zip [5,3,2,6,2,7,2,5,4,6,6] ["im","a","turtle"]  
[(5,"im"),(3,"a"),(2,"turtle")]
ghci> zip [1..] ["apple", "orange", "cherry", "mango"]  
[(1,"apple"),(2,"orange"),(3,"cherry"),(4,"mango")]

Putting things together

ghci> let triangles = [ (a,b,c) | c <- [1..10], b <- [1..10], a <- [1..10] ]
ghci> let rightTriangles = [ (a,b,c) | c <- [1..10], b <- [1..c], a <- [1..b], a^2 + b^2 == c^2]
ghci> let rightTriangles' = [ (a,b,c) | c <- [1..10], b <- [1..c], a <- [1..b], a^2 + b^2 == c^2, a+b+c == 24]  
ghci> rightTriangles'  
[(6,8,10)]  

{{% /section %}}