forked from steger/pr3-sose2026
132 lines
6.9 KiB
Markdown
132 lines
6.9 KiB
Markdown
# Haskell - Expressions
|
|
|
|
The following illustrates some haskell basics. It can be reproduced using `ghci`.
|
|
|
|
## Types, Literals, and Constants along with Arithmetic and Boolean Operations
|
|
|
|
Expression | Type (:t) | Value | Comment
|
|
--- | --- | --- | --------
|
|
`2` | `Num a => a` | `2` |
|
|
`2.03` | `Fractional a => a` | `2.03` |
|
|
`'c'` | `Char` | `'c'`
|
|
`"hallo"` | `String` | `"hallo"` |
|
|
`True` | `Bool` | `True` |
|
|
`x=5` | `Num a => a` | `5` | Constant named `x`
|
|
`2 + 3` | `Num a => a` | `5` | Similar `-,*,^`
|
|
`2 / 3` | `Fractional a => a` | `0.6666666666666666` |
|
|
`1 > 2` | `Bool` | `False` | Similar `<, <=, >=, ==, /=`
|
|
`True && False` | `Bool` | `False` | Similar `\|\|,not`
|
|
`((2+3)*5 > 1) \|\| not (1 > 2)` | `Bool` | `True` | Right part is not evaluated due to lazy evaluation
|
|
|
|
## Unary Functions
|
|
|
|
Expression | Type (:t) | Value | Comment
|
|
--- | --- | --- | --------
|
|
`sqrt(4)` | `Floating a => a` | `2.0` |
|
|
`sqrt 4` | `Floating a => a` | `2.0` | Similar `abs,negate,signum,recip`
|
|
`sqrt` | `Floating a => a -> a` | |
|
|
`sqrt 3^2 + 4^2` | `Floating a => a` | `19.0` |
|
|
`sqrt (3^2 + 4^2)` | `Floating a => a` | `5.0` |
|
|
`negate(sqrt (3^2 + 4^2))` | `Floating a => a` | `-5.0` |
|
|
`negate $ sqrt (3^2 + 4^2)` | `Floating a => a`| `-5.0` | Function **application** operator `$`
|
|
`(negate . sqrt) (3^2 + 4^2)`| `Floating a => a`| `-5.0` | Function **composition** operator `.` Reads `negate` **after** `negate . sqrt` |
|
|
`(negate . length) "hallo"` | `Int` | `-5` |
|
|
`negatedRoot = negate . sqrt` | `Floating c => c -> c` | | Constant named `negatedRoot`
|
|
|
|
## Binary Functions
|
|
|
|
Expression | Type (:t) | Value | Comment
|
|
--- | --- | --- | --------
|
|
`div 8 4` | `Integral a => a` | `2` | Similar `mod,gcd,lcm,not`
|
|
``8 `div` 4`` | `Integral a => a` | `2` | **Infix** notation using backticks
|
|
`8 + 4` | `Num a => a` | `12` | `-,*,^,<, <=, >=, ==, /=`
|
|
`(+) 8 4` | `Num a => a` | `12` | **Prefix** notation using parenthesis
|
|
`div` | `Integral a => a -> a -> a` | | **Currying** represents multi-argument functions as a chain of single-argument functions |
|
|
`div 8` | `Integral a => a -> a` | | binds the **first** argument; Similar `(8/),(8*),(8+),(8-)` |
|
|
`div8bySomething = div 8` | `Integral a => a -> a` | |
|
|
`div8bySomething 4` | `Integral a => a` | `2` |
|
|
`uncurry div` | `Integral c => (c, c) -> c` | | accepts a single tuple argument
|
|
`uncurry div (8,4)` | `Integral c => c` | `2` |
|
|
`uncurry` | `(a -> b -> c) -> (a, b) -> c`| |
|
|
`` (`div` 4) `` | `Integral a => a -> a` | | **Sectioning** binds the **second** argument of infix functions; Similar `(/8),(*8),(+8),(-8)` |
|
|
``divSomethingBy4 = (`div` 4)`` | `Integral a => a -> a` | |
|
|
`divSomethingBy4 8` | `Integral a => a` | `2` |
|
|
`const` | `a -> b -> a` | |
|
|
`const 8` | `Num a => b -> a` | | function that ignores the input and always returns 8
|
|
`const 8 4` | `Num a => a` | `8` |
|
|
|
|
## Tuples
|
|
|
|
Expression | Type (:t) | Value | Comment
|
|
--- | --- | --- | --------
|
|
`(1, 2)` | `(Num a, Num b) => (a, b)` | `(1, 2)` |
|
|
`(1, "hello", True)` | `(Num a => (a, String, Bool)` | `(1, "hello", True)` |
|
|
`fst (1, 2)` | `Num a => a` | `1` |
|
|
`snd (1, 2)` | `Num b => b` | `2` |
|
|
`(,) 1 2` | `Num a => a -> a -> (a, a)` | `(1, 2)` |
|
|
|
|
## Strings
|
|
|
|
Expression | Type (:t) | Value | Comment
|
|
--- | --- | --- | --------
|
|
`"hello" ++ " world"` | `String` | `"hello world"` | String concatenation
|
|
`length "hello"` | `Int` | `5` | Length of the string
|
|
`null ""` | `Bool` | `True` | Checks if the string is empty
|
|
|
|
## Control Structures
|
|
|
|
Expression | Type (:t) | Value | Comment
|
|
--- | --- | --- | --------
|
|
`if 10/2==5 then "five" else "something else"` | `String` | `"five"` |
|
|
`case 1 of { 1 -> "small"; 2 -> "medium"; _ -> "large"}` | `String` | `"small"` | patterns are overlapping
|
|
`(let x = 5*2 in (x * 2,x /2))` | `(Fractional b, Num a) => (a, b)` | `(20,5.0)` |
|
|
|
|
## Lists
|
|
|
|
Expression | Type (:t) | Value | Comment
|
|
--- | --- | --- | --------
|
|
`[]` | `[a]` | `[]` |
|
|
`1:7:4:[]` | `Num a => [a]` | `[1,7,4]` | actual construction of a list
|
|
`[1,7,4]` | `Num a => [a]` | `[1,7,4]` |
|
|
`8 : [1,7,4]` | `Num a => [a]` | `[8,1,7,4]` | **cons** operator, short for construct
|
|
`[1,7,4]` | `[Num a] => [a]` | `[1,7,4]` |
|
|
`(++)` | `[a] -> [a] -> [a]` | |
|
|
`[1,7,4] ++ [8]` | `Num a => [a]` | `[1,7,4,8]` |
|
|
`[1,7,4] !! 2` | `Num a => [a]` | `4` |
|
|
`(!!)` | `[a] -> Int -> a` | |
|
|
`head [1,7,4]` | `Num a => a` | `1` | Similar `last`
|
|
`tail [1,7,4]` | `[Num a] => [a]` | `[7,4]` | Similar `init`
|
|
`length [1,7,4]` | `Int` | `3` |
|
|
`null []` | `Bool` | `True` |
|
|
`reverse [1,7,4]` | `[Num a] => [a]` | `[4,7,1]` | Similar `Data.List.sort`
|
|
`take 2 [1,7,4]` | `[Num a]=>[a]` | `[1,7]` | Similar `drop`
|
|
`take` | `Int -> [a] -> [a]` | |
|
|
`sum [1,7,4]` | `Num a=>a` | `12` | Similar `product,maximum,minimum,length`
|
|
`foldl (-) 0 [1,7,4]` | `Num a => a` | `-12` | `(((0-1)-7)-4)`
|
|
`foldl` | `Foldable t => (b -> a -> b) -> b -> t a -> b` | |
|
|
`foldr (-) 0 [1,7,4]` | `Num a => a` | `-2` | `(1-(7-(4-0)))`
|
|
`elem 7 [1,7,4]` | `Bool` | `True` |
|
|
`all even [1,7,4]` | `Bool` | `False` | Similar `any`
|
|
`filter even [1,7,4]` | `[Integral a] => [a]` | `[1,7,4]` | Similar `odd,(>1),(/=3)`
|
|
`(length . filter (>1) ) [1,7,4]` | `Int` | `2` |
|
|
`Data.List.partition (>1) [1,7,4]` | `(Ord a, Num a) => ([a], [a])` | `([7,4],[1])`
|
|
`zip [1,7,4] ["one","seven","four","eight"]` | `Num a => [(a, String)]` | `[(1,"one"),(7,"seven"),(4,"four")]` | truncating to the shorter list
|
|
`Data.List.sortOn fst $ zip [1,7,4] ["one", "seven", "four"]` | `(Ord b, Num b) => [(b, String)]` | `[(1,"one"),(4,"four"),(7,"seven")]`
|
|
`Data.List.sort ["one","seven","four","eight"]` | `[String]` | `["eight","four","one","seven"]`
|
|
`reverse $ Data.List.sort ["one","seven","four","eight"]` | `[String]` | `["seven","one","four","eight"]`
|
|
`Data.List.sortBy compare ["one","seven","four","eight"]` | `[String]` | `["eight","four","one","seven"]`
|
|
`Data.List.sortBy (flip compare) ["one","seven","four","eight"]` | `[String]` | `["seven","one","four","eight"]`
|
|
`Data.List.sortBy (curry( (uncurry compare) . (uncurry(Control.Arrow.***) (length,length)))) ["one","seven","four","eight","ten"]` | `[String]` | `["one","ten","four","seven","eight"]` |
|
|
`Data.List.sortBy (Data.Ord.comparing length) ["one","seven","four","eight","ten"]` | `[String]` | `["one","ten","four","seven","eight"]`
|
|
`map (+1) [1,7,4]` | `Num a => [a]` | `[2,8,5]` |
|
|
`map length ["one", "seven", "four"]` | `[Int]` | `[3,5,4]` |
|
|
`map (negate . abs) [1,-7,4]` | `Num a => [a]` | `[-1,-7,-4]` |
|
|
`map even [1,7,4]` | `[Bool]` | `[False,False,True]` |
|
|
`[1..5]` | `(Num a, Enum a) => [a]` | `[1,2,3,4,5]` |
|
|
`[1,3..9]` | `(Num a, Enum a) => [a]` | `[1,3,5,7,9]` |
|
|
`[1..]` | `(Num a, Enum a) => [a]` | `[1,2,3,4,5,...]` | infinite sequence
|
|
`take 4 [10..]` | `(Num a, Enum a) => [a]` | `[1,2,3,4]` | laziness in action
|
|
`[x*2 \| x <- [1..5]]` | `[Num a] => [a]` | `[2, 4, 6, 8, 10]` | List comprehension
|
|
``[x*2 \| x <- [1..5], x `mod` 3 == 0]`` | `[Num a] => [a]` | `[6]` |
|
|
`[ (a,b,c) \| c <- [1..10], b <- [1..c], a <- [1..b], a^2 + b^2 == c^2]` | `(Num c, Eq c, Enum c) => [(c, c, c)]` | `[(3,4,5),(6,8,10)]`
|