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]: heresecis 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 (injust separates the expression from the body.)let villain = (28,"chirs") in fst villain=>28: returns first value of per variable defined tuple (seevariablesbelow 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=>xlet (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=>9let square x = x * xentspricht quasi (JS)const square = x => x * xin(siehe #variables) nutzt die vorher definierte funktionsquareals higher order function
+is a function (writing+(function) asplusfor 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]:mapis 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:wherecan also define functionswhereis no expression, so it cannot be used in expressions (somehow "only in functions") => see let ... in below
wherebindings 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=>4let ... inis 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 aletinside 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
FUNCTIONpro 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::treturns 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
readandshoware functions,showis like atoStringandreada 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(readMUST be directly used afterwards or you have to add eplicit type annotations (see below))
- type annotations begins with
:: - can be inlined
read "5" :: Intand(read "5" :: Float) * 4
:t head=>head :: [a] -> a:ahere 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 variableshave to look like - eg
Eq ameans that every following a MUST have the same type - basic typeclasses:
Eqe.g.:t (==)=>(Eq a) => a -> a -> BoolOrde.g.(>) :: (Ord a) => a -> a -> Bool(type must have a ordering)Showe.g.show :: Show a => a -> String(type must presentable as string) ! theshow-fn (lowercased!) is liketoString;show 3=>"3"Reade.g.read :: Read a => String -> a(like opposite ofShow/show); reads the string and tries to get a type (Int, list, ...) from stringEnume.g.succ :: Enum a => a -> a:Enum-Nebenbedingung meint dass der Typ Numerierbar (bzw eine interne Ordnung haben muss)Boundede.g.minBound :: Bounded a => a: Type must have an upper and lower bound (maxBound- andminBound-fn)Nume.g.:t 42=>42 :: (Num t) => tand(*) :: (Num a) => a -> a -> a(product eg in2*2)Integral: includesIntandInteger(hat nicht mit einem eigentlichen Integral zu tun)Floating:FloatandDouble
- Everything before the
unter windows empfiehlt stack in
C:\sr-stacko.ä. 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 buildbuilds your app =>stack build --file-watch=> watch-modestack exec [YOUR_PROJECT_NAME]-exeexecute
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 * xMain.hs
module Main where
import Lib
main :: IO ()
main = someFuncmodule MODULE_NAME (EXPORT_NAME_1, ...) where=> defines the moduleName and which functions it will exportmodule MODULE_NAME wherewill 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' xsfactorial :: (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 = bmyCompare :: (Ord a) => a -> a -> Ordering
a `myCompare` b
| a > b = GT
| a == b = EQ
| otherwise = LTthis example includes the backticks (
`myCompare`) for readability
initials :: String -> String -> String
initials firstname lastname = [f] ++ ". " ++ [l] ++ "."
where (f:_) = firstname
(l:_) = lastname