on dependabot/npm_and_yarn/reveal.js/socket.io-parser-3.3.3
help
sign in
3author: Ilya Kostyuchenko
6# Функциональное программирование
14 fmap :: (a -> b) -> f a -> f b
17```{ .haskell .fragment }
18class Functor f => Alternative f where
19 (<|>) :: f a -> f a -> f a
25## Библиотека про математику
29static int add(int x, int y) {
34["Нам для сертификации надо чтобы каждая функция логировала свой вызов."]{.fragment}
41static int add(int x, int y) {
482. Невозможно рефакторить
493. Почему функция для складывания чисел умеет логи?
56static Pair<Integer, String> add(int x, int y, string log) {
57 return new Pair(x + y, log + "add");
611. ~~Неявная зависимость~~
622. ~~Невозможно рефакторить~~
633. Неудобно программировать
643. Почему функция для складывания чисел умеет логи?
71static int add(int x, int y, Logger log) {
771. ~~Неявная зависимость~~
782. ~~Невозможно рефакторить~~
793. Неудобно программировать
803. ~~Почему функция для складывания чисел умеет логи?~~
85add :: Int -> Int -> (Int, String)
86add x y = (x + y, "add " + show x + show y)
89[Неудобно программировать]{ .fragment }
91```{ .haskell .fragment }
92add :: Int -> Int -> Int
93times :: Int -> Int -> Int
95add8AndDouble :: Int -> Int
96add8AndDouble = times 2 . add 8
102add :: Int -> Int -> (Int, String)
103times :: Int -> Int -> (Int, String)
106```{ .haskell .fragment }
107add8AndDouble :: Int -> (Int, String)
108add8AndDouble x = (y2, log1 <> log2)
111 (y2, log2) = times 2 y1
114{height=200px .fragment}
116```{ .haskell .fragment }
117add8AndDouble :: Int -> Int
118add8AndDouble = times 2 . add 8
124data WithLog a = WithLog a String
127```{ .haskell .fragment }
128add :: Int -> Int -> WithLog Int
129times :: Int -> Int -> WithLog Int
132```{ .haskell .fragment }
133add8AndDouble :: Int -> WithLog Int
134add8AndDouble = times 2 `magic` add 8
137```{ .haskell .fragment }
139 (Int -> WithLog Int) ->
140 (Int -> WithLog Int) ->
144```{ .haskell .fragment }
145magic f g x1 = WithLog x3 (log1 <> log2)
147 (WithLog x2 log1) = g x1
148 (WithLog x3 log2) = f x2
155 (Int -> WithLog Int) ->
156 (Int -> WithLog Int) ->
160```{ .haskell .fragment }
162 (Int -> WithLog Int) ->
163 (Int -> WithLog Int) ->
167```{ .haskell .fragment }
168add8AndDouble :: Int -> WithLog Int
169add8AndDouble = times 2 <=< add 8
175factor :: Int -> WithLog [Int]
177sum :: [Int] -> WithLog Int
180```{ .haskell .fragment }
181sumFactors :: Int -> WithLog [Int]
182sumFactors = sum <=< factor -- Doesn't work :(
185```{ .haskell .fragment }
187 (Int -> WithLog Int) ->
188 (Int -> WithLog Int) ->
192```{ .haskell .fragment }
199```{ .haskell .fragment }
209getCoffee :: Order -> Maybe Coffee
210payForCoffee :: Coffee -> Maybe Payment
213```{ .haskell .fragment }
214buyCoffee :: Order -> Maybe Payment
215buyCoffee = payForCoffee <=< getCoffee
218```{ .haskell .fragment }
219getCoffee :: Order -> Either CoffeeError Coffee
220payForCoffee :: Coffee -> Either CoffeeError Payment
223```{ .haskell .fragment }
224buyCoffee :: Order -> Either CoffeeError Payment
225buyCoffee = payForCoffee <=< getCoffee
228```{ .haskell .fragment }
239class Applicative m => Monad m where
240 (<=<) :: (b -> m c) -> (a -> m b) -> (a -> m c)
243```{ .haskell .fragment }
244instance Monad Maybe where
245 (<=<) f g x = case g x of
250```{ .haskell .fragment }
251instance Monad (Either e) where
252 (<=<) f g x = case g x of
257```{ .haskell .fragment }
258instance Monad WithLog where
259 (<=<) f g x = WithLog x3 (log1 <> log2)
261 (WithLog x2 log1) = g x
262 (WithLog x3 log2) = f x2
267### Больше операторов!
269```{ .haskell .fragment }
270(<=<) :: Monad m => (b -> m c) -> (a -> m b) -> (a -> m c)
272```{ .haskell .fragment }
273buyCoffee :: Order -> Maybe Payment
274buyCoffee = payForCoffee <=< getCoffee
277```{ .haskell .fragment }
278flip :: (a -> b -> c) -> (b -> a -> c)
282```{ .haskell .fragment }
283(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> (a -> m c)
287```{ .haskell .fragment }
288buyCoffee = getCoffee >=> payForCoffee
293### Маленькое отступление
295`f :: () -> a` эквивалентно `f :: a`
297[Потому что у `()` всего одно значение (`()`), а любая функция для одинаковых аргументов всегда возвращает одинаковые значения (потому что по-другому невозможно).]{ .fragment }
302(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> (a -> m c)
305```{ .haskell .fragment }
306(>>=) :: Monad m => m b -> (b -> m c) -> m c
309```{ .haskell .fragment }
310buyCoffee :: Order -> Maybe Payment
311buyCoffee order = getCoffee order >>= payForCoffee
314```{ .haskell .fragment }
315maybeBuyCoffee :: Maybe Order -> Maybe Payment
316maybeBuyCoffee mOrder = mOrder >>= buyCoffee
319```{ .haskell .fragment }
320(>>=) :: Monad m => m b -> (b -> m c) -> m c
323```{ .haskell .fragment }
324(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> (a -> m c)
327```{ .haskell .fragment }
328 (() -> m b) -> (b -> m c) -> (() -> m c)
330```{ .haskell .fragment }
331 m b -> (b -> m c) -> m c
337(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> (a -> m c)
341(>>=) :: Monad m => m b -> (b -> m c) -> m c
342(>>=) mb bmc = ( (\() -> mb) >=> bmc ) ()
345```{ .haskell .fragment }
346(>>=) mb bmc = ( (\() -> mb) >=> bmc ) ()
350-- ^-----------------------^
356### Время раскрыть ложь
359class Applicative m => Monad m where
360 (>>=) :: m a -> (a -> m b) -> m b
364```{ .haskell .fragment }
367 (ma >>= return) == ma
370```{ .haskell .fragment }
376[`return` -- нейтральный элемент по `>=>`]{.fragment}
378```{ .haskell .fragment }
382 (return x >>= f) == f x
388instance Monad Maybe where
389 ma >>= f = case ma of
396```{ .haskell .fragment }
397instance Monad (Either e) where
398 ma >>= f = case ma of
405```{ .haskell .fragment }
406instance Monad WithLog where
407 (WithLog a log1) >>= f = WithLog b (log1 <> log2)
411 return a = WithLog a ""
421getCoffee :: Markup -> Order -> Coffee
422payForCoffee :: Markup -> Coffee -> Payment
424buyCoffee :: Markup -> Order -> Payment
425buyCoffee markup = payForCoffee markup . getCoffee markup
428```{ .haskell .fragment }
429data Reader r a = Reader
430 { runReader :: r -> a
434[`r` -- то, что у нас в "окружении".]{ .fragment }
439data Reader r a = Reader { runReader :: r -> a }
441getCoffee :: Order -> Markup -> Coffee
442payForCoffee :: Coffee -> Markup -> Payment
445```{ .haskell .fragment }
446getCoffee :: Order -> Reader Markup Coffee
447payForCoffee :: Coffee -> Reader Markup Payment
450```{ .haskell .fragment }
451type PricingEnv = Reader Markup
454```{ .haskell .fragment }
455getCoffee :: Order -> PricingEnv Coffee
456payForCoffee :: Coffee -> PricingEnv Payment
459```{ .haskell .fragment }
460buyCoffee :: Order -> PricingEnv Payment
461buyCoffee = payForCoffee <=< getCoffee
464```{ .haskell .fragment }
466payment = runReader (buyCoffee order) markup
472data Reader r a = Reader
473 { runReader :: r -> a
476instance Monad (Reader r) where
477 return a = Reader (\_ -> a)
479 (Reader g) >>= f = Reader ( \r -> runReader (f (g r)) r )
482```{ .haskell .fragment}
483 (>>=) :: Reader r a -> (a -> Reader r b) -> Reader r b
485 (Reader g) >>= f = Reader ( \r -> runReader (f (g r)) r )
490-- ^-----------------^
498getCoffeePrice :: Markup -> Coffee -> Price
499getDiscount :: Markup -> Coffee -> Price
500getPayment :: Markup -> Price -> Payment
502payForCoffee :: Markup -> Coffee -> Payment
503payForCoffee markup coffee = getPayment markup amount
505 coffeePrice = getCoffeePrice markup coffee
506 discount = getDiscount markup coffee
507 amount = coffeePrice - discount
510```{ .haskell .fragment }
511type PricingEnv = Reader Markup
513getCoffeePrice :: Coffee -> PricingEnv Price
514getDiscount :: Coffee -> PricingEnv Price
515getPayment :: Price -> PricingEnv Payment
517payForCoffee :: Coffee -> PricingEnv Payment
519 coffee >>= getCoffeePrice >>= \coffeePrice ->
520 coffee >>= getDiscount >>= \discount ->
521 getPayment (coffeePrice - discount)
528```{ .haskell .fragment }
530qux :: a -> Reader r b
533foo = bar >>= \x -> qux x
536```{ .haskell .fragment }
538 -- (x :: a) <- (bar :: Reader r a)
543```{ .haskell .fragment }
545 -- (x :: a) <- (bar :: Reader r a)
547 -- (y :: b) <- (qux x :: Reader r b)
552```{ .haskell .fragment }
553foo = bar >>= \x -> qux x >>= return
559type PricingEnv = Reader Markup
561getCoffeePrice :: Coffee -> PricingEnv Price
562getDiscount :: Coffee -> PricingEnv Price
563getPayment :: Price -> PricingEnv Payment
565payForCoffee :: Coffee -> PricingEnv Payment
567 coffee >>= getCoffeePrice >>= \coffeePrice ->
568 coffee >>= getDiscount >>= \discount ->
569 getPayment (coffeePrice - discount)
572```{ .haskell .fragment }
573payForCoffee :: Coffee -> PricingEnv Payment
574payForCoffee coffee = do
575 coffeePrice <- getCoffeePrice coffee
576 discount <- getDiscount coffee
577 getPayment (coffeePrice - discount)
585payForCoffee :: Coffee -> PricingEnv Payment
586payForCoffee coffee = do
587 coffeePrice <- getCoffeePrice coffee
588 discount <- getDiscount coffee
589 getPayment (coffeePrice - discount)
593```{ .haskell .fragment }
594payForCoffee :: Coffee -> PricingEnv Payment
595payForCoffee coffee = do
596 coffeePrice <- getCoffeePrice coffee
597 discount <- getDiscount coffee
598 let amount = coffeePrice - discount
605type PricingEnv = Reader Markup
608data Coffee = Coffee { getCoffeePrice :: Price }
610getCoffeePrice :: Coffee -> PricingEnv Price
613```{ .haskell .fragment }
614data Reader r a = Reader { runReader :: r -> a}
617```{ .haskell .fragment }
619ask = Reader (\r -> r)
622```{ .haskell .fragment }
623getCoffeePrice :: Coffee -> PricingEnv Price
624getCoffeePrice coffee = do
625 -- (markup :: Markup) <- (ask :: PricingEnv Markup)
627 let coffePrice = getCoffeePrice coffee
628 return (coffee + markup)
634data Order = Order { orderCoffee :: Coffee, orderId :: Int }
637```{ .haskell .fragment }
638createOrder :: Coffee -> Order
641[Откуда брать `orderId`?]{ .fragment }
643```{ .haskell .fragment }
644createOrder :: Coffee -> Reader Int Order
645createOrder coffee = do
647 return (Order coffee newId)
652```{ .haskell .fragment }
653createOrders :: [Coffee] -> Reader Int [Order]
656```{ .haskell .fragment }
657mapM :: (Monad m) => (a -> m b) -> [a] -> m [b]
660```{ .haskell .fragment }
661createOrders = mapM createOrder
667createOrders :: [Coffee] -> Reader Int [Order]
668createOrders = mapM createOrder
671[Все `id` будут одинаковые.]{ .fragment }
673[`Reader` эквивалентно глобальной **константе**.]{ .fragment }
675[Айдишники -- скорее глобальная **переменная**.]{ .fragment }
677[-- Но у нас же нет переменных!]{ .fragment }
679[-- Да, нет!]{ .fragment }
685```{ .haskell .fragment }
686data State s a = ... -- s -- само состояние
689put :: s -> State s ()
692```{ .haskell .fragment }
693data State s a = State { runState :: s -> (a, s) }
696get = State (\s -> (s, s))
698put :: s -> State s ()
699put s = State (\_ -> ((), s))
705data State s a = State { runState :: s -> (a, s) }
708```{ .haskell .fragment }
709class Monad (State s) where
710 return x = State (\s -> (x, s))
712 (>>=) :: State s a -> (a -> State s b) -> State s b
713 (State f) >>= g = State go
715 go s = runState (g a) s'
724```{ .haskell .fragment }
725getNewId :: State Int Int
732[-- Это какой-то процедурный языке получается!]{ .fragment }
734[-- Лучше!*]{ .fragment }
736```{ .haskell .fragment }
737createOrder :: Coffee -> State Int Order
738createOrder coffee = do
740 return (Order coffee newId)
742createOrders :: [Coffee] -> State Int [Order]
743createOrders = mapM createOrder
750```{ .haskell .fragment }
754 (>>=) :: [a] -> (a -> [b]) -> [b]
756 (a : aa) >>= f = f a <> (a >>= f)
759[Контекст недетерменированности (нескольких вариантов)]{ .fragment }
761```{ .haskell .fragment }
767-- [(1,1),(1,2),(1,3),(1,4),(1,5),(2,1),(2,2),(2,3),(2,4),(2,5),(3,1),(3,2),(3,3),(3,4),(3,5),(4,1),(4,2),(4,3),(4,4),(4,5),(5,1),(5,2),(5,3),(5,4),(5,5)]
774```{ .haskell .fragment }
775data Identity a = Identity { runIdentity :: a }
777class Monad Identity where
778 return x = Identity x
780 (>>=) :: Identity a -> (a -> Identity b) -> Identity b
781 (Identity a) >>= f = Identity (f a)
787class Applicative m => Monad m where
789 (>>=) :: m a -> (a -> m b) -> m b
792[Монада -- перегрузка композиции функций.]{.fragment }
794```{ .haskell .fragment }
795class Functor m => Applicative m where
797 (<*>) :: m (a -> b) -> m a -> m b
800[Аппликативный функтор -- перегрузка применения функций.]{.fragment }
802[-- Почему не `(a -> b) -> f a -> f b`.]{.fragment }
804[-- Это `fmap`. (И функции нескольких аргументов)]{.fragment }
809(a -> b) -> f a -> f b
812```{ .haskell .fragment }
813(a -> (b -> c)) -> f a -> f (b -> c)
816```{ .haskell .fragment }
817getMarkup :: Env Markup
819getPayment :: Markup -> Price -> Payment
822```{ .haskell .fragment }
823payment :: Env Payment
824payment = fmap getPayment getMarkup <*> getPrice
827```{ .haskell .fragment }
828payment = fmap getPayment getMarkup <*> getPrice
830-- Env Markup -> Env (Price -> Payment)
833```{ .haskell .fragment }
837```{ .haskell .fragment }
838payment = getPayment <$> getMarkup <*> getPrice
844(<*>) :: m (a -> b) -> m a -> m b
851```{ .haskell .fragment }
852ap :: Monad m => m (a -> b) -> m a -> m b
859```{ .haskell .fragment }
860instance Monad ... where ...
862instance Applicative ... where
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list