FP / Zoznamy

Zoznamy

Funkcionálne programovanie

Vytvorenie zoznamu

[]   -- prázny zoznam
(:)  -- pridanie prvku na začiatok zoznamu
[1, 2, 3, 4] == 1 : (2 : (3 : (4 : [])))
⇝ True

Operatory

(++) :: [a] -> [a] -> [a]
(!!) :: [a] -> Int -> a
"Ahoj, " ++ "svet!"
⇝ "Ahoj, svet!"

"Ahoj, svet!" !! 3
⇝ 'j'

Funkcie

length :: [a] -> Int
concat :: [[a]] -> [a]
head :: [a] -> a
tail :: [a] -> [a]
init :: [a] -> [a]
last :: [a] -> a
take :: Int -> [a] -> [a]
drop :: Int -> [a] -> [a]

a množstvo ďalších

Príklad

leftShift :: Int -> [a] -> [a]
leftShift n xs = drop n xs ++ take n xs

rightShift :: Int -> [a] -> [a]
rightShift n xs = drop n' xs ++ take n' xs
    where n' = length xs - n

Pattern matching

Porovnávanie vzorov

isOne 1 = True
isOne n = False
length [] = 0
length (x:xs) = 1 + length xs

Wild-cards

isOne 1 = True
isOne _ = False
length [] = 0
length (_:xs) = 1 + length xs

As-patterns

doubleFirst (x:xs) = x:x:xs
doubleFirst' s@(x:xs) = x:s

Vnorené vzory

sumPairs :: Num a => [(a, a)] -> [a]
sumPairs [] = []
sumPairs ((x,y):rest) = (x+y) : sumPairs rest

Intermezzo

Aritmetické postupnosti

[1..10]
⇝ [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[1,3..10]
⇝ [1, 3, 5, 7, 9]
[10,7..0]
⇝ [10, 7, 4, 1]

[1..]

Nekonečné zoznamy

take 5 [1..]
⇝ [1, 2, 3, 4, 5]

Výpočet na základe požiadavky — lazy evaluation

Vzory práce s zoznamami

Vzory práce s zoznamami

Funkcie vyššieho rádu

Zobrazenie (map)

map square [1..5]
⇝ [1, 4, 9, 16, 25]
map :: (a -> b) -> [a] -> [b]

Alebo inak

Príklad

sumPairs [] = []
sumPairs ((x,y):rest) = (x+y) : sumPairs rest
sumPairs' pairs = map (\(x,y) -> x + y) pairs

Filtrovanie

filter odd [1..5]
⇝ [1, 3, 5]
filter :: (a -> Bool) -> [a] -> [a]

Kombinovanie

Súčet zoznamu

[5, 10, 8, 3]
5 + 10 + 8 + 3
foldr1 (+) [5, 10, 8, 3]
foldr (+) 0 [5, 10, 8, 3]

foldr & foldl

$$ \mathtt{foldr}\ (\oplus)\ a\ [x_1, x_2, \dots, x_n] = x_1 \oplus (x_2 \oplus (\dots (x_n \oplus a)\dots)) $$ $$ \mathtt{foldl}\ (\oplus)\ a\ [x_1, x_2, \dots, x_n] = (\dots ((a \oplus x_1) \oplus x_2) \dots ) \oplus x_n $$

foldr :: (a -> b -> b) -> b -> [a] -> b
foldl :: (b -> a -> b) -> b -> [a] -> b
sum xs = foldr add 0 xs
         where add x accumulator = x + accumulator
sum' xs = foldl add 0 xs
          where add accumulator x = accumulator + x
length = foldl plusone 0
         where plusone n x = n + 1
reverse = foldl prepend []
          where prepend xs x = x : xs

takeWhile & dropWhile

takeWhile :: (a -> Bool) -> [a] -> [a]
dropWhile :: (a -> Bool) -> [a] -> [a]
takeWhile (<10) [3, 5, 4, 2, 8, 15, 4, 7]
⇝ [3, 5, 4, 2, 8]

Aký to má význam?

Abstrakcia prechádzania zoznamom

Množinové abstrakcie

Množinové abstrakcie

List comprehension

[(x, y) | x <- [1, 2, 3], y <- [3, 4], x < y]