Функциональное программирование - Александр Алексеев
TRANSCRIPT
Функциональноепрограммирование
Александр Алексеев
Парадигмыпрограммирования
– Процедурное программирование– Объектно-ориентированное программирование– Функциональное программирование– Логическое программирование– и другие...
Процедурноепрограммирование
– Pascal– Си– и другие...
Языки процедурного программирования:
Объектно-ориентированное
программирование
– Java– C#– Delphi (Object Pascal)– C++– Python– Perl, Perl 6– PHP5– и многие другие
ООП-языки:
Функциональноепрограммирование
Функциональноепрограммирование
Функциональноепрограммирование
Все очень просто!
Основы(на примере Haskell)
data Bool = True | False
data Bool = True | False
positive :: Int → Boolpositive x = x > 0
data Bool = True | False
positive :: Int → Boolpositive x = x > 0
max :: (Ord a) => a → a → amax x y | x > y = x | otherwise = y
data Person = Person { firstName :: String, lastName :: String, birthYear :: Int } deriving (Show)
data Person = Person { firstName :: String, lastName :: String, birthYear :: Int } deriving (Show)
alex = Person { firstName = "Александр", lastName = "Алексеев", birthYear = 1988 }
class Eq a where (==), (/=) :: a -> a -> Bool x /= y = not (x == y) x == y = not (x /= y)
class Eq a where (==), (/=) :: a -> a -> Bool x /= y = not (x == y) x == y = not (x /= y)
instance Eq Person where x == y = birthYear x == birthYear y
class Eq a where (==), (/=) :: a -> a -> Bool x /= y = not (x == y) x == y = not (x /= y)
instance Eq Person where x == y = birthYear x == birthYear y x /= y = not (x == y)
anton = Person { firstName = "Антон", lastName = "Алексеев", birthYear = 1991 }
anton = Person { firstName = "Антон", lastName = "Алексеев", birthYear = 1991 }
alex == anton False
anton = Person { firstName = "Антон", lastName = "Алексеев", birthYear = 1991 }
alex == anton Falsealex == alex True
anton = Person { firstName = "Антон", lastName = "Алексеев", birthYear = 1991 }
alex == anton Falsealex == alex Trueanton == alex False
anton = Person { firstName = "Антон", lastName = "Алексеев", birthYear = 1991 }
alex == anton Falsealex == alex Trueanton == alex Falseanton /= alex True
instance Ord Person where compare x y = compare (birthYear y) (birthYear x)
instance Ord Person where compare x y = compare (birthYear y) (birthYear x)
instance Ord Person where x `compare` y = birthYear y `compare` birthYear x
instance Ord Person where compare x y = compare (birthYear y) (birthYear x)
instance Ord Person where x `compare` y = birthYear y `compare` birthYear x
max :: (Ord a) => a → a → a
instance Ord Person where compare x y = compare (birthYear y) (birthYear x)
instance Ord Person where x `compare` y = birthYear y `compare` birthYear x
max :: (Ord a) => a → a → a
max alex anton
instance Ord Person where compare x y = compare (birthYear y) (birthYear x)
instance Ord Person where x `compare` y = birthYear y `compare` birthYear x
max :: (Ord a) => a → a → a
max alex anton
birthYear (max alex anton) == 1988
Каррирование(англ. currying)
max :: (Ord a) => a → a → a
max :: (Ord a) => a → a → amax :: (Ord a) => a → (a → a)
max :: (Ord a) => a → a → amax :: (Ord a) => a → (a → a)
max' = max alex
max :: (Ord a) => a → a → amax :: (Ord a) => a → (a → a)
max' = max alexmax' :: Person → Person
max :: (Ord a) => a → a → amax :: (Ord a) => a → (a → a)
max' = max alexmax' :: Person → Person
max' anton :: Person
max :: (Ord a) => a → a → amax :: (Ord a) => a → (a → a)
max' = max alexmax' :: Person → Person
max' anton :: PersonbirthYear (max' anton) == 1988
Лямбда-функции
Лямбда-функции
(λ)
(\x y → x + y)
(\x y → x + y)(\x y → x + y) :: ?
(\x y → x + y)(\x y → x + y) :: Num a => a → a → a
(\x y → x + y)(\x y → x + y) :: Num a => a → a → a
(\x y → x + y) 3 4
(\x y → x + y)(\x y → x + y) :: Num a => a → a → a
(\x y → x + y) 3 4(\x y → x + y) 3 4 == 7
Кортежи
(1, 2)
(1, 2)('a', 'b')
(1, 2)('a', 'b')(1, 2, 3, 4)
(1, 2)('a', 'b')(1, 2, 3, 4)(1, 'a')
(1, 2)('a', 'b')(1, 2, 3, 4)(1, 'a')('a')
(1, 2)('a', 'b')(1, 2, 3, 4)(1, 'a')('a')( )
(1, 2)('a', 'b')(1, 2, 3, 4)(1, 'a')('a')( )(1, (2, 'a'), 3)
(1, 2)('a', 'b')(1, 2, 3, 4)(1, 'a')('a')( )(1, (2, 'a'), 3)
fst (1, 2) == 1
(1, 2)('a', 'b')(1, 2, 3, 4)(1, 'a')('a')( )(1, (2, 'a'), 3)
fst (1, 2) == 1snd (1, 2) == 2
(1, 2)('a', 'b')(1, 2, 3, 4)(1, 'a')('a')( )(1, (2, 'a'), 3)
fst (1, 2) == 1snd (1, 2) == 2snd (1, (2, 'a'), 3) == (2, 'a')
Списки
[1, 2, 3]['a', 'b', 'c'][ ][ [1, 2], [3, 4] ][ (1, 'a'), (2, 'b'), (3, 'c') ]
head :: [a] → ahead [4, 8, 15, 16, 23, 42] == 4
tail :: [a] → [a]tail [4, 8, 15, 16, 23, 42] == [8, 15, 16, 23, 42]
head :: [a] → ahead [4, 8, 15, 16, 23, 42] == 4
tail :: [a] → [a]tail [4, 8, 15, 16, 23, 42] == [8, 15, 16, 23, 42]
init :: [a] → [a]init [4, 8, 15, 16, 23, 42] == [4, 8, 15, 16, 23]
last :: [a] → alast [4, 8, 15, 16, 23, 42] == 42
length :: [a] → Intlength [4, 8, 15, 16, 23, 42] == 6
null :: [a] → Boolnull [ ] == True null [1, 2, 3] == False
reverse [1, 2, 3] == [3, 2, 1]take 3 [1, 2, 3, 4, 5] == [1, 2, 3]drop 3 [1, 2, 3, 4, 5] == [4, 5]sum [1, 2, 3, 4, 5] == 15[1, 2, 3] ++ [4, 5] == [1, 2, 3, 4, 5]
Генераторысписков,
интервалы,ленивые вычисления
[ x * 2 | x ← [1, 2, 3] ] == [2, 4, 6]pairs = [ (x, y) | x ← [1, 2], y ← ['a', 'b'] ]pairs == [ (1,'a'), (1,'b'), (2,'a'), (2,'b') ]
[ x * 2 | x ← [1, 2, 3] ] == [2, 4, 6]pairs = [ (x, y) | x ← [1, 2], y ← ['a', 'b'] ]pairs == [ (1,'a'), (1,'b'), (2,'a'), (2,'b') ]
[1..5] == [1, 2, 3, 4, 5][2,4..10] == [2, 4, 6, 8, 10][1..] == [1, 2, 3, 4, 5, 6, 7, 8, 9, …]take 3 [1..] == [1, 2, 3]
[ x * 2 | x ← [1, 2, 3] ] == [2, 4, 6]pairs = [ (x, y) | x ← [1, 2], y ← ['a', 'b'] ]pairs == [ (1,'a'), (1,'b'), (2,'a'), (2,'b') ]
[1..5] == [1, 2, 3, 4, 5][2,4..10] == [2, 4, 6, 8, 10][1..] == [1, 2, 3, 4, 5, 6, 7, 8, 9, …]take 3 [1..] == [1, 2, 3]
cycle [1, 2, 3] == [1, 2, 3, 1, 2, 3, 1, 2, 3, … ]take 5 $ cycle [1, 2, 3] == [1, 2, 3, 1, 2]
Функциивысшего порядка
filter :: (a -> Bool) -> [a] -> [a]
filter :: (a -> Bool) -> [a] -> [a]filter (\x -> x `mod` 2 == 0) [1..10] == [2, 4, 8, 10]
filter :: (a -> Bool) -> [a] -> [a]filter (\x -> x `mod` 2 == 0) [1..10] == [2, 4, 8, 10]
map :: (a -> b) -> [a] -> [b]
filter :: (a -> Bool) -> [a] -> [a]filter (\x -> x `mod` 2 == 0) [1..10] == [2, 4, 8, 10]
map :: (a -> b) -> [a] -> [b]map (\x → x + 5) [1,2,3] == [6,7,8]
filter :: (a -> Bool) -> [a] -> [a]filter (\x -> x `mod` 2 == 0) [1..10] == [2, 4, 8, 10]
map :: (a -> b) -> [a] -> [b]map (+5) [1,2,3] == [6,7,8]
filter :: (a -> Bool) -> [a] -> [a]filter (\x -> x `mod` 2 == 0) [1..10] == [2, 4, 8, 10]
map :: (a -> b) -> [a] -> [b]map (+5) [1,2,3] == [6,7,8]
foldl :: (a -> b -> a) -> a -> [b] -> a
filter :: (a -> Bool) -> [a] -> [a]filter (\x -> x `mod` 2 == 0) [1..10] == [2, 4, 8, 10]
map :: (a -> b) -> [a] -> [b]map (+5) [1,2,3] == [6,7,8]
foldl :: (a -> b -> a) -> a -> [b] -> afoldl (\s x -> x + s) 0 [1, 2, 3] == 6
filter :: (a -> Bool) -> [a] -> [a]filter (\x -> x `mod` 2 == 0) [1..10] == [2, 4, 8, 10]
map :: (a -> b) -> [a] -> [b]map (+5) [1,2,3] == [6,7,8]
foldl :: (a -> b -> a) -> a -> [b] -> afoldl (\s x -> x + s) 0 [1, 2, 3] == 6
sum = foldl (\s x -> x + s) 0
Пишемсобственные
функции
null' :: [a] → Bool
null' :: [a] → Boolnull' [ ] = True
null' :: [a] → Boolnull' [ ] = Truenull' _ = False
null' :: [a] → Boolnull' [ ] = Truenull' _ = False
head' :: [a] → a
null' :: [a] → Boolnull' [ ] = Truenull' _ = False
head' :: [a] → ahead' (x:xs) = x
null' :: [a] → Boolnull' [ ] = Truenull' _ = False
head' :: [a] → ahead' (x:xs) = xhead' _ = error 'Empty list!'
null' :: [a] → Boolnull' [ ] = Truenull' _ = False
head' :: [a] → ahead' (x:xs) = xhead' _ = error 'Empty list!'
[1, 2, 3] == (1:(2:(3:[])))
foldl' :: (a -> b -> a) -> a -> [b] -> a
foldl' :: (a -> b -> a) -> a -> [b] -> afoldl' func acc (x:xs) = foldl' func (func acc x) xs
foldl' :: (a -> b -> a) -> a -> [b] -> afoldl' func acc (x:xs) = foldl' func (func acc x) xsfoldl' _ acc _ = acc
foldl' :: (a -> b -> a) -> a -> [b] -> afoldl' func acc (x:xs) = foldl' func (func acc x) xsfoldl' _ acc _ = acc
elem' :: Eq a => a -> [a] -> Bool
foldl' :: (a -> b -> a) -> a -> [b] -> afoldl' func acc (x:xs) = foldl' func (func acc x) xsfoldl' _ acc _ = acc
elem' :: Eq a => a -> [a] -> Boolelem' x (y:yx) | x == y = True | ...
foldl' :: (a -> b -> a) -> a -> [b] -> afoldl' func acc (x:xs) = foldl' func (func acc x) xsfoldl' _ acc _ = acc
elem' :: Eq a => a -> [a] -> Boolelem' x (y:yx) | x == y = True | otherwise = elem' x yx
foldl' :: (a -> b -> a) -> a -> [b] -> afoldl' func acc (x:xs) = foldl' func (func acc x) xsfoldl' _ acc _ = acc
elem' :: Eq a => a -> [a] -> Boolelem' x (y:yx) | x == y = True | otherwise = elem' x yxelem' _ _ = False
foldl' :: (a -> b -> a) -> a -> [b] -> afoldl' func acc (x:xs) = foldl' func (func acc x) xsfoldl' _ acc _ = acc
elem' :: Eq a => a -> [a] -> Boolelem' x (y:yx) | x == y = True | otherwise = elem' x yxelem' _ _ = False
elem' 1 [1, 2, 3] == True
foldl' :: (a -> b -> a) -> a -> [b] -> afoldl' func acc (x:xs) = foldl' func (func acc x) xsfoldl' _ acc _ = acc
elem' :: Eq a => a -> [a] -> Boolelem' x (y:yx) | x == y = True | otherwise = elem' x yxelem' _ _ = False
elem' 1 [1, 2, 3] == True elem' 7 [1, 2, 3] == False
За кадром остались:
За кадром остались:– параметризованные типы
За кадром остались:– параметризованные типы– монады
За кадром остались:– параметризованные типы– монады– ввод/вывод
За кадром остались:– параметризованные типы– монады– ввод/вывод– аппликативные функторы
За кадром остались:– параметризованные типы– монады– ввод/вывод– аппликативные функторы– застежки
Зачем все это нужно:
Зачем все это нужно:– Настоящая кроссплатформенность
Зачем все это нужно:– Настоящая кроссплатформенность– Автоматическое управление памятью
Зачем все это нужно:– Настоящая кроссплатформенность– Автоматическое управление памятью– Отсутсвие побочных эффектов
Зачем все это нужно:– Настоящая кроссплатформенность– Автоматическое управление памятью– Отсутсвие побочных эффектов– Автоматическое распараллеливание
Зачем все это нужно:– Настоящая кроссплатформенность– Автоматическое управление памятью– Отсутсвие побочных эффектов– Автоматическое распараллеливание– Строгая типизация
Зачем все это нужно:– Настоящая кроссплатформенность– Автоматическое управление памятью– Отсутсвие побочных эффектов– Автоматическое распараллеливание– Строгая типизация– и не только
Насколько быстр Haskell?
Насколько быстр Haskell?
Что можно написать на Haskell?
Что можно написать на Haskell?– CLI-приложения (например, Darcs)
Что можно написать на Haskell?– CLI-приложения (например, Darcs)– GUI-приложения (wxHaskell, gtk2hs, etc)
Что можно написать на Haskell?– CLI-приложения (например, Darcs)– GUI-приложения (wxHaskell, gtk2hs, etc)– веб-приложения (Yesod, Happstack, etc)
Что можно написать на Haskell?– CLI-приложения (например, Darcs)– GUI-приложения (wxHaskell, gtk2hs, etc)– веб-приложения (Yesod, Happstack, etc)– компиляторы, парсеры (Alex, Happy)
Что можно написать на Haskell?– CLI-приложения (например, Darcs)– GUI-приложения (wxHaskell, gtk2hs, etc)– веб-приложения (Yesod, Happstack, etc)– компиляторы, парсеры (Alex, Happy)– модули ядра Linux
Что можно написать на Haskell?– CLI-приложения (например, Darcs)– GUI-приложения (wxHaskell, gtk2hs, etc)– веб-приложения (Yesod, Happstack, etc)– компиляторы, парсеры (Alex, Happy)– модули ядра Linux– и многое другое
Другие ФП-языки:
Другие ФП-языки:– Erlang
Другие ФП-языки:– Erlang– OCaml
Другие ФП-языки:– Erlang– OCaml– Standart ML
Другие ФП-языки:– Erlang– OCaml– Standart ML– Common Lisp
Другие ФП-языки:– Erlang– OCaml– Standart ML– Common Lisp– Scheme, Racket
Другие ФП-языки:– Erlang– OCaml– Standart ML– Common Lisp– Scheme, Racket– Clojure
Другие ФП-языки:– Erlang– OCaml– Standart ML– Common Lisp– Scheme, Racket– Clojure– и другие
Литературапо ФП
Подборка ссылок:
Подборка ссылок:– http://fprog.ru/planet/
Подборка ссылок:– http://fprog.ru/planet/– http://erlanger.ru/
Подборка ссылок:– http://fprog.ru/planet/– http://erlanger.ru/– http://it-talk.org/
Подборка ссылок:– http://fprog.ru/planet/– http://erlanger.ru/– http://it-talk.org/– http://groups.google.ru/group/haskell-russian
Подборка ссылок:– http://fprog.ru/planet/– http://erlanger.ru/– http://it-talk.org/– http://groups.google.ru/group/haskell-russian– http://groups.google.ru/group/erlang-russian
Подборка ссылок:– http://fprog.ru/planet/– http://erlanger.ru/– http://it-talk.org/– http://groups.google.ru/group/haskell-russian– http://groups.google.ru/group/erlang-russian– http://groups.google.ru/group/clojure-russian
Подборка ссылок:– http://fprog.ru/planet/– http://erlanger.ru/– http://it-talk.org/– http://groups.google.ru/group/haskell-russian– http://groups.google.ru/group/erlang-russian– http://groups.google.ru/group/clojure-russian– http://habrahabr.ru/hub/haskell
Подборка ссылок:– http://fprog.ru/planet/– http://erlanger.ru/– http://it-talk.org/– http://groups.google.ru/group/haskell-russian– http://groups.google.ru/group/erlang-russian– http://groups.google.ru/group/clojure-russian– http://habrahabr.ru/hub/haskell– http://goo.gl/VUvjk (эта презентация)
Спасибо за внимание!
Александр Алексеев
http://eax.me/