3. Класс = поля + методы
Объект класса
Наследование, ассоциация
Функторы, делегаты
Интерфейсы
ООП-паттерны
Модуль = типы + функции
Значение АТД
Комбинаторы, композиция
Лямбды, ФВП, продолжения
Обобщение типов
???
Объектно -
ориентированное
программирование
Функциональное
программирование
4. Класс = поля + методы
Объект класса
Наследование, ассоциация
Функторы, делегаты
Интерфейсы
ООП-паттерны
Модуль = типы + функции
Значение АТД
Комбинаторы, композиция
Лямбды, ФВП, продолжения
Обобщение типов
Функциональные идиомы
Объектно -
ориентированное
программирование
Функциональное
программирование
6. Функциональные идиомы
● Foldable, Traversable
● Functors
● Applicative Functors
● Monoids
● Monads
● Existential types
● Lenses
● Zippers
● Comonads
● GATDs
В чем разница между понятиями
“ООП-паттерн” и “ФП-идиома”?
7. ООП-паттерн vs Идиома
Паттерн: подход “снаружи”.
Несколько классов связываются в единую
систему с обобщающими интерфейсами.
Идиома: подход “изнутри”.
Идиома структурирует данные, обобщает и
пополняет их свойства.
9. Список
-- Список на АТД:
data List a = Empty | Cons a (List a)
myList1 = Cons 1 (Cons 2 (Cons 3 Empty))
-- Списки в Haskell:
myList1 = [1, 2, 3]
myList2 = 1 : 2 : 3 : []
myList3 = 1 : [2, 3]
http://learnyouahaskell.com/zippers
10. Zipper для списка
data Zipper a = Zip [a] a [a]
toLeft (Zip xs a (y:ys)) = Zip (a:xs) y ys
toRight (Zip (x:xs) a ys) = Zip xs x (a:ys)
extract (Zip _ a _) = a
http://learnyouahaskell.com/zippers
12. Zip [2, 1, 0] 3 [4..10]
Текущий элемент
Сохраненный Контекст
13. data Tree a = Empty | Node a (Tree a) (Tree a)
data Direction = L | R
modify :: (a -> a) -> Tree a -> [Direction] -> Tree a
Дерево
1
2
5 3
1
2
50 30
14. data Tree a = Empty | Node a (Tree a) (Tree a)
data Direction = L | R
modify :: (a -> a) -> Tree a -> [Direction] -> Tree a
newTree1 = modify (*10) myTree [R, L]
newTree2 = modify (*10) newTree1 [R, R]
Изменение дерева
1
2
50 30
15. data Tree a = Empty | Node a (Tree a) (Tree a)
data NodeCtx a = LCtx a (Tree a)
| RCtx a (Tree a)
data TreeZipper a = TZ (Tree a) [NodeCtx a]
extract (TZ (Node a _ _) _) = a
Zipper для дерева
16. goLeft :: TreeZipper a -> TreeZipper a
goLeft (TZ (Node a l r) ctxs) = (TZ l (LCtx a r : ctxs))
goRight :: TreeZipper a -> TreeZipper a
goRight (TZ (Node a l r) ctxs) = (TZ r (RCtx a l : ctxs))
goUp :: TreeZipper a -> TreeZipper a
goUp = ...
Zipper для дерева
18. fromZipper :: TreeZipper a -> Tree a
fromZipper (TZ cur []) = cur
fromZipper z = fromZipper (goUp z)
Сборка дерева
RCtx 1
LCtx 2 3
5
1
2
35
19. data TreeDir = U | L | R
modify :: (a -> a) -> TreeZipper a -> [TreeDir] -> TreeZipper a
modify f (TZ (Node a l r) ctxs) [] = TZ (Node (f a) l r) ctxs
modify f z (L:dirs) = modify f (goLeft z) dirs
modify f z (R:dirs) = modify f (goRight z) dirs
modify f z (U:dirs) = modify f (goUp z) dirs
Изменение дерева
22. “Жизнь” без идиом
type Cell = (Int, Int)
type Grid = [Cell]
step :: Grid -> Grid
step p = let
next all [] = []
next all cur@((aX, aY) : alives) =
[(x, y) | x <- lim aX, y <- lim aY, length (neighbours8 (x, y) all) == 3]
++ (next all alives)
alive all cell = length (neighbours8 cell all) `elem` [2,3]
in L.nub $ filter (alive p) p ++ (next p p)
23. “Жизнь” без идиом
type Cell = (Int, Int)
type Grid = [Cell]
step :: Grid -> Grid
step p = let
next all [] = []
next all cur@((aX, aY) : alives) =
[(x, y) | x <- lim aX, y <- lim aY, length (neighbours8 (x, y) all) == 3]
++ (next all alives)
alive all cell = length (neighbours8 cell all) `elem` [2,3]
in L.nub $ filter (alive p) p ++ (next p p)
这是什么?
29. data Layer a = Layer a
comonadCantorRule :: Layer Segments -> Segments
comonadCantorRule layer = cantorGen (extract layer)
comonadCantorGen :: Layer Segments -> Layer Segments
comonadCantorGen layer = layer =>> comonadCantorRule
> take 2 $ iterate comonadCantorGen cantorLayer
[ Layer [(0.0,9.0)], Layer [(0.0,3.0),(6.0,9.0)] ]
Фрактал - список слоев
30. Определение комонады
class Functor w => Comonad w where
extract :: w a -> a
duplicate :: w a -> w (w a)
extend :: (w a -> b) -> w a -> w b
extend f = fmap f . duplicate
duplicate = extend id
(=>>) :: Comonad w => w a -> (w a -> b) -> w b
cx =>> rule = extend rule cx
31. Простейшая комонада Layer
data Layer a = Layer a
instance Functor Layer where
fmap f (Layer a) = Layer (f a)
instance Comonad Layer where
duplicate (Layer a) = Layer (Layer a) -- w a -> w (w a)
extract (Layer a) = a -- w a -> a
35. Зипперы - это комонады
http://habrahabr.ru/post/225473/
data Universe a = Universe [a] a [a]
left, right :: Universe a -> Universe a
left (Universe (a:as) x bs) = Universe as a (x:bs)
right (Universe as x (b:bs)) = Universe (x:as) b bs
extract :: Universe a -> a
extract (Universe _ x _) = x
duplicate :: Universe a -> Universe (Universe a)
duplicate u = Universe (tail $ iterate left u) u (tail $ iterate right u)