## 2018-07-17

It feels like there are so many great functions available from Haskell and they seem to make a great deal of sense

Like `succ 1` gives `2`, the successor to `1`

I'm used to a method like this being called `add`, but that feels like a function which would mutate and `succ` does not

Composability feels great

Reading about `max` (it makes sense that there's a max function, but I hadn't needed it yet), I wondered if I could adapt it for finding the largest value from a list of numbers

And it went exactly as I'd hoped and thought it might!

Where `max 1 2` gives `2`, `foldr max 0 [1,2,10,3,4]` gives `10`

There's likely a better way to do this (and this example returns `0` if no larger number is found and that's not great), but it's nice that such a thing is so simple

Composing functions is fun

`add x y = x + y` is the same as `add = (+)`

They both take two arguments and return their sum

Except they aren't the same because the former is a function and the latter is a definition

``````one = 1
// 2
``````

I'm not yet sure how this compares to variables in other languages, but I have some hunches

Trailing apostrophes in function names is a convention to denote strictness (non-laziness) or a slightly modified version of the non apostrophe'd name

I don't know what strictness looks like yet

Lists (`[1,2,3]`) are homogenous data structures (no mixing types)

`++` is used for concatenation

`[1] ++ [2]` gives `[1,2]`

And strings are just lists of characters so

`"Hello," ++ " " ++ "World!"` gives `Hello, World!`

`foldr (++) [] ["Hello,", " ", "World!"]` also works (I'm going to keep coming back to `foldr`, aren't I)

`++` walks through the entire first list before appending. Yikes

`:`, known as the cons operator, adds a thing to the beginning of a list and is apparently much more efficient

`1:2:3:[] == [1,2,3]`

`foldr (:) "" ['o', 'k', 'a', 'y'] == "okay"`

Getting an element at an index is accomplished with `!!`

`['o','k','a','y'] !! 0 == 'o'`

Alright I'm kind of shook here...

`head' = (!! 0)` works? You can pass arguments in upfront? Dang

## 2018-07-24

Using comparators on lists is interesting

``````[1, 1] > [1] -- because 1 and 1 are the same and then 1 is greater than nothing
[1, 3] > [1, 2] -- because 1 and 1 are the same and then 3 is greater than 2
[0] > [] -- because 0 is greater than nothing
``````

And there are many functions for working with lists

``````head [0, 1, 2, 3, 4]
-- 0
tail [0, 1, 2, 3, 4]
-- [1, 2, 3, 4]
init [0, 1, 2, 3, 4]
-- [0, 1, 2, 3]
last [0, 1, 2, 3, 4]
-- 4

-- Exception
``````
``````length [0, 1, 2, 3, 4]
-- 5
``````
``````null []
-- True
null [1]
-- False
``````
``````reverse [0, 1, 2, 3, 4]
-- [4, 3, 2, 1, 0]
``````
``````take 2 [0, 1, 2, 3, 4]
-- [0, 1]
take 0 [0, 1, 2, 3, 4]
-- []
take 10 [0, 1, 2, 3, 4]
-- [0, 1, 2, 3, 4]

drop 2 [0, 1, 2, 3, 4]
-- [2, 3, 4]
drop 0 [0, 1, 2, 3, 4]
-- [0, 1, 2, 3, 4]
drop 10 [0, 1, 2, 3, 4]
-- []
``````
``````maximum [0, 1, 2, 3, 4]
-- 4
minimum [0, 1, 2, 3, 4]
-- 0
``````
``````sum [0, 1, 2, 3, 4]
-- 10
product [0, 1, 2, 3, 4]
-- 0
``````
``````0 `elem` [0, 1, 2, 3, 4]
-- True
5 `elem` [0, 1, 2, 3, 4]
-- False
``````

Ranges seem very friendly

``````[0..4]
-- [0, 1, 2, 3, 4]
['a'..'e']
-- "abcde"
['F'..'J']
-- "FGHIJ"
``````
``````[0, 3..9]
-- [0, 3, 6, 9]
['A', 'C'.. 'Z']
-- "ACEGIKMOQSUWY"
``````

Different ways to get the first ten multiples of 3

``````[3, 6..3*10] == take 10 [3,6..]
-- True
``````

And there are methods for generating lists...

``````take 5 (cycle "LO")
-- "LOLOL"

take 5 (repeat 'A') -- repeat 'A' creates an infinite list
-- "AAAAA"

replicate 5 'A' -- replicate 5 'A' creates a list of five As
-- "AAAAA"
``````

## 2018-07-31

List comprehensions are amazing and I don't appreciate having had to live without them for so long

``````[x*2 | x <- [1..3]]
-- [2,4,6]
``````

Here's an example with a predicate which filters out even numbers

``````[x | x <- [1..10], odd x]
``````

You can also draw from multiple lists getting every possible combination consisting of one value from each list

``````let nouns = ["coffee", "notebook", "headphones"]
let adjectives = ["iced", "fresh", "loud"]
[a ++ " " ++ n | a <- adjectives, n <- nouns]
``````

And values from a list fed into a list comprehension don't need to be used

In this example, `length'` takes a list and converts each of its members to `1` and then adds them together producing the length of the list

``````length' xs = sum [1 | _ <- xs]
``````

Nested list comprehensions are a thing too!

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

Tuples are fixed size and used for storing heterogenous elements as a single value

``````(1, 'A')
``````

A tuple of size two is called a pair and a tuple of size three is called a triple

Tuples of a type must be consistent

``````-- This won't work because the first value in the first pair is a list of characters while the first value in the second pair is a list of numbers
[("foo", 1), ([1,2,3], 2)]
``````

There are some handy functions for working specifically with pairs like `fst` and `snd`

``````fst (1,'A') -- 1
snd (1,'A') -- 'A'
``````

`zip` takes one item at a time from two lists to create tuples until one of the lists is exhausted

``````zip [1..10] [1..]
-- [(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9),(10,10)]
``````

I'm taking this next exercise on finding right triangles verbatim from Learn You a Haskell

``````-- First we're generating all the triples with integers less than or equal to i
-- 10
[ (a,b,c) | c <- [1..10], a <- [1..10], b <- [1..10]]

-- Then we're adding a predicate to check if the triangles are right triangles
-- by checking that `a^2 + b^2 == c^2`
-- We're also only checking triples where a is less than c because the
-- hypotenuse of a right triangle is always its longest side and we're only
-- checking triples where b is less than a because otherwise we'd end up with
-- duplicated triples
[ (a,b,c) | c <- [1..10], a <- [1..c], b <- [1..a], a^2 + b^2 == c^2]

-- Finally we're adding another predicate to ensure that the sum of the length
-- of the sides is 24 (this is an arbitrary constraint)
[ (a,b,c) | c <- [1..10], a <- [1..c], b <- [1..a], a^2 + b^2 == c^2, a+b+c == 24]
``````

## 2018-08-07

In Haskell, every expression's type is known at compile time

Unlike some other languages, Haskell has type inference, so it knows a number is a number without being told it's a number

`:t` follow by an expression, like `:t ('A', 1)`, provides the type of that expression

I've been using it a lot as I learn and it's great but also confusing when it says a thing I do understand is a type I don't understand making me suspect that I don't truly understand the thing at all

`::` is used to describe what type a thing has in code

``````addThree :: Int -> Int -> Int -> Int
addThree x y z = x + y + z
``````

`Int` is an integer with bounds `Integer` is an integer without bounds, so it can be used for larger numbers, but it's less efficient than `Int`

`Float` is a floating-point number with single precision `Double` is a floating-point number with double precision (more precise, less performant)

`Bool` is `True` or `False`

`Char` is a unicode character

Tuples have theoretically infinite type possibilities

Haskell supports polymorphic functions which use type variables such as the built-in `head`

``````:t head
``````

Haskell has Type Classes like `Eq`, which means the thing can be called with `==` and `/=`, and `Show`, which means the thing can be called with `show`

`show` converts a thing to a string, `read`, implemented on members of the `Read` class, converts a string into a thing

``````show 1
-- "1"
-- 2
``````

## 2018-08-14

When using `read` to convert a string into another type, type annotations are helpful

``````read "1.0" -- *** Exception: Prelude.read: no parse
read "1.0" :: Float -- 1.0

read "('A', 0)" :: (Char, Int) -- ('A',0)
``````

`()`, `Bool`, `Char`, `Ordering`, `Int`, `Integer`, `Float`, and `Double` are all members of the `Enum` type class

This means that they are all enumerable, so each instance can be called with `succ` and `pred` and they can all compose ranges

The `Bounded` type class have an upper and lower bound

``````maxBound :: Int -- 9223372036854775807
``````

Tuples whose components are all instances of `Bounded` are also considered instances of `Bounded`

``````maxBound :: (Int, Char) -- (9223372036854775807,'\\1114111')
``````

Instances of `Num` act like numbers and are all also members of `Show` and `Eq`

Whole numbers are polymorphic constants

``````:t 100 -- 100 :: Num p => p

-- so

100 :: Float -- 100.0
-- and
(100 :: Double) * (100 :: Double) -- 10000.0
-- because
:t (*) -- (*) :: Num a => a -> a -> a
``````

The `Floating` class includes `Float` and `Double`

`sin`, `cos`, and `sqrt` require instances of `Floating`

The `Integral` class includes `Int` and `Integer`

Integral numbers are whole numbers

`fromIntegral` converts `Integral`s into `Floating`s

``````(read "1" :: Int) + 2.5 -- 3.5
``````

## 2018-08-21

Pattern matching is great, definitely cuts down on if/else branching

``````one :: Int -> String
one 1 = "Yay!"
one _ = "Oh no"

one 1 -- Yay!
one 0 -- Oh no
``````

Patterns are matched in order, so a catchall should always come last

If there is no catchall, function calls can error, so probably just include a catchall

Tuple pattern matching works like destructuring so

``````wrap :: (String, String) -> String -> String
wrap (x, z) y = x ++ y ++ z
wrap ("(", ")") "hey" -- "(hey)"
``````

This works on various sizes of tuples

The `(x:_)` or `(x:xs)` syntax is very helpful for recursing with a list and also simple things like `head`

``````head' (x:_) = x

``````

As-patterns are cool -- you get your destructured elements as well as a reference to the original argument

``````firstLetter :: String -> String
firstLetter [email protected](x:_) = "The first letter of " ++ xs ++ " is " ++ [x]
firstLetter "trebuchet" -- The first letter of trebuchet is t
``````

Guards are neat -- they're like a compromise between pattern matching and if/else

``````one :: Int -> String
one x
| x == 1    = "Yay!"
| otherwise = "Oh no"
``````

They work on boolean expressions, can handle multiple arguments

`where` is used to store values so they aren't re-calculated unnecessarily

``````sumIs :: [Int] -> String
sumIs xs
| s < 0          = "Less than zero!"
| s `mod` 2 == 0 = "Even!"
| otherwise      = "Odd!"
where s = sum xs

sumIs [1,2] -- Odd!
sumIs [1,2,3] -- Even!
sumIs [-10] -- Less than zero!
``````

Multiple `where` values can be provided in the same block

## 2018-08-28

`let`/`in` expressions are similar to `where` but don't span across guards

``````quadruple :: Int -> Int
quadruple x = let double = x * 2 in double * 2
``````

They're also usable in more places, like pretty much anywhere

``````squaresOver50 :: [Int] -> [Int]
squaresOver50 xs = [ sq | x <- xs, let sq = x * x, sq > 50 ]

squaresOver50 [1..10] -- [64,81,100]
``````

## 2018-09-06

Case expressions are fun

``````one :: Int -> String
one x = case x of 1 -> "Yay!"
_ -> "Oh no"

one 1 -- Yay!
one 0 -- Oh no
``````

``````repeat' x = x:repeat' x
take 10 (repeat' 'A') -- AAAAAAAAAA
``````

Recursion works how you would expect in a lazy environment