Wykład 1
Basics/Lecture01.hs
- Projekt zespołowy, (40 pktów, przydzielane na +-dziesiątych zajęciach)
- Dwa testy na laboratoriach, (2 x 15 pktów)
quicksort :: Ord a => [a] -> [a]
quicksort [] = []
quicksort (x:xs) = quicksort le ++ [x] ++ quicksort gr
where
le = filter (< x) xs
gr = filter (>=x) xs
Można i tak:
quicksort [] = []
quicksort (x:xs) = quicksort le ++ [x] ++ quicksort gr
where
le = filter (< x) xs
gr = filter (>=x) xs
- Teoria kategorii
- Deklaratywne
- Bez efektów ubocznych
- λ - calculus
- Leniwe obliczanie
Składamy strzałki:
(.) :: (a -> b) -> (b -> c) -> (a -> c)
g . f x = g (f x)
Monady są wszechobecne:
class Monad m where
(>>=) :: m a -> (a -> m b) -> m b
return :: a -> m a
Uwaga notacyjna:
a -> b -> c = a -> (b->c) ~izomorficzne~ (a,b) -> c
How vs. What
Przykład imperatywnego kodu (Python):
sum = 0
for x in list:
sum += x
print(sum)
Przykład deklaratywnego (funkcyjnego) kodu (Haskell):
sum = foldr (+) 0 list
Inny przykład innego deklaratywnego kodu (Sql):
SELECT * FROM employees WHERE age >= 20;
Definicja Funkcja (wyrażenie) ma efekty uboczne, jeśli zmienia ona stan pewnych zmiennych poza swoim środowiskiem.
Pytanie Niech f i g będą funkcjami napisanymi w Pythonie. Czy spełniona jest następująca równość:
f(5)+g(5) = g(5)+f(5)
Przykłady
- Globalne zmienne
- I/O
- ...
Definicja (notacja Haskellowa) e ::= x ∈ Variables | λx -> e | e e'
Definicja (simply typed λ-calculus) Gramatyka typów: t ::= t -> t' | t' ∈ BaseTypes Gramatyka wyrażeń λ: e ::= x | λx:t -> e | e e' | c ∈ ConstantsOfBaseTypes
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⢿⣿⣿⠿⠿⠿⠻⠿⢿⡿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ ⣿⣿⣿⣿⣿⣿⡿⠟⠉⠈⠉⠉⠄⢠⠄⠄⢀⠄⠄⡬⠛⢿⢿⣿⣿⣿⣿⣿⣿⣿ ⣿⣿⣿⡿⡿⠉⠄⠄⠄⠄⠄⠄⠅⠄⠅⠄⠐⠄⠄⠄⠁⠤⠄⠛⢿⢿⣿⣿⣿⣿ ⣿⣿⣿⠍⠄⠄⠄⠄⠄⠄⠄⠄⣀⣀⠄⣀⣠⣀⠄⢈⣑⣢⣤⡄⠔⠫⢻⣿⣿⣿ ⣿⡏⠂⠄⠄⢀⣠⣤⣤⣶⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣮⣔⠂⡙⣿⣿ ⡿⠄⠄⣠⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣦⣈⣿ ⠇⠄⢠⣿⣿⣿⣿⣿⡿⠿⣿⣿⣿⣿⣿⣿⣿⣿⡟⠿⠿⢿⡿⣿⣿⣿⣿⣿⡧⣼ ⠄⠄⠽⠿⠟⠋⠁⠙⠄⢠⣿⡿⢿⣿⣿⣿⣿⣿⣷⡠⢌⣧⠄⠈⠛⠉⠛⠐⡋⢹ ⠄⠄⠄⠄⠄⠄⠄⢀⣠⣾⡿⠑⠚⠋⠛⠛⠻⢿⣿⣿⣶⣤⡄⢀⣀⣀⡀⠈⠄⢸ ⣄⠄⠄⠄⢰⣾⠟⠋⠛⠛⠂⠄⠄⠄⠄⠒⠂⠛⡿⢟⠻⠃⠄⢼⣿⣿⣷⠤⠁⢸ ⣿⡄⠄⢀⢝⢓⠄⠄⠄⠄⠄⠄⠄⠄⠠⠠⠶⢺⣿⣯⣵⣦⣴⣿⣿⣿⣿⡏⠄⢸ ⣿⣿⡀⠄⠈⠄⠄⠄⠠⢾⣷⣄⢄⣀⡈⡀⠠⣾⣿⣿⣿⣿⣿⣿⣿⡿⠿⢏⣀⣾ ⣿⣿⣷⣄⠄⠄⠄⢀⠈⠈⠙⠑⠗⠙⠙⠛⠄⠈⠹⠻⢿⡻⣿⠿⢿⣝⡑⢫⣾⣿ ⣿⣿⣿⣿⣿⣆⡀⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠑⠐⠚⣨⣤⣾⣿⣿
Nieskończona lista jedynek:
ones = 1:ones
Nieskończona lista kolejnych liczb naturalnych:
nats = [1..]
Zagadka
f = 0:1:[ x+y | (x,y) <- zip f (tail f)]
Wyrażenie
((2+3)+(1+4))+(5+6)
Innermost evaluation:
((2+3)+(1+4))+(5+6) -> (5+(1+4))+(5+6) ->
(5+5)+(5+6) -> 10+(5+6) ->
10+11 -> 21
Lazy evaluation:
((2+3)+(1+4))+(5+6) -> ((2+3)+(1+4))+11 ->
((2+3)+5)+11 -> (5+5)+11 ->
10+11 -> 21
Rozważmy funkcję napisaną w C i w Haskellu:
int f(int x, int y) {
if (x>0)
return x-1;
else
return x+1;
}
f :: Int -> Int -> Int
f x y = if x > 0 then x-1 else x+1
Ta sama funkcja:
f :: Int -> Int -> Int
f x y = if x > 0 then x-1 else x+1
dodajmy jeszcze:
val = f 1 (product [1..])
length1 :: [a] -> Int
length1 [] = 0
length1 (x:xs) = 1 + (length1 xs)
i policzmy
let x = product [1..] in length1 [1,x]
- Jaki będzie wynik?
Zmieńmy trochę naszą definicję length:
length2 :: [Int] -> Int
length2 [] = 0
length2 (x:xs) = if x > 0 then 1 + (length2 xs) else 1 + (length2 xs)
i policzmy znowu:
let x = product [1..] in length2 [1,x]
- Jaki teraz będzie wynik?
Przykład
length1 [1,x] -> length1 1:[x] -> 1+(length1 [x]) ->
1+(length1 x:[]) ->1+(1+length1 []) -> 1+(1+0)-> 1+1 -> 2
Definicja Wyrażenie jest postaci normalnej (NF, normal form), jeśli nie da się go zredukować.
Przykłady
5
2:3:[]
(2,'t')
\x->x+2
Definicja Wyrażenie jest w Weak Head Normal Form (WHNF), jeśli jest -abstrakcją lub wyrażeniem w ktorym najbardziej zewnętrzny konstruktor jest obliczony.
Przykłady
(1+1,2)
\x->x+2
5:whatever
Just (sum [1..10])
Nie-przykłady
map (\x-> x*x) [1,2]
(+) 1 2
Pytanie Czy wyrażenie
f
jest w WHNF (NF?), jeśli
f x = x*x
Sztuczka
seq x y -- oblicza x do WHNF (drugi argument może być dowolny, np. ()) i zwraca y.
Można sprawdzić działanie
ghci> let x = 2+3 :: Int
ghci> :sprint x
ghci> seq x ()
()
ghci> :sprint x
ghci> let y = map id [x]
ghci> :sprint y
ghci> seq y ()
()
ghci> :sprint y
ghci> y
ghci> :sprint y
Ćwiczenie Przedstawić ciąg redukcji:
map negate [1,2,3]
Ściągawka:
map ::(a -> b) -> [a] -> [b]
map f [] = []
map f (x:xs) = (f x) : map f xs
negate :: (Num a) => a -> a
negate x = -x
Ćwiczenie 2 Przedstawić ciąg redukcji:
(take 6 . map (+1)) [1..10]
Twierdzenie Leniwa ewaluacja działa w co najwyżej tylu krokach co ewaluacja gorliwa.
Problem Pamięć!
Ćwiczenie
sum' [] = 0
sum' (x:xs) = x + sum' xs
sum' [1..100000000]
sumUp [1..100000000]