diff --git a/3-99 Research/Haskell/Chapter 2 - Starting Out.md b/3-99 Research/Haskell/Chapter 2 - Starting Out.md new file mode 100644 index 00000000..9c696bce --- /dev/null +++ b/3-99 Research/Haskell/Chapter 2 - Starting Out.md @@ -0,0 +1,124 @@ +# What the Hell am I doing? +Learning about GHCI! + +One caveat: doing negative numbers + +5 * -3 will cause issues because it's not clear what '-' actually represents... +Does it mean subtraction or negation? +5 * (-3) fixes this issue. + +## Boolean Stuff +'&&' means 'and' +'||' means 'or' +'not' is a negation + +Types are also the law of the land here. You can't mix and match types across operations they're not specified for already. +This makes sense and is intuitive. Some expressions like '5' can take multiple types though, for example being an integer or a float. + +## A quick note on functions +*infix* functions are those that go in between arguments +- e.g 5+10 +- or 2*2.3 + +*prefix* functions are those that go *before* arguments. They are more common with non number types +- succ 0 +- min 9 10 + +You can also make prefix functions with two arguments into infix functions when you want. Here's an example +- div 92 10 +This integral divides 92 by 10, yielding 9. But at first glance, it is not clear what is the divisor. So instead we can write +- 92 'div' 10 +This is easy and more clear for some applications. + +# Baby's First Functions +1. I created my first Haskell program! It is called 'baby.hs' +2. It gets loaded into GHCI by doing ':l baby' +3. Now I created 'doubleUs', and loaded it the same way + I notice that things are 'a' type. They accept floats and integers no problem... +4. Now, we can rewrite 'doubleUs' +```haskell +doubleUs x y = doubleMe x + doubleMe y +``` +This makes things flexible! We know too that doubleMe is obviously correct, so we don't have to spend more time making sure our implementation in doubleUs is correct too. + +Notably, functions are not ordered in a Haskell script. It does not matter if doubleUs comes before or after doubleMe. + +## if - then - else +Haskell REQUIRES an else statement. This is because functions are complete, and therefore they must return *something*. + +## Function Names are Funky +also, ' is a perfectly valid character in naming things in Haskell. It is usually used for a couple of reasons +1. To denote that a function is 'strict', that is to say not lazy +2. To denote a slightly modified version of a function + +The other notable thing about function names: they can't begin with capital letters. + +Functions that don't take any parameters are **definitions** or **names**. + +# An intro to lists +Lists in Haskell are *homogenous*. Every element in a list is the same data type. + +Lists can be easily concatenated with '++'. This has a weird feature though in that Haskell cycles through the whole list on the LHS before concatenating. This can take a long time with bigger lists. + +':' can sometimes solve this issue by putting the thing to be added right at the front of a list. This is instantaneous in comparison. + +Lists can be indexed by '!!'. Indexes start at 0. + +Lists, if their elements can be compared, are comparable. They are an 'all' comparison by default, first from the head and then by each element therafter. They return a SINGLE true or false. + +## Here's some basic list operations: +Head: The first entry +Tail: Everything but the head +Init: Everything but the last +Last: Take a guess, Einstein. + +length: says the length! +null: checks if the list is empty ('[]') +reverse: Reverses the list +take n: takes n first elements from the list. If n is greater than length(list), it only returns the whole list +drop n: does the opposite of take, drops n elements from the beginning of the list +maximum or minimum: expected +sum, product: expected +elem thing list: elem takes a thing, and looks for it in the list. If it is, it returns true. if not, false. + +## Ranges +Ranges can be created using '..'. +[1..20] is all integers from 1 to 20 +['a'..'z'] is all letters from a to z + +Ranges can also be a little more clever and use a step: +[1,2..20] gives all EVEN numbers 1 to 20. +[3,6..20] gives all multiples of 3 between 3 and 20. + +[1,2,4,8,16..100] will NOT work however, because you cn only specify one step. + +Ranges don't work backwards by default. A step must be specified: +[20..1] FAIL +[20,19..1] pass! + +Floats can get funky in ranges +[0.1, 0.3..1] yields [0.1,0.3,0.5,0.7,0.899999999999999,1.099999999999999999]... weird. + +Infinite ranges are also a thing. [13,26..] is a totally valid statement. Because Haskell is 'lazy', we can say take 24 [13,25..] and get the first 24 elements of this range. + +cycle takes a list and cycles it into an infinite list. This let's take work ad infinitium. +repeat does a similar thing but only with one element. But replicate does this too and is arguably easier +replicate n x = [x,x..x] where length [x,x..x] = n + +## List Comprehensions +They're very similar to set building notation. +```haskell +-- instead of the following +take 10 [2, 4..] + +-- we can write +[x*2 | x <- [1..10]] + +-- we can also add predicates +[x*2 | x <- [1.10], x*2 >= 12] +-- will only yield even numbers greater than 12 in the first 10 elements of the set +``` + +I made it to boomBangs and stopped. I'm outta gas :) + + diff --git a/3-99 Research/Haskell/baby.hs b/3-99 Research/Haskell/baby.hs new file mode 100644 index 00000000..d75553a1 --- /dev/null +++ b/3-99 Research/Haskell/baby.hs @@ -0,0 +1,9 @@ +doubleMe x = x + x + +doubleUs x y = doubleMe x + doubleMe y + +doubleSmallNumber x = if x > 100 + then x + else x*2 + +doubleSmallNumber' x = (if x > 100 then x else x*2) + 1