Notes for learning haskell
weitermachen bei http://learnyouahaskell.com/recursion
notes from the help
-cmd-tool (haskell landing-page) + learnyouahaskell.com
- E-V-E-R-Y-T-H-I-N-G is a function
[1, '2']
=>ERROR
: a list can contain only one single type[2,4,8,10] !! 2
=>8
:!!
extracts item by index from an array1 : []
=>[1]
the colone-func (:
) adds a value at the head of a list[2,4] ++ [8,10]
=>[2,4,8,10]
:++
concats two arrays[3,2] > [2,3]
=>True
;[2,2] > [2,1]
=>True
: When using<
,<=
,>
and>=
to compare lists, they are compared in lexicographical order. First the heads are compared. If they are equal then the second elements are compared, etc.head
,tail
,last
,init
,length
,reverse
,take
,drop
=> array-funcs (siehe auch gute dokus von ramda zu funktionalitäten)null []
=>True
: checks for empty listelem 3 [1,2,3]
=>True
: check if first var is in given list (siehe auch infix-funktionen)- further List-funcs
cycle [1,2]
=>[1,2,1,2,...]
;repeat 1
=>[1,1,1,...]
: produces infinite lists
- a char defined via single quote
'
, a string via double quote"
- a string is a list of chars =>
['h', 'i'] == "hi"
'h' != "h"
, da"h" == ['h']
'a' : "sap"
=>"asap" == ['a', 's', 'a', 'p']
: add the char'a'
to the char-list['s', 'a', 'p'] == "sap"
[first,sec..end]
=> füllt ein array mit der vorschrift:[first,first + step,first + 2 * step,…end]
wobeistep = sec - first
[1..4]
=>[1,2,3,4]
: heresec
is implicitly set tosec = first + 1
- Doku allgemein zu 'arithmetic sequence'
- can be used if the items implement
Enum
(read morein the documentation) (in principle strings with a-z and integer; double possible but not necessarily good)
let x = 4 in x * x
=>16
: define variables and give them scope (in
just separates the expression from the body.)let villain = (28,"chirs") in fst villain
=>28
: returns first value of per variable defined tuple (seevariables
below for syntax)
let (a,b) = (10,12) in a * 2
=>20
:(10,12)
is matched against pattern(a,b)
and so a resolves to 10let (a,_,_) = (10,12,13) in a * 2
=>20
:_
is ignore-operator and can be used multiple in tuple- and list-patternslet (a:b:c:[]) = "xyz" in a
=>x
: wherebylet (a:b:c:[]) == let (a:b:c)
(see list for the colone-func)(a:b:c:d)
is short-hand for(a:(b:(c:d)))
: so a is the first from b, which is the first from c and c is the restlet (a:[]) = "xyz" in a
=>x
let (a:_) = "xyz" in a
=>x
let ab@(a,b) = (10,20) in (ab,a,b)
=>((10,20),10,20)
:VAR@...
saves the original value of the pattern-matches inVAR
(28, "JP")
=>...
: keep a bunch of values together, (can contain different types)fst (28, "JP")
=>28
: returns the first val of a tuple- wenn shape of object is clear : tuple > list, zb, store x-y-coods:
- A:
[[1,2],[2,3]]
vs B:[(1,2),(2,3)]
=> - B > A, da
[[1,2],[2,3,4]]
=> no error for haskell[(1,2),(2,3,4)]
=> haskell-error
- A:
- singleton-tuple (
(1)
) does not exist
let square x = x * x in square 3
=>9
let square x = x * x
entspricht quasi (JS)const square = x => x * x
in
(siehe #variables) nutzt die vorher definierte funktionsquare
als higher order function
+
is a function (writing+
(function) asplus
for clarity) :let plus a b = a + b
(second+
ist die arithmetische operation)- most haskell-functions are curried, so
plus (1) (2) == plus (1, 2)
whereplus 1 == plus (1)
returns a function (added braces for clarity) map (+1) [1..4]
=>[2,3,4,5]
:map
is global library-func, somap (+1) [1..4] == map (plus 1) [1...4]
3 `elem` [1,2,3]
=>True
: usingelem
-func (list) with the infix-operator
<expression> where <bindings>
get1 = x where x=1
;get1
=>1
: define variables after usagecalcSum a b = sum' a b where sum' c d = c + d
:where
can also define functionswhere
is no expression, so it cannot be used in expressions (somehow "only in functions") => see let ... in below
where
bindings can also be nested. It's a common idiom to make a function and define some helper function in its where clause and then to give those functions helper functions as well, each with its own where clause.
let <bindings> in <expression>
let x=1 in x+3
=>4
let ... in
is an expression and can be used nearly everywhere4 * (let a = 9 in a + 1) + 2
=>42
[let square x = x*x in (square 2, square 6)]
=>[4,36]
let a=2; b=6; in a*b
=>12
: semicolons can sperate serval inline variables- other differntations (where/let):
[add1 | a <- [1..4], let add1 = a+1]
=>[2,3,4,5]
: The names defined in alet
inside a list comprehension are visible to the output function (the part before the |)
- abgeleitet von math. Notation:
{ 2x | x ∈ ℕ, x ≤ 10 }
=>[x*2 | x <- [1..10]]
=>[2,4,...,20]
[FUNCTION | DEFINITIONEN, NEBENBEDINGUNGEN, ...]
FUNCTION
=> wie sollen die einzelnen Elemente seinDEFINITIONEN
=> nach Formatx <- ...
CONSTRAINTS
(Nebenbedingungen) => function (x `mod` 7 == 3
,x < 5
, ...)
- composition:
[ [ x | x <- xs, even x ] | xs <- [[1,2],[2,4]]]
=>[[2],[2,4]]
- da
FUNCTION
pro ele ist kann man es entsprechend composen
- da
- use with pattern matching for variables:
[a+b | (a,b) <- [(1,2),(6,9)]
=>[3,15]
is42 :: (Integral a) => a -> String
is42 42 = "is 42"
is42 x = "not 42"
this is syntactic suggar for a normal case expression:
is42 :: (Integral a) => a -> String
is42 n = case n of
42 -> "is 42"
n -> "not 42"
detailedIs42 :: (Integral a) => a -> String
detailedIs42 numb
| numb < 42 = "too low"
| numb == 42 = "is 42"
| otherwise = "too high"
:t 'a'
=>'a' :: Char
::t
returns the type- > 1 params:
add x y = x + y
, type-def:add :: Int -> Int -> Int
- => no diff between return-type + params (last type is return type) => see currying
read
andshow
are functions,show
is like atoString
andread
a bit like the opposite fromshow
(reads the string and tries to get a type (Int, list, ...) from string)show 3
=>"3"
,read "5" - 1
=>4
(read
MUST be directly used afterwards or you have to add eplicit type annotations (see below))
- type annotations begins with
::
- can be inlined
read "5" :: Int
and(read "5" :: Float) * 4
:t head
=>head :: [a] -> a
:a
here is a type variable and can be any type- functions that have type variables are called polymorphic
- a bit like interfaces in OOP
:t (==)
=>(Eq a) => a -> a -> Bool
- Everything before the
=>
-Operator is called a class constraint (Nebenbedingung) - contraints for a type definition defines how the
type variables
have to look like - eg
Eq a
means that every following a MUST have the same type - basic typeclasses:
Eq
e.g.:t (==)
=>(Eq a) => a -> a -> Bool
Ord
e.g.(>) :: (Ord a) => a -> a -> Bool
(type must have a ordering)Show
e.g.show :: Show a => a -> String
(type must presentable as string) ! theshow
-fn (lowercased!) is liketoString
;show 3
=>"3"
Read
e.g.read :: Read a => String -> a
(like opposite ofShow
/show
); reads the string and tries to get a type (Int, list, ...) from stringEnum
e.g.succ :: Enum a => a -> a
:Enum
-Nebenbedingung meint dass der Typ Numerierbar (bzw eine interne Ordnung haben muss)Bounded
e.g.minBound :: Bounded a => a
: Type must have an upper and lower bound (maxBound
- andminBound
-fn)Num
e.g.:t 42
=>42 :: (Num t) => t
and(*) :: (Num a) => a -> a -> a
(product eg in2*2
)Integral
: includesInt
andInteger
(hat nicht mit einem eigentlichen Integral zu tun)Floating
:Float
andDouble
- Everything before the
unter windows empfiehlt stack in
C:\sr-stack
o.ä. zu installieren da osnst die langen Pfade zu Problemen führen können stack#3285 (ebenso auch die project-root für haskell-folder)
- ... init stack-prject (see docu)
stack build
builds your app =>stack build --file-watch
=> watch-modestack exec [YOUR_PROJECT_NAME]-exe
execute
for VS Code with haskero: you need to install intero (
stack build intero
)
Lib.hs:
module Lib (someExportFunc, otherExport) where
-- possible type-annotations:
someExportFunc :: IO ()
-- the func:
someExportFunc = putStrLn 'hello world'
-- [...] private implementation-funcs
privateFunc = "this will not be exported"
-- weitere export-funcs
otherExport x = x * x
Main.hs
module Main where
import Lib
main :: IO ()
main = someFunc
module MODULE_NAME (EXPORT_NAME_1, ...) where
=> defines the moduleName and which functions it will exportmodule MODULE_NAME where
will export every defined function in the file
- hindent sieht cooler aus
- stylish-haskell hatte bei mir bei der ersten installation nicht funktioniert
- brittany another formatter
allgemein:
- dieser aritkel scheint den anschein zu amche ndas haskell deutlich weniger leisten könnte (aber zum anfang sollte das nicht so wichtig oder problematisch sein)
fjeden ToCheck:
- yesod
- good starting point for web => scheint älteste und "robusteste" zu sein
- scheint aber komplettes web-framework zu sein (MVC-bla)
- servant
- angeblich speziell für REST-Apis sehr gut
- scheint gutes bonus-set zu haben (auto-generate API-Docs in swagger, JS client, mock server, documentation)
- spock
- im allgemeinen gilt spock > scotty, scheint aber nicht mehr so aktiv weiterentwickelt zu werden
- müsste man sich weiter anschauen
good article which mentions a lot of different libs
List from the best to the worst (after the comments, no further own experiences currently)
- project-m36
- beam
- haskell-opaleye + tisch (postgre-only)
- persistent + esqueleto (?)
- postgresql-simple + mysql-simple
- scheint sehr gut zu sein weil es am wenigsten tut => aber doku sagt mir spontan nix
length' :: (Num b) => [a] -> b
length' [] = 0
length' (_:xs) = 1 + length' xs
factorial :: (Integral a) => a -> a
factorial 0 = 1
factorial n = n * factorial (n - 1)
max' :: (Ord a) => a -> a -> a
max' a b
| a > b = a
| otherwise = b
myCompare :: (Ord a) => a -> a -> Ordering
a `myCompare` b
| a > b = GT
| a == b = EQ
| otherwise = LT
this example includes the backticks (
`myCompare`
) for readability
initials :: String -> String -> String
initials firstname lastname = [f] ++ ". " ++ [l] ++ "."
where (f:_) = firstname
(l:_) = lastname