-- comenzile din comentarii care încep cu -- \> sunt de scris la consolă -- :help (sau :?) -- :set prompt "λ> " -- :r (:reload) pentru reîncărcarea sursei -- :! com -- pentru rularea unei comenzi a sistemului de operare -- (e.g. :! clear / :! cls sau :! ls / :! dir) -- :t add1 -- (:type) -- află tipul oricărei expresii -- :t (+) -- pentru operatori trebuie dați în forma prefixată -- :: înseamnă "are tipul" -- v :: => tip = v are tipul tip, în contextul de tip -- de asemenea: -- :i add1 -- (:info) -- funcționează și pentru operatori, e.g. :i + -- Tipuri de date -- \> :type 1 -- 1 :: Num a => a -- 1 este de un tip oarecare, cu condiția să fie un tip numeric -- \> :t 1.2 -- 1.2 :: Fractional a => a -- 1.2 este de un tip oarecare, cu condiția să fie fracțional -- \> :t True -- True :: Bool -- \> :t False -- False :: Bool -- \> :t [1,2,3] -- [1,2,3] :: Num t => [t] -- este o listă de elemente de tip t, iar t este un tip numeric -- \> :t (1, 'a') -- (1, 'a') :: Num t => (t, Char) -- o pereche -- \> :t (1, 'a', True, [5..9]) -- un tuplu -- (1, 'a', True, [5..9]) :: (Num t1, Num t, Enum t1) => (t, Char, Bool, [t1]) -- perechile și listele NU sunt același lucru -- toate elementele dintr-o listă sunt de același tip -- elementele dintr-un tuplu pot fi de tipuri diferite -- în Haskell avem operatori infixați -- \> [1..] -- o listă infinită -- \> [1..20] -- [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20] -- \> [1,4..20] -- [1,4,7,10,13,16,19] -- \> head [1,2,3] -- 1 -- \> tail [1,2,3] -- [2,3] -- \> (tail [1,2,3]) -- [2,3] -- \> [1,2,3] !! 2 -- 3 -- \> 1 : [2,3,4] -- [1,2,3,4] -- \> 1 + 2 -- 3 -- \> fst (1, 'a') -- 1 -- \> snd (1, 'a') -- 'a' -- șirurile de caractere sunt același lucru (ca tip) cu liste de caractere -- λ> head "abcd" -- 'a' -- λ> tail "abcd" -- "bcd" -- elem este member -- ++ este operatorul de concatenare -- Funcții -- \ stă pentru lambda -- definire directă a funcției add1 :: Num t => t -> t -> t -- necesar pentru că sinteza de tip determină că add1 este pe întregi add1 = \x y -> ((+) x y) -- (add1 1 2) -- ((add1 1) 2) -- add1 1 2 -- \> :t add1 -- aplicare parțială -- \> map (add1 1) [1..5] -- un operator pot să îl folosesc în formă infixată sau prefixată cu paranteze -- o funcție pot să o folosesc în formă prefixată sau infixată cu ` -- λ> 1 `add1` 2 -- în Haskell toate funcțiile sunt funcții curry add2 = \x -> \y -> (((+) x) y) -- cu toate parantezele și în formă curry, dar ne-necesar add3 = \x y -> x + y -- PATTERN MATCHING add4 x y = x + y -- "dacă apelez add4 cu argumentele x și y, valoarea întoarsă este" -- transformare operator -> funcție (formă infixată -> formă prefixată add5 = (+) -- "add5 este același lucru cu funcția (+)" -- transformarea inversă: 1 `add6` 3 -- p-m incomplet (non-exhaustiv) addX 1 2 = 3 addX 1 x = x + 1 addX 5 6 = 11 -- în Haskell toți identificatorii încep cu literă MICĂ -- în Haskell CONTEAZĂ INDENTAREA -- Perechi (acces cu fst și snd) -- \> (1, 'a') -- Tupluri -- \> ('a', [1,2,3], False) -- Liste, acces cu head și tail, funcții utile: (:), elem, (!!), (++) -- \> [1, 2, 3] -- \> [1..10] -- \> [1, -1..-20] -- setează pasul listei (rația progresiei aritmetice) -- \> ['a'..'z'] len1 l = if l == [] then 0 else 1 + len1 (tail l) -- pattern-matching len2 [] = 0 len2 (h:t) = 1 + len2 t -- _ = nu ma intereseaza sa leg valoarea la un nume -- "dacă len2 este aplicat pe o listă care a fost obținută prin aplicarea lui : -- între ceva și altceva, atunci leagă ceva la h și leagă altceva la t și evaluează -- corpul" -- paranezele sunt puse doar pentru asociativitate -- p-m face o legare a variabilelor din pattern în așa fel încât să se potrivească cu valoarea parametrului actual -- când apelez len2 [1,2,3], haskell leagă în așa fel încât [1,2,3] să fie rezultatul expresiei h:t -- "ce ar trebui să fie h și t astfel încât h:t -> [1,2,3] match (h:t) = (h, t) match2 (h1:h2:h3:t) = (h1,h2,h3,t) match3 (h1:_:_:t) = (h1,t) -- patternul arată cum a fost construită valoarea dată ca argument -- și dacă patternul se potrivește, atunci se fac legările onform cu patternul len2b [x,y,z] = 3 -- sau len2b (h1:h2:h3:[]) = 3 -- când voi apela, Haskell întreabă "ce ar putea fi h1 h2 h3 aî (h1:h2:h3:[]) să dea argumentul cu care am apelat?" len2c [] = 0 len2c (_ : t) = 1 + len2c t -- nu folosesc partea de pattern dinainte de : -- "_" înseamnă că acolo este o valoare, dar mie în corpul funcției nu îmi trebuie len2d [] = 0 len2d (h1:h2:h3:t) = 3 + len2d t -- merge doar pentru liste de lungime multiplu de 3 -- case len3 l = case l of [] -> 0 otherwise -> 1 + len3 (tail l) len3b l = case l of [] -> 0 --h:t -> 1 + len3 t -- _:t -> 1 + len3b t --otherwise -> 1 + len3 (tail l) --_ -> 1 + len3 (tail l) l1 -> 1 + len3 (tail l1) --inline: len3c l = case l of []->0; _:t->1+len3c t -- patterns non-exhaustive len4 [] = 0 len4 [_] = 1 -- gărzi (vedeți https://wiki.haskell.org/Pattern_guard ) len5 l | l == [] = 0 | otherwise = 1 + len5 (tail l) -- gărzile sunt legate de un = -- în gărzi pot pune condiții complete (în case pot pune doar patter-match pe valoarea unei variabile, după care fac case) len5b [] = 0 len5b l = let t = tail l; ll = len5b t in 1 + ll len6 l | l == [] = 0 | otherwise = 1 + len6 t where t = tail l -- let in este o expresie -- where se folosește împreună cu un = sau cu o serie de gărzi len6a [] = 0 len6a (h : t) = let lenT = len6a t in 1 + lenT len6b [] = 0 len6b l = let t = tail l lenT = len6b t in 1 + lenT len6c [] = 0 len6c l = 1 + lenT where t = tail l lenT = len6c t len6d l | l == [] = 0 | otherwise = 1 + lenT where lenT = len6d (tail l) -- expresia din where se evaluează doar dacă este nevoie because lazy -- p-m în let len6e [] = 0 len6e l = let h:t = l; lT = len6b t in 1+lT -- gărzi pe aceeași linie, și where len6f l | l == [] = 0 | otherwise = 1+lt where lt = len6f (tail l) -- ... și cu let len7 l | l==[] = 0 | True = let lt = len7 (tail l) in 1 + lt -- let și inline case len8 l = let t = tail l in case l of [] -> 0 ; otherwise -> 1 + len8 t len9 [] = 0 len9 [_] = 1 len9 (_:rest@(_:_)) = 1 + len9 rest len10 [] = 0 len10 l = 1 + (len10 $ tail l) -- (+1) $ length $ tail $ filter even [1..20] -- List comprehensions -- [x+2 | x <- [1..20], x `mod` 3 == 0] -- [ expr | var <- domeniu, var2 <- domeniu2, cond, cond, cond ] mapLC f l = [f x | x <- l] filterLC f l = [x | x <- l, f x] --sau [x | x <- l, f x == True] cart m1 m2 = [(e1, e2) | e1 <- m1, e2 <- m2] -- fluxuri ones = 1 : ones naturals = naturalsFrom 0 where naturalsFrom n = n : naturalsFrom (n+1) evens = filter even naturals evens2 = zipWith (+) naturals naturals