Skip to content
Snippets Groups Projects
Commit 183e3113 authored by Nicolas Lenz's avatar Nicolas Lenz :snowflake:
Browse files

Last part

parent 6040ff0b
No related branches found
No related tags found
No related merge requests found
......@@ -78,7 +78,11 @@ Only usable in patterns, i.e. on *left-hand side* of the `=`!
You can use backticks \` to write functions between their arguments.
## Example: QuickSort
```haskell
(+3) `map` [1,2,3]
```
## Exercise: QuickSort
Sort a `[Int]` using QuickSort!
......
......@@ -8,13 +8,61 @@ Comparable to *interfaces* in object-oriented programming or *traits* in Rust. C
More concrete: Typeclasses ensure that types of that typeclass have certain functions available.
## Example
## Using a typeclass
Let's try `:t (==)`:
```haskell
(==) :: Eq a => a -> a -> Bool
```
That means: `==` works for every type `a` with the typeclass `Eq`. Let's have a look at Eq: `:i Eq`
## Writing a typeclass
Let's extend `double` into a typeclass.
```haskell
class Ratable a where
rate :: a -> String
class Doubleable a where
double :: a -> a
instance Ratable Int where
rate 42 = "Great"
rate _ = "Not so great"
instance Doubleable Int where
double x = x * 2
six = double 3
```
## Caution with polymorphic types
```
{- Won't work!
instance Doubleable String where
double str = str ++ str
-}
```
`String` is a synonym for `[Char]`. Lists are a polymorphic type (`[a]`). In class instances, instantiated type variables are not allowed!
```haskell
-- Instead:
instance Doubleable [a] where
double list = list ++ list
```
## Interesting pre-defined typeclasses
`Eq`, `Ord`, `Read`, `Show`, `Enum`, `Bounded`, `Num`
## Exercise
Implement a typeclass for things that can be given a true or false with a function `boolify` and instanciate it for a few types.
Example:
```
boolify 0 ~> False
boolify 1 ~> True
boolify [] ~> False
boolify [1,2,3,4] ~> True
```
\ No newline at end of file
# Functors
## What is a functor?
Remember map?
```haskell
map :: (a -> b) -> [a] -> [b]
map (+3) [1,2,3]
```
Do something for every element of a list.
## Not only lists
This principle should work for more than lists!
We can use a typeclass to let more things be mapped over.
```haskell
class Functor f where
fmap :: (a -> b) -> f a -> f b
```
There is also `<$>` as short infix variant
## Still works with lists
```haskell
x = (+3) `fmap` [1,2,3]
y = (*2) <$> [10,4,2]
z = (==2) <$> [1,2,3]
a = (==2) <$> (*2) <$> [1,2,3]
```
## What else?
`:i Functor`
`Maybe`, `(,) a`, `(->) r`
**Exercise:** Try around with mapping on `Maybe` and lists. Implement `Functor` for `List`, our own list type.
# Monads
## Burrito
A monad is like a burrito. Any questions left?
## Starting off with functors
- A functor is a *container*
- We can apply functions on the content of the container
- Hence `fmap :: (a -> b) -> f a -> f b`: we take a container containing `a`'s, apply a function `a -> b`, and get a container containing `b`'s
## Monads
- A monad is always also a functor, but with more features
- Therefore: monads are also containers
- A monad `m` has two additional features:
- `return :: a -> m a`: Wraps a bare element in the monad container.
- `(>>=) : m a -> (a -> m b) -> m b` (*"bind"*): Applies a monad function `(a -> m b)` on a monad.
- We can map functions `a -> b` over functors, each element is transformed into another element
- But on monads we can use functions `a -> (m b)`, each returning a whole container by itself!
## Trying it out on lists
Monadic functions `a -> m b` can be chained together
```haskell
x = list >>= \x -> [-x,x] >>= \x -> [x + 1, x + 2]
```
## do-notation
```haskell
dolist :: [Int]
dolist = do
a <- list
b <- [-a, a]
[b+1, b+2]
```
## Understanding IO a little better
`[a]` are monads: A container containing `a`s as alements you can get out with `>>=`.
`IO a` are monads: A container with a *state* containing `a`s as *result* you can get out with `>>=`
```haskell
main :: IO ()
main = do
putStrLn "What is your name?"
name <- getLine
putStrLn ("Hello " ++ name ++ "!")
```
```haskell
putStrLn :: String -> IO ()
getLine :: IO String
```
```haskell
main :: IO ()
main = putStrLn "What is your name?"
>>= \_ -> getLine
>>= \name -> putStrLn ("Hello " ++ name ++ "!")
```
\ No newline at end of file
# Bigger Projects
## Stack
To start a project, you'll want to use *Stack*. Take a look at the docs: <https://docs.haskellstack.org/en/stable/README/>
Stack takes care of everything from installing the correct compiler over downloading packages to building.
Install using your package manager, the Windows installer or the command in the docs.
## Important commands
- `stack new name`
- `stack build`
- `stack exec`
- `stack ghci`
## Important files
- `package.yaml`
- `stack.yaml`
\ No newline at end of file
fortytwo = 42
rateNumber :: Int -> String
rateNumber 42 = "cool"
rateNumber x
| x < fortytwo = "meh"
| x < 100 = "okay"
| otherwise = "great"
data BaseColor = Red | Green | Blue deriving (Show, Eq)
{-
instance Eq BaseColor where
Red == Red = True
Green == Green = True
Blue == Blue = True
_ == _ = False
-}
isPartOfYellow :: BaseColor -> Bool
isPartOfYellow Red = True
isPartOfYellow Green = True
isPartOfYellow Blue = False
isPartOfYellow' :: BaseColor -> Bool
isPartOfYellow' x = case x of
Red -> True
Green -> True
Blue -> False
quicksort :: [Int] -> [Int]
quicksort [] = []
quicksort (x:xs) = quicksort (filter (< x) xs) ++ x : quicksort (filter (>= x) xs)
class Doubleable a where
double :: a -> a
instance Doubleable Int where
double x = x * 2
instance Doubleable [a] where
double list = list ++ list
data Tree a = Empty | Fork a (Tree a) (Tree a) deriving Show
instance Functor Tree where
fmap f Empty = Empty
fmap f (Fork x l r) = Fork (f x) (fmap f l) (fmap f r)
peter :: Tree Int
peter = Fork 3 (Fork 4 Empty Empty) (Fork 6 Empty Empty)
main :: IO ()
-- main = getLine >>= \x -> putStrLn (x ++ x)
main = do
x <- getLine
y <- getLine
putStrLn "hallo"
putStrLn (x ++ x)
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment