Learn you a Haskell for Great Good!

IHaskell-Notebook version 0.21.9

jupyter-notebooks are an interactive 'thing'

I have heard them called:

- 'reproducible-research-thing'
- 'literate-programming-thing'
- 'an-application-thing-that-can-teach-haskell-coding-thing'

I'm partial to the last one ... yeah lets use that one.

To evaluate a code 'cell' denoted with:

**In [ ]:**

select it by clicking on it like this ...'click'
and then press the ~~Shift~~ Ctrl/ and Enter keys at the same time

well... hold the ~~'shift'~~ 'control' key down while hitting the 'enter' key
'shift' return works but also adds a new cell if it can.

This will trigger the ghci-interpreter to parse the input and then cook it down untill it is ready to be a 'printed out responce' using the ghcjs 'thing'.

That is a really high level view of the software. we will dig deeper into this stuff later/ much later ...but for now just remember

'~~Capitalize~~Ctrl/Control+Enter'.

how does a jupyter notebook really work? I have no idea! but is uses python code.

to learn more about this 'jupyter' stuff goto jupyter.org

What is *Haskell* ?

- Haskell is pure
- Haskell is lazy
- Haskell is statically typed ...
- but has
*type inference*

- but has
- Haskell is functional ...
- with
*higher-order-functions*

- with
- Haskell uses immutable data structures
- Haskell is named after 'Haskell Curry'
- Haskell was designed by mostly really smart 'bearded-dudes'
- Haskell is said to be difficult to learn
- because most programmers learned how to program a dumb way

- Haskell has alot of stuff

doesn't seem that hard yet... does it?

In [38]:

```
--programs in haskell are a series of transformations to data.
xs = [1,2,3,4,5,6] -- this is a list of Numbers named xs.
doubleThis x = x * 2 -- this is a function that doubles stuff
map doubleThis xs -- this transfoms our list --sort of
```

In [39]:

```
print xs -- not really remember 'immutable'
```

In [40]:

```
--some really basic arithmetic.
2 + 5
42 + 100
50 + (-8)
84 / 2 --below are the results of this math in order
```

So here is your first assignment:
write a program that multiplies two numbers
and then subracts a number from that product
and then add back another number to equal *42*

x * y - z + q = 42

--lower case letters are just place holders.

In [41]:

```
-- OK! I'll show you!
50 * 100 - 4999 + 41
```

In [42]:

```
-- your turn! oh yeah '--' lines are code comments.
-- Shift+Enter to run your program
```

how did you do?

Ok how about some Boolean algebra?

What!

&& represents logical *and*

|| represents logical *or*

not represents logical *negates*

In [43]:

```
True && False -- should return False
```

In [44]:

```
True && True -- should return True
```

In [45]:

```
False || True -- True
```

In [46]:

```
not False -- catching on?
```

In [47]:

```
-- testing for equality you use '==' double equal
-- testing for un-equal you use '/=' slash equal
5 == 5
5 /= 5
```

Now it's your turn -did you think i was going to do all the programing!

write an expression that uses 'Bools' using if/then/else see if you can get "nice" to print

In [48]:

```
--as in:
if 11 == 10 then "nice" else "oops"
```

In [49]:

```
-- go ahead don't be shy!
-- type some code on next line
--and hit Shift+Enter to evaluate your code
```

Well how did you do? I can't tell cuz your are in the future.......

Up next: An introduction to haskell *List*s

lists are like shopping lists ...sort of

they are *homogenous* meaning all the items need to be
the same type like this:

In [50]:

```
lostNumbers = [4,8,16,23,42] --lostNumbers is a List of values
lostNumbers --prints it out the value
```

In [51]:

```
-- a common task with lists is make one list out of two lists
lostNumbers ++ [100,99,98] -- (++) is concatination
```

In [52]:

```
--or did I?
lostNumbers --eval cell to see a secret message...
```

*Immutable* which is a fancy word for you can
never change a value once it is created... This seems silly at first
but has the number 42 every changed during your life time? Nope! and
it never will.
you have to give the two lists a name to reuse it anywhere. So lets
call our new list say 'newList'

In [53]:

```
newList = lostNumbers ++ [100,99,98]
newList -- will print it out below
```

*the colon* is what we use and it's name is 'cons' which is short for 'construct'.

In [54]:

```
-- Oh yeah a String in haskell is a list of 'char' or characters.
-- 'colon t' is a command that lets you see the 'type' of something
-- types are like HUGE in haskell.
:t "Some string"
-- and its not 'cons' either ...
```

In [55]:

```
-- That double colon in the output above is called 'has type' and has
--nothing to do with 'cons' either
--Here is 'cons'
'A' : " small cat"
--or
42 : [1,2,3]
--how about we stick the cat string onto the 42 list. will that work?
42 : [1,2,3] ++ 'A' : " small cat"
-- go head and try it
```

In [56]:

```
-- lets look at some stuff that is == 'equal' remember Bool?
[1,2,3] == 1:2:3:[]
['a','b','c','d'] == 'a':'b':'c':'d':[]
"abcd" == 'a':'b':'c':'d':[]
```

In [57]:

```
{-
Thats alot of stuff printed out but in the end you see 'True'
why... cuz they are.
the right side is equal to the left side. So it evaluated to 'True'
the right side is 'sugar'd or 'frosted' I like to say!
do you remember 'lazy' yea everyone is!
its just alot less keys to press ... oh my fingers are tired!
OK thats alot of gibber/jabber lets get back to writing haskell
-}
"Steve Buscemi" !! 6
-- what the hell is that 'bang' bang' == !!
-- Shift+Enter to find out....
-- {- blah,blah,blah -} is how you do a block-comment
```

In [58]:

```
-- !! is how you pull out the 'n'th item in a list. computer people
-- start counting at zero,one,two... lazy and fussy are we!
-- lists can contain other lists like this:
[[1,2,3],[10,9,8],[42]]
-- programmers like the number 42 and the word 'foo' I'm not sure why?
```

In [59]:

```
--see if you make a list hold another list or two
--you have to put the comas and braces just SOOOOOO!
myNestedList = undefined
-- replace 'undefined' with your nested list.
-- then Shift+Enter to run it.... I'm not going to tell you that
-- anymore... the shifting thing that is.
```

In [60]:

```
--Lists can also be compared to each other
--using > greater-than, < less-than and >= or <= or == or /=
--Lists are compared in lexicographical ... from the left one at a time.
[3,2,1] > [2,1,0]
[3,2,1] > [2,20,100]
[1,3,42] > [2,4,43]
[2,3,4] /= [2,42,43]
```

In [61]:

```
--see if you can write two lists that are close but not quite equal
--using 'chars' witch are just 'a' or 'G' or 'c' or 'q'
--chars are compared alphabetically so 'a' < 'b' or is it?
'a' > 'b'
'z' > 'a'
-- ['a','c','e'] ? ['a','c', 'f']
-- remove the -- just above and fill in the ? with <,>,==, or @
```

In [62]:

```
--another way to pick apart lists is to use 'head' and 'tail'
head [1,2,3,4]
tail [1,2,3,4]
head [] --what is the head of nothing? oh no more 'red-ink'
```

In [63]:

```
--haskell also has a 'last' function for lists
last [1,2,3,4]
--and 'init'
init [1,2,3,4]
```

In [64]:

```
--'cycle' takes a list and cycles it into an infine list --ooohh!
--'take' trims it off so your computer won't catch on fire!
take 42 (cycle ['a'..'z'])
```

I'm gonna skip over type-classes cuz they are over my head as such! we will revisit them shortly.

Next up is: Function Syntax and specifically 'pattern matching'

In [65]:

```
--you specify a pattern to which some data should conform and if
--it does you 'deconstruct' the data according to those patterns
--trivial example--
lucky :: (Integral a) => a -> String
lucky 7 = "LUCKY NUMBER SEVEN"
lucky x = "Sorry, you're out of luck, pal!"
lucky 42
lucky 7
```

In [66]:

```
--here is how you could use pattern matching to return a number/String
--from guessing from one..five
sayMe :: (Integral a) => a -> String
sayMe 1 = "One!"
sayMe 2 = "Two!"
sayMe 3 = "Three!"
sayMe 4 = "Four!"
sayMe 5 = "Five!"
sayMe x = "Not between 1 and 5"
sayMe 4
sayMe 2
sayMe 42
```

```
factorial :: (Integral a) => a -> a
factorial 0 = 1 -- when factorial matches 0 it returns 1
factorial n = n * factorial (n - 1)
```

calling factorial 3 ...

factorial is not =0 so it tries 3 * factorial 2 ..recurses again

factorial is not =0 so it tries 3 * (2 * factorial 1) ..recures again

factorial is not =0 so it tries 3 * (2 * (1 factorial 0)) ...

here since we defined factorial 0 = 1 our function 'expands/resolves'

into:

3 * (2 * (1 * 0)) --substitute 0 for 1

3 * (2 * (1 * 1)) --reduces to

3 * (2 * 1) --reduces to

3 * 2 --reduces to

6

In [67]:

```
factorial :: (Integral a) => a -> a
factorial 0 = 1 -- when factorial 0 hits is just returns 1 and finishes
factorial n = n * factorial (n - 1)
--more on recursion comming up...
factorial 3
```

In [68]:

```
--patterns must be 'exhaustive'...cover all inputs...
--here is some pattern matching on adding 2 tuples...
addVectors :: (Num a) => (a,a) -> (a,a) -> (a,a) --two pairs for params
addVectors (x1, y1) (x2, y2) = (x1 + x2, y1 + y2)
--and call it with:
addVectors (3,5)(6,2)
```

In [69]:

```
--here is how you DIY --fst/snd for triple-tuples
-- the underscores mean we don't care about that pattern/position
first :: (a, b, c) -> a
first (x, _, _) = x
second :: (a, b, c) -> b
second (_, y, _) = y
third :: (a, b, c) -> c
third (_, _, z) = z
first ('a', 'b', 'c')
second ('a', 'b', 'c')
third ('a', 'b', 'c')
```

In [70]:

```
--here we pattern match on a list-comprehension
xs = [(1,3), (4,3), (2,4), (5,3), (5,6), (3,1)]
[a + b | (a, b) <- xs] -- and xs == the list of tuples above
```

In [71]:

```
--here is DIY head function --remember that cute inch-worm from before
head' :: [a] -> a
head' [] = error "Can't call head on an empty list, dummy!"
head' (x:_) = x
head' [4, 5, 6]
head' ["ghci", "build", "stack"]
head' []
```

In [72]:

```
--your turn... didn't think you had to do any more work ... Not!
--write a function that shows the first and second items in a list
--dont forget to make it 'exhaustive'
--i'll write this much for you:
tell :: (Show a) => [a] -> String
tell [] = "The list is empty"
tell (x:[]) = "The list has one element: " ++ show x
-- show first and second items here
-- show how to handle rest of 5 item list
tell []
tell ['a']
tell ['a', 'b']
tell ['a', 'b', 'c', 'd', 'e']
```

In [73]:

```
--lets try some more stuff with recursion
length' :: (Num b) => [a] -> b
length' [] = 0 --the length of an empty list is 0
length' (_:xs) = 1 + length' xs
--here we chopped of the head and call that 1
--(+) the rest of the list
--basically we keep chopping and adding 1 till we hit the [].
--then add it all up
length' "Ham Bone"
length' "Ham"
length' "Bone"
```

In [74]:

```
--lets do our own version of sum
sum' :: (Num a) => [a] -> a
sum' [] = 0 --sometimes called base-case
sum' (x:xs) = x + sum' xs
--could it be that simple? indeed
sum' [1,2,3,4]
sum' [22,1,1]
```

In [75]:

```
--patterns are kinda like an alias
-- xs@(x:y:ys) --so you can say 'xs' instead of '(x:y:ys)'
--yet another form of lazy :)
capital :: String -> String
capital "" = "Empty String, whoops!"
capital all@(x:xs) =
"The first letter of " ++ all ++ " is " ++ [x]
capital "Dracula"
capital "TacoCat"
```

Instead of explaining 'guards' syntax, lets write some in code

In [76]:

```
--guards provide several bools --first True is eval'd.
bmiTell :: (RealFloat a) => a -> String
bmiTell bmi --no '=' after function name/params
| bmi <= 18.5 = "You're underweight"
| bmi <= 25.0 = "You're supposedly normal"
| bmi <= 30.0 = "You so big you scare my wife!"
| otherwise = "You are a whale congrats!"
--otherwise = True --to make 'exhaustive'
bmiTell 17.5
bmiTell 29.40
bmiTell 42.42
```

In [77]:

```
--lets make our own max function.
--two args must be comparible
max' :: (Ord a) => a -> a -> a
max' a b -- no 'equals-sign'
| a > b = a
| otherwise = b
max' 7 9
max' 10 1
max' 'a' 'z'
```

In [78]:

```
--lets write our own version of compare
:t compare --ghci version
myCompare :: (Ord a) => a -> a -> Ordering
a `myCompare` b --defined as infix `sometimes` is better
| a > b = GT
| a == b = EQ
| otherwise = LT
:t myCompare
compare 3 2
3 `myCompare` 4
myCompare 42 42
```

In [79]:

```
--OK now! -thats how you begin again after finishing and
--aren't sure what's next
--Oh yeah! Where? ...were we...
--'where' can be used with guards to keep things DRY.
--here is our lastest bmi function:
{-
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!"
-}
-- and here it is using 'where'
bmiTell':: (RealFloat a) => a -> a -> String
bmiTell' weight height
| bmi <= 18.5 = "Your underweight,..."
| bmi <= 25.0 = "Your normal, more or less"
| bmi <= 30.0 = "You so fat!"
| otherwise = "Your a whale, conrats"
where bmi = weight / height ^ 2
bmiTell' 85 1.90
```

In [80]:

```
--here is a bmiCalc that returns a list of bmi's
calcBmis :: (RealFloat a) => [(a, a)] -> [a]
calcBmis xs = [bmi w h | (w, h) <- xs]
where bmi weight height = weight / height ^ 2
calcBmis [(85, 1.90),(81, 1.90), (78, 1.90)]
```

In [81]:

```
--'Let it be' was sung by Paul not George!
--'let'<bindings>'in' <expression> haskell is sung by Alanzo C.!
4 * (let a = 9 in a + 1) +2 --see what i mean about 42's
--they can also be used as functions in local scope*
[let square x = x * x in (square 5, square 3, square 2)]
--will this work?
(let a = 100; b = 200; c = 300
in a*b*c,
let foo = "Hey "; bar = "there!"
in foo ++ bar)
```

In [82]:

```
--looks like it did! dammn!
--'lets' look at some more examples
let zoot x y z = x * y + z
zoot 3 9 2
let boot x y z = x * y + z in boot 3 4 2
--is 'boot' still in scope? no- not the mouthwash silly
boot --outside of let expression it is out of scope. don't!
```

In [83]:

```
--both of these are 'interchangeable'
--one is just a sugar frosted version of the other
--guess which ?
head' :: [a] -> a
head' [] = error "Empty lists have no head"
head' (x:_) = x
--or
head_ :: [a] -> a
head_ xs =
case xs of
[] -> error "Empty lists tell no lies"
(x:_) -> x
head' [1,2,3,4]
head_ [2,3,4,5]
head_ []
```

In [84]:

```
--one more case for case's
describeList :: [a] -> String
describeList xs =
"The list is " ++
case xs of
[] -> "empty"
[x] -> "a singleton list"
xs -> "a longer list"
describeList []
describeList [2]
describeList [2,3,4]
```

next up

In [85]:

```
--In haskell recursion is important ... declare what something 'is'
-- not 'how' you get it.
--it is mandatory that we look at the
--fibonacci secquence yet again:
fib 0 = 0
fib 1 = 1
fib n = fib (n-1) + fib (n-2)
fib 20
```

In [86]:

```
--Maximum awesome-ness
--maximum' :: (Ord a) => [a] -> a
maximum_ [] = error "maximum of empty list is just dum!"
maximum_ [x] = x
maximum_ (x:xs) = max x (maximum_ xs)
--maximum of a lsit is the max of head and maximum of tail
:t max
:t maximum_
maximum_ [22,42,33,9]
maximum_ [2,5,7]
max 2 (maximum_ [5,7])
maximum_ [] --look out you dummie!
```

In [87]:

```
--Haskell-prelude version
:t replicate
replicate 3 5
--our DIY version
replicate_ n x
| n <= 0 = []
| otherwise = x:replicate_ (n-1) x
:t replicate_
replicate_ 5 3
```

In [88]:

```
:t take -- prelude version for comparison sake'
take' :: (Num i, Ord i) => i -> [a] -> [a]
take' n _
| n <= 0 = []
take' _ [] = []
take' n (x:xs) = x : take' (n-1) xs
take' 3 [4,3,2,1]
```

In [89]:

```
--reverse simply reverses a list. no kidding wow-wee
:t reverse -- again for comparisonism
reverse' :: [a]-> [a]
reverse' [] = [] -- look a nothing in the rearview mirror/ same-nothing
reverse' (x:xs) = reverse' xs ++ [x] --rev' tail and stick head back on it
reverse' []
reverse' [5,4,3,2,1]
reverse' ['c','b','a']
```

In [90]:

```
--ok now lets look at repeat/repeat/repeat/repeat...
:t repeat -- you know why? don't play dum with me!
repeat' :: a -> [a]
repeat' x = x:repeat' x --could that possibly work? yeah FOREVER!
--thats why you need to 'take' just so much
take 5 (repeat' 3) --now that's better
take 5 repeat' 3 --error take does not take 3 args but two....
--don't even mention repeat is totally 'foo-barred'
```

In [91]:

```
--now comes 'zip' which take two lists and 'zips' them together...
:t zip -- again for compareishness , i like it...
zip' :: [a] -> [b] -> [(a,b)]
zip' _ [] = []
zip' [] _ = []
zip' (x:xs) (y:ys) = (x,y):zip' xs ys --why i never!
zip' [1,2,3] ['a','b','c', 'd']
```

In [92]:

```
-- I've been looking forward to using him!!!
--and now a classic algorIthmism 'Quick-sort'
quicksort :: (Ord a) => [a] -> [a]
quicksort [] = []
quicksort (x:xs) =
let smallerSorted = quicksort [a | a <- xs, a <= x]
biggerSorted = quicksort [a | a <- xs, a > x]
-- |need to be flush @ smaller... and bigger...
in smallerSorted ++ [x] ++ biggerSorted
--tesing 1,2,3
quicksort [10,2,5,3,1,6,7,4,2,3,4,8,9]
quicksort "the quick brown fox jumps over the lazy dog"
-- did not see that comming!
-- for diaramma below
quicksort [5,1,9,4,6,7,3]
```

- this is a direct cut/paste from origin-master l.y.a.h.f.g.g (CL)

So if we have, say [5,1,9,4,6,7,3] and we want to sort it, this algorithm will first take the head, which is 5 and then put it in the middle of two lists that are smaller and bigger than it. So at one point, you'll have [1,4,3] ++ [5] ++ [9,6,7]. We know that once the list is sorted completely, the number 5 will stay in the fourth place since there are 3 numbers lower than it and 3 numbers higher than it. Now, if we sort [1,4,3] and [9,6,7], we have a sorted list! We sort the two lists using the same function. Eventually, we'll break it up so much that we reach empty lists and an empty list is already sorted in a way, by virtue of being empty. Here's an illustration:

a pattern is emerge'n here with this recursion thing

- define your base case
- define your function that does something to an element
- have that same function applied to the rest of the stuff

In [93]:

```
--lets look at some sample code:
max 4 5 == (max 4) 5 --they should be equal
```

In [94]:

```
--partial application or partially applied functions
-- offensively simple version:
multThree :: (Num a) => a -> a -> a -> a
multThree x y z = x * y * z
multTwoWithNine = multThree 9
--call function
multTwoWithNine 2 3
--name a partially applied multTwoWithNine function
multWithEighteen = multTwoWithNine 2
--call new function with one more arg.
multWithEighteen 10
```

In [95]:

```
--lets create a function that takes a number and
--compairs it to 100 and return GT LT or EQ
compareWithHundred :: (Num a, Ord a) => a -> Ordering
compareWithHundred x = compare 100 x
--call with different params
compareWithHundred 99
compareWithHundred 101
compareWithHundred 100
```

In [96]:

```
--the same function can be written this way also:
compareWithHundred' = compare 100
--call function with same args as above
compareWithHundred' 99
compareWithHundred' 101
compareWithHundred' 100
```

In [97]:

```
--Infix functions can also be parially applied using 'sections'
--to section apply parens and only add arg to one side only
--like this:
divideByTen :: (Floating a) => a -> a
divideByTen = (/ 10)
-- call function with other side argument
divideByTen 200
-- same as
200 / 10
-- or
(/10) 200
```

In [98]:

```
--what about just calling multThree 3 4 ... lets see
multThree 3 4
```

In [99]:

```
--that message is saying there is no 'Show' typeclass for the
--function (a0 -> a0)
--just name it 'some' 'thing' and give it the last arg.
--as in:
someThing = multThree 3 4
someThing 1
```

In [100]:

```
-- i love the drunk octopi! not sure why
-- this function takes a function and then applies it twice to
-- 'something' ... not the previous 'some' 'thing'
applyTwice :: (a -> a) -> a -> a
applyTwice f x = f (f x)
-- how would you call this function?
applyTwice (+3) 3
applyTwice (/10) 100
applyTwice (multThree 2 2) 1
applyTwice (3:) [42]
```

In [101]:

```
:t zipWith -- from the mother ship!
```

In [102]:

```
--here is our version
zipWith' :: (a -> b -> c) -> [a] -> [b] -> [c]
zipWith' _ [] _ = []
zipWith' f (x:xs) (y:ys) = f x y : zipWith' f xs ys
-- here is what it can do:
zipWith' (+) [4,2,5,6] [2,6,2,3]
zipWith' max [4,2,5,6] [2,6,2,3]
zipWith' (zipWith' (*)) [[4,2,5,6],[2,6,2,3],[4,2,5,6]]
[[2,6,2,3],[4,2,5,6],[2,6,2,3]]
```

In [103]:

```
flip' :: (a -> b -> c) -> (b -> a -> c)
flip' f = g
where g x y = f y x
-- this is equivalent
flip_ f y x = f x y
```

zip function straight up:

In [104]:

```
zip [1,2,3,4,5] "hello"
```

and then 'flip'd

In [105]:

```
flip' zip [1,2,3,4,5] "hello"
```

In [106]:

```
zipWith div[4,2,5,6] [2,6,2,3]
zipWith (flip' div) [4,2,5,6] [2,6,2,3]
-- not sure what this use case would be ...
```

In [107]:

```
-- map uses a function of (a to b),
-- with an arg of list of [a's]
-- and returns a list of [b's]
:t map -- from prejude
map :: (a -> b) -> [a] -> [b]
map _ [] = []
map f (x:xs) = f x : map f xs
-- lets use it and see what we get...
map (+3) [1,2,3,4,5]
map (^2) [1,2,3,4,5]
map (replicate 4) [3..7]
map fst [(1,4),(3,5),(6,3),(2,6)]
```

In [108]:

```
-- filter uses a predicate function of (True or False),
-- with an arg of list of [a's]
-- and returns list of [a's] that meet the predicate
filter :: (a -> Bool) -> [a] -> [a]
filter _ [] = []
filter p (x:xs)
| p x = x : filter p xs
| otherwise = filter p xs
-- now lets call it some
filter (> 3) [1,2,3,4,5,6,7]
let notNull x = not (null x)
in filter notNull [[1,2,3],[],[3,4,5],[2,2],[],[],[]]
filter (`elem` ['A'..'Z']) "i lauGh At You BecAuse u r aLL the Same"
```

In [109]:

```
:t "GAYBALLS"
-- yeah so "GAYBALLS" is a list of Char so it returning a list.
```

In [110]:

```
--Here is our previous 'Quick-sort' using filter
quicksort_ :: (Ord a) => [a] -> [a]
quicksort_ [] = []
quicksort_ (x:xs) =
let smallerSorted = quicksort_ (filter (<=x) xs)
biggerSorted = quicksort_ (filter (>x) xs)
in smallerSorted ++ [x] ++ biggerSorted
quicksort_ [3,6,5,2,8,9]
```

next in line is

In [111]:

```
--find the sum of all odd squares that are smaller than 10,000
sum (takeWhile (<10000) (filter odd (map (^2) [1..])))
--looks kinda lisp'e with all the closing parens......
```

In [119]:

```
nums = map (^2) [1..]
oddnums = filter odd nums
lastTime = takeWhile (< 10000) oddnums
sum lastTime
```

In [120]:

```
let nums = map (^2)[1..]
filter odd nums = oddnums
lastChunk = takeWhile (< 10000) oddnums
in sum lastChunk
```

Collatz sequencs:

In [114]:

```
chain :: (Integral a) => a -> [a]
chain 1 = [1] --base/edge case
chain n
| even n = n:chain (n `div` 2) --if even divide it by 2
| odd n = n:chain (n * 3 + 1) --if odd do this
-- lets see what it does
chain 5
chain 10
chain 1
chain 30
```

In [115]:

```
numLongChains :: Int
numLongChains =
length (filter isLong (map chain [1..100]))
where isLong xs = length xs > 15
```

In [116]:

```
-- first we 'map chain' to a 'range' to get list of chains
map chain [1..5] --used smaller range for smaller output
-- we need to define isLong function
isLong_ xs = length xs > 15
-- next we 'length filter f map chain' gives num of list you have > 15
length (filter isLong_ (map chain [1..100]))
```

*Lambda* == anonymous function == `(\xs -> length xs > 15)`

In [117]:

```
--since 'isLong' is only used once we could use a 'lambda'
-- a 'lamba is an unnamed function you only use once.
numLongChains_ :: Int
numLongChains_ =
length (filter (\xs -> length xs > 15)(map chain [1..100]))
-- this is a lambda: (\xs -> length xs > 15)
numLongChains_
```

In [15]:

```
listOfFunctions = map (*) [0..] -- [0.. is an infinite list..]
-- (listOfFunctions !! 4) returns partial function == (4)
(listOfFunctions !! 4) 5 -- and multiplies it by (4)5 or 4*5
```

In [12]:

```
zipWith (\a b -> (a * 30 + 3) / b)[5,4,3][1,2,3]
```

In [11]:

```
-- this is long-hand-version of above...
((5 * 30) + 3) / 1
((4 * 30) + 3) / 2
((3 * 30) + 3) / 3
```

In [31]:

```
addThree x y z = x+y+z
addThreeLambda = \x -> \y -> \z -> x+y+z
addThree 1 2 3
addThreeLambda 1 2 3
```