6 <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
8 <link rel="stylesheet" href="css/reset.css">
9 <link rel="stylesheet" href="css/reveal.css">
10 <link rel="stylesheet" href="css/theme/superblack.css">
12 <!-- Theme used for syntax highlighting of code -->
13 <link rel="stylesheet" href="lib/css/monokai.css">
15 <!-- Printing and PDF exports -->
17 var link = document.createElement('link');
18 link.rel = 'stylesheet';
19 link.type = 'text/css';
20 link.href = window.location.search.match(/print-pdf/gi) ? 'css/print/pdf.css' : 'css/print/paper.css';
21 document.getElementsByTagName('head')[0].appendChild(link);
29 <h2>Функциональное программирование</h2>
30 <aside class="notes" data-markdown>
31 Функциональное программирование это не про использование map filter reduce.
33 Функциональное программирование это вообще ортогонально к ооп.
35 ИМХО проблема с ООП -- наследование (которое тоже ортогонально к ООП) -- нет разграничения между абстракцией и
38 и вообще обзывание это функциональным программированием -- не совсем правильно.
40 то, что мы сейчас будем пытаться сделать -- сделать код более переиспользуемым.
42 сделать наши данные максимально тупыми => переиспользуемыми.
44 пытаться комбинировать слишком умные куски -- не получится -- слишком сложно.
46 мы хотим сделать простые куски, которые просто комбинировать и еще чтобы компилятор проверял эти наши
47 комбинации на валидность.
50 <section data-markdown>
51 Функциональное программирование:
52 > функции -- это тоже данные.
54 `Int -> Bool` (функция) -- ровно такие же данные как и `Int`. Их также можно складывать в структуры,
55 передавать как аргументы и т. п.
67 <code class="java">int x;</code>
72 <code class="haskell">x :: Int</code>
79 <code class="java">int f(int x)</code>
84 <code class="haskell">f :: Int -> Int</code>
91 <code class="java">static <T> T f(T x)</code>
97 <code class="haskell">f :: a -> a</code>
108 <code class="java">static <T> T f(T x)</code>
113 <code class="haskell">f :: a -> a</code>
118 <td class="fragment">
120 <code class="java">f(x);</code>
123 <td class="fragment">
125 <code class="haskell">f x</code>
129 <tr class="fragment">
132 <code class="java">f(x, y);</code>
137 <code class="haskell">f x y</code>
139 <pre class="fragment">
140 <code class="haskell">f x y = (f x) y</code>
142 <aside class="notes">
156 <code class="java">static <T> T f(T x)
157static <T> T g(T x)</code>
162 <code class="haskell">f :: a -> a
167 <tr class="fragment">
170 <code class="java">f(g(x));
174 <td class="fragment">
176 <code class="haskell">f (g x)
191 <pre><code class="haskell">f :: a -> a
192g :: a -> a</code></pre>
193 <pre class="fragment"><code class="haskell">f (g x)</code></pre>
194 <pre class="fragment"><code class="haskell">(f . g) x == f (g x)</code></pre>
195 <pre class="fragment"><code class="haskell">h = f . g
196h x == f (g x)</code></pre>
199 <pre><code class="haskell">f :: a -> a
203h = f . g</code></pre>
205 <h3 class="fragment">моноид</h3>
207 <aside class="notes" data-markdown>
208 моноид -- у тебя есть две штуки одного типа и ты можешь получить еще одну
212 Это очень простой способ рождения сложности из простоты
214 причем тип h выводится из определения. Нам его указывать не надо.
216 если у нас изначальные маленькие кусочки хорошо описаны, то порожденные большие кусочки будут автоматически
226 Бинарная асоциативная операция
229 <pre><code class="haskell fragment">(.) :: (a -> a) -> (a -> a) -> (a -> a)</code></pre>
235 <pre><code class="haskell fragment">id :: a -> a
245 <h3>Чисто функционаьлный</h3>
246 <p class="fragment" data-markdown>Все что функция может сделать -- посмотреть на свои аргументы это вернуть
248 <aside class="notes" data-markdown>Нельзя просто произвольно распечатать строку в консоль, нельзя просто
250 отправить запрос на бд, нельзя просто произвольно изменить глобальную переменную.</aside>
253 <h3>Referential transparency</h3>
254 <h5>(Любую константу можно заменить на само значение)</h5>
255 <pre><code class="java fragment">int x = 8;
257System.out.println(y + " might be the same as " + y);</code></pre>
258 <pre><code class="java fragment">int x = 8;
259System.out.println(x++ + " might be the same as " + x++);</code></pre>
261 <aside class="notes" data-markdown>Сильно упрощает рефакторинг и понимание кода.</aside>
264 <h3>Нет переменных, циклов и условных переходов</h3>
266 <p class="fragment" data-markdown>
267 Зато есть константы и нормальная рекурсия
269 (А переходов вообще нет)
273 <h3>Очень ленивый</h3>
275 <pre><code class="haskell fragment">xs = [4, 1, 3, 2]
279 <p class="fragment" data-markdown>
280 `xs'` не нужен чтобы распечатать `xs`, поэтому сортироваться ничто не будет.
282 (Зачем делать то, что можно не делать)
286 <p>Если хотите быстро и просто потыкаться, тут есть интерктивная штука:</p>
287 <a href="https://www.haskell.org">haskell.org</a>
298 <pre><code class="haskell">add2 :: Int -> Int
299add2 x = x + 2</code></pre>
300 <p>Все функции и константы всегда обозначаются словами с маленькой буквы без пробелов.</p>
301 <p>(Константы это просто функции с нулем аргументов.)</p>
304 <h3>Pattern mathcing</h3>
305 <pre><code class="haskell">fixBuz :: Int -> String
309divide8 _ = "Some other number"</code></pre>
312 Так матчить можно произвольные структуры произвольного уровня вложенности.
314 `_` -- специальное название константы, которое говорит что вам все равно что в ней лежит.
316 <aside class="notes" data-markdown>
317 функции объявляются в несколькро строк. Первая -- обьявленик типа функции,
318 а последубщие -- реализация. В общем случае тип можно не указывать, но указывать тип у высказыванй на самом
319 верхнем уровне (не вложенные) считается хорошим тоном и улучшает выведение типов и ошибки компиляции.
321 У функции может быть несколько реализаций: какая из них вызовется зависит от значений передаваемых
322 аргументов. матчинг произхводится сверху вниз.
324 если в аргемантах написано слово с маленькой буквы, то значение аргумента биндится на эту константу.
333 <pre><code class="haskell">data Foo = Bar
335foo = Bar</code></pre>
338 `Foo` -- тип структуры. `Bar` -- конструктор структуры.
340 Тут у `Foo` всего одно значение `Bar`.
344 <h3>Произведение типов</h3>
345 <h5>(обычные поля структур)</h5>
346 <aside class="notes" data-markdown>
347 После констрктора можно укзать существующие типы, которые в нем храняться.
350 <pre><code class="haskell">data PersonType = Person String Int</code></pre>
351 <pre><code class="haskell fragment">vasya :: PersonType
352vasya = Person "Vasya" 8
353-- тип можно не укзывать
354petya = Person "Petya" 5</code></pre>
355 <pre><code class="haskell fragment">getName :: PersonType -> String
356getName (Person name _) = name</code></pre>
357 <pre><code class="haskell fragment">greetPerson :: PersonType -> String
358greetPerson p = "Hello, " ++ getName p</code></pre>
359 <pre><code class="haskell fragment">greetPerson petya
360-- "Hello, Petya"</code></pre>
363 <h3>Еще немного функций</h3>
364 <pre><code class="haskell fragment">greetPerson :: PersonType -> String
365greetPerson p = "Hello, " ++ getName p</code></pre>
367 <pre><code class="haskell fragment">greetPerson :: PersonType -> String
368greetPerson p = "Hello, " ++ name
370 name = getName p</code></pre>
371 <pre><code class="haskell fragment">greetPerson :: PersonType -> String
372greetPerson p = "Hello, " ++ name
374 getName' (Person name _) = name
375 name = getName' p</code></pre>
378 <pre><code class="haskell">data PersonType = Person String Int
380getName :: PersonType -> String
381getName (Person name _) = name</code></pre>
382 <pre><code class="haskell fragment">greetName :: String -> String
383greetName name = "Hello, " ++ name</code></pre>
384 <pre><code class="haskell fragment">greetPerson :: PersonType -> String
385greetPerson p = greetName (getName p)</code></pre>
386 <pre><code class="haskell fragment">greetPerson :: PersonType -> String
387greetPerson = greetName . getName</code></pre>
388 <pre><code class="haskell fragment">greetPerson petya
389-- "Hello, Petya"</code></pre>
390 <pre><code class="haskell fragment">(greetName . getName) petya
391-- "Hello, Petya"</code></pre>
395 <aside class="notes" data-markdown>
396 Функции нескольких аргументов -- странный синтаксис -- потом расскажу.
399 <pre><code class="haskell fragment">data Bool = False | True</code></pre>
400 <pre><code class="haskell fragment">x :: Bool
402y = False</code></pre>
404 <pre><code class="haskell fragment">ifThenElse :: (Bool, a, a) -> a</code></pre>
405 <pre><code class="haskell fragment">ifThenElse (True, a, _) = a
406ifThenElse (False, _, b) = b</code></pre>
407 <pre><code class="haskell fragment">ifThenElse (True, "Hello", "World")
408-- "Hello"</code></pre>
410 <pre><code class="haskell fragment">ifThenElse (False, "Hello", "World")
411-- "World"</code></pre>
415 <pre><code class="haskell">data CircleType = Circle Double Double Double
416data RectangleType = Rectangle Double Double Double Double
418 <pre><code class="haskell fragment">data Shape =
419 CircleShape CircleType | RectangleShape RectangleType</code></pre>
420 <pre><code class="haskell fragment">surface :: Shape -> Double</code></pre>
421 <pre><code class="haskell fragment">surface (CircleShape (Circle _ _ r)) =
422 pi * r ^ 2</code></pre>
423 <pre><code class="haskell fragment">surface (RectangleShape (Rectangle x1 y1 x2 y2)) =
424 (abs (x2 - x1)) * (abs (y2 - y1))</code></pre>
425 <pre><code class="haskell fragment">shape = CircleShape (Circle 0 0 2)
429 <pre><code class="haskell fragment">otherShape = RectangleShape (Rectangle 1 2 3 4)
437 <h2>И еще немного функций</h2>
440 <h3>Лямбда-выражения</h3>
442 <pre><code class="haskell fragment">add8 :: Int -> Int</code></pre>
443 <pre><code class="haskell fragment">add8 x = x + 8</code></pre>
444 <pre><code class="haskell fragment">add8 = \x -> x + 8</code></pre>
445 <p data-markdown class="fragment">
448 (λ печатать тяжело)</p>
450 <pre><code class="haskell fragment">foo :: (Int -> Int) -> Int</code></pre>
451 <pre><code class="haskell fragment">foo add8</code></pre>
452 <pre><code class="haskell fragment">foo (\x -> x + 8)</code></pre>
455 <h3>Давайте придумаем синтаксис для функции нескольких аргументов!</h3>
458 <pre><code class="haskell">x, y :: Int
463 <pre><code class="haskell fragment">xPlusY :: Int
464xPlusY = add x y</code></pre>
465 <p class="fragment" data-markdown>Применение функции -- лево-ассоциативно</p>
466 <pre><code class="haskell fragment">xPlusY = (add x) y</code></pre>
467 <pre><code class="haskell fragment">xPlusY = f y
468f = add x</code></pre>
469 <pre><code class="haskell fragment">f :: Int -> Int</code></pre>
470 <pre><code class="haskell fragment">add :: Int -> (Int -> Int)</code></pre>
473 <pre><code class="haskell">add :: Int -> (Int -> Int)</code></pre>
474 <p class="fragment" data-markdown>Тип `->` -- право-ассоциативный</p>
476 <pre><code class="haskell fragment">add :: Int -> Int -> Int</code></pre>
477 <pre><code class="haskell fragment">add a b = a + b</code></pre>
478 <pre><code class="haskell fragment">add = \a b -> a + b</code></pre>
481 <p>Любая функция берет строго один аргумент.</p>
483 <p>Функция нескольких аргументов все равно берет строго одтн аргумент и возвращает функцию, которая берет
489 (И из-за того, что применение функции лево-ассоциативно, вызов таких не трубует особого
496 <pre><code class="haskell fragment">add :: Int -> Int -> Int
497add a b = a + b</code></pre>
499 <pre><code class="haskell fragment">add8 :: Int -> Int</code></pre>
500 <pre><code class="haskell fragment">add :: Int -> (Int -> Int)</code></pre>
501 <pre><code class="haskell fragment">add8 = add 8</code></pre>
502 <pre><code class="haskell fragment">add8 3
508 <p class="fragment" data-markdown>Оператор (например `+`) -- функция, название которой не содержит буквы и
510 <pre><code class="haskell fragment">x +&+ y = x + y</code></pre>
511 <pre><code class="haskell fragment">8 +&+ 9
516 <h3>Funny fact 2</h3>
518 <p class="fragment" data-markdown>Оператор можно превратить в функцию, окружив его скобками.</p>
519 <pre><code class="haskell fragment">add :: Int -> Int -> Int
520add x y = x + y</code></pre>
521 <pre><code class="haskell fragment">add = (+&+)</code></pre>
522 <pre><code class="haskell fragment">add = (+)</code></pre>
526 <h3>Funny fact 3</h3>
528 <p class="fragment" data-markdown>Функцию можно превратить в оператор, окружив ее обратными кавычками.</p>
529 <pre><code class="haskell fragment">add :: Int -> Int -> Int
530add x y = x + y</code></pre>
531 <pre><code class="haskell fragment">add 8 9
533 <pre><code class="haskell fragment">8 `add` 9
543 <h3>Односвязный список</h3>
544 <pre><code class="haskell fragment">data IntList = Cons Int IntList | Nil</code></pre>
545 <pre><code class="haskell fragment">nums :: IntList
546nums = 1 `Cons` (2 `Cons` (3 `Cons` Nil))</code></pre>
547 <pre><code class="haskell fragment">sum :: IntList -> Int</code></pre>
548 <pre><code class="haskell fragment">sum (Cons x xs) = x + sum xs</code></pre>
549 <pre><code class="haskell fragment">sum Nil = 0
550sum (Cons x xs) = x + sum xs</code></pre>
551 <pre><code class="haskell fragment">sum nums
556 <pre><code class="haskell">take :: Int -> IntList -> IntList</code></pre>
557 <pre><code class="haskell fragment">take _ Nil = Nil
559take n (Cons x xs) = Cons x (take (n - 1) xs)</code></pre>
560 <pre><code class="haskell fragment">nums :: IntList
561nums = 1 `Cons` (2 `Cons` (3 `Cons` Nil))</code></pre>
562 <pre><code class="haskell fragment">take 2 nums
563-- Cons 1 (Cons 2 Nil)
565-- Cons 1 (Cons 2 (Cons 3 Nil))
571 <pre><code class="haskell">repeat :: Int -> IntList</code></pre>
572 <pre><code class="haskell fragment">repeat n = n : (repeat n)</code></pre>
573 <pre><code class="haskell fragment">repeat 8
574-- Cons 8 (Cons 8 (Cons 8 (Cons 8 (Cons 8 (Cons 8 (Cons 8 (Cons 8 (Cons 8 (Cons 8 (...</code></pre>
575 <pre><code class="haskell fragment">(take 3 . repeat) 8
576-- Cons 8 (Cons 8 (Cons 8 Nil))</code></pre>
577 <pre><code class="haskell fragment">(sum . take 3 . repeat) 8
583 <td>Наша самодеятельность</td>
584 <td>В стандартной библиотеке</td>
586 <tr class="fragment">
588 <pre><code class="haskell">IntList</code></pre>
591 <pre><code class="haskell">[Int]</code></pre>
594 <tr class="fragment">
596 <pre><code class="haskell">Nil</code></pre>
599 <pre><code class="haskell">[]</code></pre>
602 <tr class="fragment">
604 <pre><code class="haskell">Cons</code></pre>
607 <pre><code class="haskell">:</code></pre>
610 <tr class="fragment">
612 <pre><code class="haskell">Cons 3 (Cons 4 Nil)</code></pre>
615 <pre class="fragment"><code class="haskell">3 : 4 : []</code></pre>
616 <pre class="fragment"><code class="haskell">[3, 4]</code></pre>
622 <p data-markdown>`repeat`, `sum` и `take` тоже есть в стандартной библиотеке.</p>
630 <pre><code class="haskell">quicksort :: [Int] -> [Int]</code></pre>
632 <pre><code class="haskell fragment">quicksort (x:xs) =
633 quicksort smaller ++ [x] ++ quicksort larger
635 smaller = filter (< x) xs
636 larger = filter (>= x) xs</code></pre>
639 <pre><code class="haskell">filter :: (Bool -> Int) -> [Int] -> [Int]</code></pre>
640 <pre><code class="haskell fragment">filter f (x:xs) =
643 else x:(filter f xs)</code></pre>
644 <pre><code class="haskell fragment">filter _ [] = []
648 else x:(filter f xs)</code></pre>
651 <pre><code class="haskell">quicksort :: [Int] -> [Int]
653 quicksort smaller ++ [x] ++ quicksort larger
655 smaller = filter (< x) xs
656 larger = filter (>= x) xs
661 else x:(filter f xs)</code></pre>
664 <pre><code class="haskell">quicksort :: [Int] -> [Int]
667 quicksort smaller ++ [x] ++ quicksort larger
669 smaller = filter (< x) xs
670 larger = filter (>= x) xs
675 else x:(filter f xs)</code></pre>
676 <pre><code class="haskell fragment">quicksort [2, 1, 3, 4]
677-- [1, 2, 3, 4]</code></pre>
680 <p data-markdown>`filter` тоже есть в стандартной библиотеке.</p>
685 <h2>Где и как смотреть "стандартную библиотеку"</h2>
690 <a href="https://hackage.haskell.org/package/base">Hackage</a>
693 (Там вам нужен только пакет `base`. Ссылка ведет прямо на него.)
695 Еще если там нажать `s`, то будет поиск.
698 <li class="fragment">
699 <a href="https://hoogle.haskell.org">Hoogle</a>
704 Например: `Int -> [Int] -> [Int]`
706 (Тут вам опять же нужен только пакет `base`. Нужно чтобы справа было "package:base".)
716 <script src="./js/reveal.js"></script>
719 // More info about config & dependencies:
720 // - https://github.com/hakimel/reveal.js#configuration
721 // - https://github.com/hakimel/reveal.js#dependencies
724 // Displaнес presentation control arrows
727 // Help the user learn the controls by providing hints, for example by
728 // bouncing the down arrow when they first encounter a vertical slide
729 controlsTutorial: true,
731 // Determines where controls appear, "edges" or "bottom-right"
732 controlsLayout: 'bottom-right',
734 // Visibility rule for backwards navigation arrows; "faded", "hidden"
736 controlsBackArrows: 'faded',
738 // Display a presentation progress bar
741 // Display the page number of the current slide
744 // Add the current slide number to the URL hash so that reloading the
745 // page/copying the URL will return you to the same slide
748 // Push each slide change to the browser history. Implies `hash: true`
751 // Enable keyboard shortcuts for navigation
754 // Enable the slide overview mode
757 // Vertical centering of slides
760 // Enables touch navigation on devices with touch input
763 // Loop the presentation
766 // Change the presentation direction to be RTL
769 // See https://github.com/hakimel/reveal.js/#navigation-mode
770 navigationMode: 'linear',
772 // Randomizes the order of slides each time the presentation loads
775 // Turns fragments on and off globally
778 // Flags whether to include the current fragment in the URL,
779 // so that reloading brings you to the same fragment position
782 // Flags if the presentation is running in an embedded mode,
783 // i.e. contained within a limited portion of the screen
786 // Flags if we should show a help overlay when the questionmark
790 // Flags if speaker notes should be visible to all viewers
793 // Global override for autoplaying embedded media (video/audio/iframe)
794 // - null: Media will only autoplay if data-autoplay is present
795 // - true: All media will autoplay, regardless of individual setting
796 // - false: No media will autoplay, regardless of individual setting
799 // Global override for preloading lazy-loaded iframes
800 // - null: Iframes with data-src AND data-preload will be loaded when within
801 // the viewDistance, iframes with only data-src will be loaded when visible
802 // - true: All iframes with data-src will be loaded when within the viewDistance
803 // - false: All iframes with data-src will be loaded only when visible
804 preloadIframes: null,
806 // Number of milliseconds between automatically proceeding to the
807 // next slide, disabled when set to 0, this value can be overwritten
808 // by using a data-autoslide attribute on your slides
811 // Stop auto-sliding after user input
812 autoSlideStoppable: true,
814 // Use this method for navigation when auto-sliding
815 autoSlideMethod: Reveal.navigateNext,
817 // Specify the average time in seconds that you think you will spend
818 // presenting each slide. This is used to show a pacing timer in the
822 // Enable slide navigation via mouse wheel
825 // Hide cursor if inactive
826 hideInactiveCursor: true,
828 // Time before the cursor is hidden (in ms)
829 hideCursorTime: 5000,
831 // Hides the address bar on mobile devices
832 hideAddressBar: true,
834 // Opens links in an iframe preview overlay
835 // Add `data-preview-link` and `data-preview-link="false"` to customise each link
840 transition: 'slide', // none/fade/slide/convex/concave/zoom
843 transitionSpeed: 'default', // default/fast/slow
845 // Transition style for full page slide backgrounds
846 backgroundTransition: 'fade', // none/fade/slide/convex/concave/zoom
848 // Number of slides away from the current that are visible
851 // Parallax background image
852 parallaxBackgroundImage: '', // e.g. "'https://s3.amazonaws.com/hakim-static/reveal-js/reveal-parallax-1.jpg'"
854 // Parallax background size
855 parallaxBackgroundSize: '', // CSS syntax, e.g. "2100px 900px"
857 // Number of pixels to move the parallax background per slide
858 // - Calculated automatically unless specified
859 // - Set to 0 to disable movement along an axis
860 parallaxBackgroundHorizontal: null,
861 parallaxBackgroundVertical: null,
863 // The display mode that will be used to show slides
866 pdfSeparateFragments: false,
876 { src: './plugin/markdown/marked.js' },
877 { src: './plugin/markdown/markdown.js' },
878 { src: './plugin/zoom-js/zoom.js', async: true },
879 { src: './plugin/notes/notes.js', async: true },
880 { src: './plugin/highlight/highlight.js', async: true }
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