diff --git a/src/02-what-is-functional-programming.md b/src/02-what-is-functional-programming.md index 4d8372267cb5fd49b1c79cf124095e70c4cca66b..ed38d14d5ebfa24645e83d59accc726ce230b1af 100644 --- a/src/02-what-is-functional-programming.md +++ b/src/02-what-is-functional-programming.md @@ -20,7 +20,7 @@ do_another_thing(x, y) - In functional programming a program is no list of commands - More a *collection of definitions* -``` +```haskell x = 4 x = 2 ``` diff --git a/src/04-first-types.md b/src/04-first-types.md index 3f8f5159c7fe1a0e9b7f758cf3a003e09e0d5e96..9f6e1ef3fb34f375077d5e44a83919568aca08e0 100644 --- a/src/04-first-types.md +++ b/src/04-first-types.md @@ -8,7 +8,7 @@ ## Basic Types in Haskell - `Int`: Integer numbers (`-1`, `0`, `30`) -- `Boolean`: Truth values (`True`, `False`) (*capitalized!*) +- `Bool`: Truth values (`True`, `False`) (*capitalized!*) - `Char`: Single characters (`'a'`, `'c'`) - `String`: Text (`"Hello"`, `"Cheese sandwich"`) - `a -> b`: Function with the diff --git a/src/05-first-logic.md b/src/05-first-logic.md index 280eeb7ede4e6a688c5f067fa3e5f61b59bfe829..c9cf4abe456a2dab521c93431757945546a44964 100644 --- a/src/05-first-logic.md +++ b/src/05-first-logic.md @@ -25,9 +25,9 @@ double x = "calculate it yourself" Pattern matching can "disassemble" values ```haskell -tail :: [Int] -> [Int] -tail [] = [] -tail (x:xs) = xs +tail' :: [Int] -> [Int] +tail' [] = [] +tail' (x:xs) = xs ``` diff --git a/src/06-finding-documentation.md b/src/06-finding-documentation.md index 43bd511c6101c7392cbb00078697d614cacaf912..4c50c931e1162c23048261b71350c7a190bdfe6d 100644 --- a/src/06-finding-documentation.md +++ b/src/06-finding-documentation.md @@ -2,4 +2,11 @@ ## Hoogle -https://hoogle.haskell.org/ +Search for functions, types, typeclasses, modules, ... by name or type + +- <https://hoogle.haskell.org/> (general) +- <https://www.stackage.org/> (for Stack) + +**Example:** I want a function that returns the first element of a list of numbers. I don't know the name of the function. + +But I can search for it by its type `[Int] -> Int`! diff --git a/src/07-first-modules.md b/src/07-first-modules.md new file mode 100644 index 0000000000000000000000000000000000000000..64ba2e7364b1bb06ad842861bc690183da5332ac --- /dev/null +++ b/src/07-first-modules.md @@ -0,0 +1,13 @@ +# Modules + +## Modules + +You found a function on Hoogle that is in the module `Data.List`? + +```haskell +import Data.List +``` + +By default only modules from the `base` package are available though. + +More about modules, packages and project management later! diff --git a/src/07-simple-io.md b/src/07-simple-io.md deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/src/08-higher-order.md b/src/08-higher-order.md deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/src/08-simple-io.md b/src/08-simple-io.md new file mode 100644 index 0000000000000000000000000000000000000000..dd0fbd2e635e23f68d689ea27feafec82996d72c --- /dev/null +++ b/src/08-simple-io.md @@ -0,0 +1,13 @@ +# Simple IO + +## Simple IO + +How to make an executable/interactive program? + +```haskell +main :: IO () +main = do + putStrLn "What is your name?" + name <- getLine + putStrLn ("Hello " ++ name ++ "!") +``` diff --git a/src/09-higher-order.md b/src/09-higher-order.md new file mode 100644 index 0000000000000000000000000000000000000000..72d54570a83adecff3727fbe4cc4f2bff9ff8a89 --- /dev/null +++ b/src/09-higher-order.md @@ -0,0 +1,5 @@ +# Higher Order Functions + +## Examples + +`map` & `filter` diff --git a/src/10-types.md b/src/10-types.md new file mode 100644 index 0000000000000000000000000000000000000000..bdef767fe4372cd0425bd5d215571e0ad5ccf8de --- /dev/null +++ b/src/10-types.md @@ -0,0 +1,118 @@ +# Types + +## What is a type? + +Let's recapture: Types classify and restrict values. + +For example: The type of booleans `Bool`. + +A Boolean is always either `True` or `False`. + +## Sum Types + +We see: a type can allow multiple values. These are called *sum types*. They are defined using `data` and `|`. + +(Just accept `deriving Show` for now, it will be explained in the next chapter) + +```haskell +data BaseColor = Red | Green | Blue deriving Show + +v1 :: BaseColor +v1 = Green + +v2 :: BaseColor +v2 = Blue +``` + +## Matching Sum Types + +Pattern maching now works! + +```haskell +isPartOfYellow :: BaseColor -> Bool +isPartOfYellow Red = True +isPartOfYellow Green = True +isPartOfYellow Blue = False +``` + +## Product Types + +But what if values should carry other values (like *"attributes"*)? + +Types can "include" other types. These are called *product types*. Sum and product types can be combined. + +```haskell +data Degree = Bachelor | Master deriving Show +data Student = Student String String Degree deriving Show +data Device = Phone Int | Fridge String | Printer deriving Show + +me :: Student +me = Student "Nicolas Lenz" "Computer Science" Master + +notMe :: Student +notMe = Student "Horst-Dieter Müller" "Philosophy" Bachelor + +myDevice :: Device +myDevice = Fridge "Bosch" +``` + +## Matching Product Types + +Pattern matching also works here. + +```haskell +isComputerScienceMaster :: Student -> Bool +isComputerScienceMaster (Student name "Computer Science" Master) = True +isComputerScienceMaster (Student name field degree) = False +``` + +## Type Variables + +Previously: + +```haskell +tail' :: [Int] -> [Int] +tail' [] = [] +tail' (x:xs) = xs +``` + +Only works on `Int`. We can simply use a type variable! + +```haskell +tail'' :: [a] -> [a] +tail'' [] = [] +tail'' (x:xs) = xs +``` + +## Polymorphic Types + +Type variables can also be used in types. + +```haskell +data Rated a = Good a | Bad a deriving Show + +rate :: Int -> Rated Int +rate 42 = Good 42 +rate x = Bad x +``` + +## Recursive Types + +Remember lists of type `a`, `[a]`? + +A list is always either +- *an empty list* or +- *an element added in front of another list*. + +## Making the List Type + +```haskell +data List a = Empty | Cons a (List a) deriving Show + +list :: List Int +list = Cons 1 (Cons 2 (Cons 3 Empty)) + +listToList :: [a] -> List a +listToList [] = Empty +listToList (x : xs) = Cons x (listToList xs) +``` diff --git a/src/11-more-functions.md b/src/11-more-functions.md new file mode 100644 index 0000000000000000000000000000000000000000..e5b203c3351c85dd6e54252dd3e174c2c33d2c77 --- /dev/null +++ b/src/11-more-functions.md @@ -0,0 +1,100 @@ +# More Functions + +## Comments + +```haskell +x = 5 -- five + +{- +multi-line comment! +-} +``` + +## where & let + +`where` and `let` can be used for helper definitions. + +```haskell +areaCircle :: Int -> Int +areaCircle r = p * (r ^ 2) where p = 3 + +areaCircle' :: Int -> Int +areaCircle' r = let p = 3 in p * (r ^ 2) +``` + +`where` is only a syntactic construct, `let .. in ..` is an expression itself and can be used pretty much everywhere (like `if .. then .. else ..`). + +(Please use `pi` instead of `3`) + +## Guards + +Fancier if-alternative, like a switch + +```haskell +rateNumber :: Int -> String +rateNumber x + | x < 42 = "meh" + | x == 42 = "cool" + | x < 100 = "okay" + | otherwise = "great" +``` + +## case + +Pattern matching as expression + +```haskell +isPartOfYellow :: BaseColor +isPartOfYellow Red = True +isPartOfYellow Green = True +isPartOfYellow Blue = False + +isPartOfYellowCase :: BaseColor +isPartOfYellowCase x = case x of + Red -> True + Green -> True + Blue -> False +``` + +## Pattern Matching vs. Conditions + +Note that function definitions and case definitions use pattern matching (e.g. can't use comparisons and functions, but disassemble values and assign parts to variables) + +ifs and guards check boolean conditions (e.g. can use comparisons and functions, but not assign to variables) + +## Wildcard + +You can discard unwanted values in pattern matching with the wildcard `_`: + +```haskell +isComputerScienceMaster :: Student -> Bool +isComputerScienceMaster (Student _ "Computer Science" Master) = True +isComputerScienceMaster (Student _ _ _) = False +``` + +Only usable in patterns, i.e. on *left-hand side* of the `=`! + +## Infix + +You can use backticks \` to write functions between their arguments. + +## Example: QuickSort + +Sort a `[Int]` using QuickSort! + +- Take the first element of a list `p` +- Return QuickSort recursively on all elements smaller than `p` +- Then `p` itself +- Then the recursively sorted bigger elements +- An empty list is already sorted + +## A Solution + +```haskell +quicksort :: [Int] -> [Int] +quicksort [] = [] +quicksort (p:xs) = (quicksort lesser) ++ [p] ++ (quicksort greater) + where + lesser = filter (< p) xs + greater = filter (>= p) xs +``` diff --git a/src/12-typeclasses.md b/src/12-typeclasses.md new file mode 100644 index 0000000000000000000000000000000000000000..62f6d906c422cf2b12ce1b8b5864807524e22401 --- /dev/null +++ b/src/12-typeclasses.md @@ -0,0 +1,20 @@ +# Typeclasses + +## What are typeclasses? + +Typeclasses in Haskell are a way of assigning "features" or "abilities" to types. + +Comparable to *interfaces* in object-oriented programming or *traits* in Rust. Caution: they have nothing to do with object-oriented classes! + +More concrete: Typeclasses ensure that types of that typeclass have certain functions available. + +## Example + +```haskell +class Ratable a where + rate :: a -> String + +instance Ratable Int where + rate 42 = "Great" + rate _ = "Not so great" +```