git.iko.soy/ikoHSE/sc-lectures
on master help sign in
Added lecture 3
commit2f6edad65028999e4910d512a8c940780f9c237a authoriko <ilyakooo0@gmail.com> dateWed 1 Apr 2020, 23:35 (7 years ago) parent73c1beb
10 files changed+1656−167
1.html+30−30 2.html+61−55 2.md+23−18 3.html+526−54 3.md+775−1 README.md+11−4 build.sh+1−1 highlight.theme+225 reveal.js/css/theme/source/superblack.scss+2−2 reveal.js/css/theme/superblack.css+2−2
1.html+30−30
@@ -47,41 +47,41 @@
4747 }
4848 pre.numberSource { margin-left: 3em; border-left: 1px solid #7a7c7d; padding-left: 4px; }
4949 div.sourceCode
50− { color: #cfcfc2; background-color: #232629; }
50+ { color: #ffffff; background-color: #000000; }
5151 @media screen {
5252 pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
5353 }
54− code span. { color: #cfcfc2; } /* Normal */
54+ code span. { color: #ffffff; } /* Normal */
5555 code span.al { color: #95da4c; background-color: #4d1f24; font-weight: bold; } /* Alert */
56− code span.an { color: #3f8058; } /* Annotation */
57− code span.at { color: #2980b9; } /* Attribute */
58− code span.bn { color: #f67400; } /* BaseN */
59− code span.bu { color: #7f8c8d; } /* BuiltIn */
60− code span.cf { color: #fdbc4b; font-weight: bold; } /* ControlFlow */
61− code span.ch { color: #3daee9; } /* Char */
62− code span.cn { color: #27aeae; font-weight: bold; } /* Constant */
63− code span.co { color: #7a7c7d; } /* Comment */
64− code span.cv { color: #7f8c8d; } /* CommentVar */
56+ code span.an { color: #86d5a4; } /* Annotation */
57+ code span.at { color: #94cbf0; } /* Attribute */
58+ code span.bn { color: #ffb06a; } /* BaseN */
59+ code span.bu { color: #bdd1d3; } /* BuiltIn */
60+ code span.cf { color: #ffd998; font-weight: bold; } /* ControlFlow */
61+ code span.ch { color: #a4e0ff; } /* Char */
62+ code span.cn { color: #73d9d9; font-weight: bold; } /* Constant */
63+ code span.co { color: #a1a6a8; } /* Comment */
64+ code span.cv { color: #b6c8c9; } /* CommentVar */
6565 code span.do { color: #a43340; } /* Documentation */
66− code span.dt { color: #2980b9; } /* DataType */
67− code span.dv { color: #f67400; } /* DecVal */
68− code span.er { color: #da4453; text-decoration: underline; } /* Error */
69− code span.ex { color: #0099ff; font-weight: bold; } /* Extension */
70− code span.fl { color: #f67400; } /* Float */
71− code span.fu { color: #8e44ad; } /* Function */
72− code span.im { color: #27ae60; } /* Import */
73− code span.in { color: #c45b00; } /* Information */
74− code span.kw { color: #cfcfc2; font-weight: bold; } /* Keyword */
75− code span.op { color: #cfcfc2; } /* Operator */
76− code span.ot { color: #27ae60; } /* Other */
77− code span.pp { color: #27ae60; } /* Preprocessor */
78− code span.re { color: #2980b9; background-color: #153042; } /* RegionMarker */
79− code span.sc { color: #3daee9; } /* SpecialChar */
80− code span.ss { color: #da4453; } /* SpecialString */
81− code span.st { color: #f44f4f; } /* String */
82− code span.va { color: #27aeae; } /* Variable */
83− code span.vs { color: #da4453; } /* VerbatimString */
84− code span.wa { color: #da4453; } /* Warning */
66+ code span.dt { color: #7cc0ec; } /* DataType */
67+ code span.dv { color: #f6b77f; } /* DecVal */
68+ code span.er { color: #e9848e; text-decoration: underline; } /* Error */
69+ code span.ex { color: #96d5ff; font-weight: bold; } /* Extension */
70+ code span.fl { color: #fdae67; } /* Float */
71+ code span.fu { color: #d487f4; } /* Function */
72+ code span.im { color: #76e8a6; } /* Import */
73+ code span.in { color: #f6b176; } /* Information */
74+ code span.kw { color: #ebebc9; font-weight: bold; } /* Keyword */
75+ code span.op { color: #ececde; } /* Operator */
76+ code span.ot { color: #86e9b0; } /* Other */
77+ code span.pp { color: #62e298; } /* Preprocessor */
78+ code span.re { color: #83c7f4; background-color: #153042; } /* RegionMarker */
79+ code span.sc { color: #80ccf4; } /* SpecialChar */
80+ code span.ss { color: #ff909b; } /* SpecialString */
81+ code span.st { color: #ff9f9f; } /* String */
82+ code span.va { color: #56d4d4; } /* Variable */
83+ code span.vs { color: #eca2a9; } /* VerbatimString */
84+ code span.wa { color: #eca2a9; } /* Warning */
8585 </style>
8686 <link rel="stylesheet" href="reveal.js/css/theme/superblack.css" id="theme">
8787 <!-- Printing and PDF exports -->
2.html+61−55
@@ -47,41 +47,41 @@
4747 }
4848 pre.numberSource { margin-left: 3em; border-left: 1px solid #7a7c7d; padding-left: 4px; }
4949 div.sourceCode
50− { color: #cfcfc2; background-color: #232629; }
50+ { color: #ffffff; background-color: #000000; }
5151 @media screen {
5252 pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
5353 }
54− code span. { color: #cfcfc2; } /* Normal */
54+ code span. { color: #ffffff; } /* Normal */
5555 code span.al { color: #95da4c; background-color: #4d1f24; font-weight: bold; } /* Alert */
56− code span.an { color: #3f8058; } /* Annotation */
57− code span.at { color: #2980b9; } /* Attribute */
58− code span.bn { color: #f67400; } /* BaseN */
59− code span.bu { color: #7f8c8d; } /* BuiltIn */
60− code span.cf { color: #fdbc4b; font-weight: bold; } /* ControlFlow */
61− code span.ch { color: #3daee9; } /* Char */
62− code span.cn { color: #27aeae; font-weight: bold; } /* Constant */
63− code span.co { color: #7a7c7d; } /* Comment */
64− code span.cv { color: #7f8c8d; } /* CommentVar */
56+ code span.an { color: #86d5a4; } /* Annotation */
57+ code span.at { color: #94cbf0; } /* Attribute */
58+ code span.bn { color: #ffb06a; } /* BaseN */
59+ code span.bu { color: #bdd1d3; } /* BuiltIn */
60+ code span.cf { color: #ffd998; font-weight: bold; } /* ControlFlow */
61+ code span.ch { color: #a4e0ff; } /* Char */
62+ code span.cn { color: #73d9d9; font-weight: bold; } /* Constant */
63+ code span.co { color: #a1a6a8; } /* Comment */
64+ code span.cv { color: #b6c8c9; } /* CommentVar */
6565 code span.do { color: #a43340; } /* Documentation */
66− code span.dt { color: #2980b9; } /* DataType */
67− code span.dv { color: #f67400; } /* DecVal */
68− code span.er { color: #da4453; text-decoration: underline; } /* Error */
69− code span.ex { color: #0099ff; font-weight: bold; } /* Extension */
70− code span.fl { color: #f67400; } /* Float */
71− code span.fu { color: #8e44ad; } /* Function */
72− code span.im { color: #27ae60; } /* Import */
73− code span.in { color: #c45b00; } /* Information */
74− code span.kw { color: #cfcfc2; font-weight: bold; } /* Keyword */
75− code span.op { color: #cfcfc2; } /* Operator */
76− code span.ot { color: #27ae60; } /* Other */
77− code span.pp { color: #27ae60; } /* Preprocessor */
78− code span.re { color: #2980b9; background-color: #153042; } /* RegionMarker */
79− code span.sc { color: #3daee9; } /* SpecialChar */
80− code span.ss { color: #da4453; } /* SpecialString */
81− code span.st { color: #f44f4f; } /* String */
82− code span.va { color: #27aeae; } /* Variable */
83− code span.vs { color: #da4453; } /* VerbatimString */
84− code span.wa { color: #da4453; } /* Warning */
66+ code span.dt { color: #7cc0ec; } /* DataType */
67+ code span.dv { color: #f6b77f; } /* DecVal */
68+ code span.er { color: #e9848e; text-decoration: underline; } /* Error */
69+ code span.ex { color: #96d5ff; font-weight: bold; } /* Extension */
70+ code span.fl { color: #fdae67; } /* Float */
71+ code span.fu { color: #d487f4; } /* Function */
72+ code span.im { color: #76e8a6; } /* Import */
73+ code span.in { color: #f6b176; } /* Information */
74+ code span.kw { color: #ebebc9; font-weight: bold; } /* Keyword */
75+ code span.op { color: #ececde; } /* Operator */
76+ code span.ot { color: #86e9b0; } /* Other */
77+ code span.pp { color: #62e298; } /* Preprocessor */
78+ code span.re { color: #83c7f4; background-color: #153042; } /* RegionMarker */
79+ code span.sc { color: #80ccf4; } /* SpecialChar */
80+ code span.ss { color: #ff909b; } /* SpecialString */
81+ code span.st { color: #ff9f9f; } /* String */
82+ code span.va { color: #56d4d4; } /* Variable */
83+ code span.vs { color: #eca2a9; } /* VerbatimString */
84+ code span.wa { color: #eca2a9; } /* Warning */
8585 </style>
8686 <link rel="stylesheet" href="reveal.js/css/theme/superblack.css" id="theme">
8787 <!-- Printing and PDF exports -->
@@ -450,14 +450,14 @@
450450<div class="sourceCode" id="cb75"><pre class="sourceCode java fragment"><code class="sourceCode java"><span id="cb75-1"><a href="#cb75-1"></a>m.<span class="fu">get</span>(<span class="st">&quot;five&quot;</span>);</span>
451451<span id="cb75-2"><a href="#cb75-2"></a><span class="co">// null</span></span></code></pre></div>
452452<div class="sourceCode" id="cb76"><pre class="sourceCode java fragment"><code class="sourceCode java"><span id="cb76-1"><a href="#cb76-1"></a><span class="kw">class</span> <span class="bu">TreeMap</span>&lt;K,V&gt; {</span>
453−<span id="cb76-2"><a href="#cb76-2"></a> V <span class="fu">get</span>(<span class="bu">Object</span> key) {</span>
453+<span id="cb76-2"><a href="#cb76-2"></a> V <span class="fu">get</span>(K key) {</span>
454454<span id="cb76-3"><a href="#cb76-3"></a> ...</span></code></pre></div>
455455<p><span class="fragment">Неявный контекст ошибки ВЕЗДЕ.</span></p>
456456</section>
457457<section class="slide level1">
458458
459459<div class="sourceCode" id="cb77"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb77-1"><a href="#cb77-1"></a><span class="kw">class</span> <span class="bu">TreeMap</span>&lt;K,V&gt; {</span>
460−<span id="cb77-2"><a href="#cb77-2"></a> Pair&lt;V, <span class="bu">Boolean</span>&gt; <span class="fu">get</span>(<span class="bu">Object</span> key) {</span>
460+<span id="cb77-2"><a href="#cb77-2"></a> Pair&lt;V, <span class="bu">Boolean</span>&gt; <span class="fu">get</span>(K key) {</span>
461461<span id="cb77-3"><a href="#cb77-3"></a> ...</span></code></pre></div>
462462<div class="sourceCode" id="cb78"><pre class="sourceCode java fragment"><code class="sourceCode java"><span id="cb78-1"><a href="#cb78-1"></a>Pair&lt;<span class="bu">Integer</span>, <span class="bu">Boolean</span>&gt; result = m.<span class="fu">get</span>(<span class="st">&quot;one&quot;</span>);</span>
463463<span id="cb78-2"><a href="#cb78-2"></a></span>
@@ -479,7 +479,7 @@
479479<section class="slide level1">
480480
481481<div class="sourceCode" id="cb80"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb80-1"><a href="#cb80-1"></a><span class="kw">class</span> <span class="bu">TreeMap</span>&lt;K,V&gt; {</span>
482−<span id="cb80-2"><a href="#cb80-2"></a> V <span class="fu">get</span>(<span class="bu">Object</span> key) <span class="kw">throws</span> NoElementException {</span>
482+<span id="cb80-2"><a href="#cb80-2"></a> V <span class="fu">get</span>(K key) <span class="kw">throws</span> NoElementException {</span>
483483<span id="cb80-3"><a href="#cb80-3"></a> ...</span></code></pre></div>
484484<div class="sourceCode" id="cb81"><pre class="sourceCode java fragment"><code class="sourceCode java"><span id="cb81-1"><a href="#cb81-1"></a><span class="kw">try</span> {</span>
485485<span id="cb81-2"><a href="#cb81-2"></a> <span class="fu">print</span>(m.<span class="fu">get</span>(<span class="st">&quot;five&quot;</span>));</span>
@@ -493,7 +493,7 @@
493493<div class="sourceCode" id="cb82"><pre class="sourceCode java"><code class="sourceCode java"><span id="cb82-1"><a href="#cb82-1"></a><span class="kw">class</span> Optional&lt;T&gt; {</span>
494494<span id="cb82-2"><a href="#cb82-2"></a> ...</span></code></pre></div>
495495<div class="sourceCode" id="cb83"><pre class="sourceCode java fragment"><code class="sourceCode java"><span id="cb83-1"><a href="#cb83-1"></a><span class="kw">class</span> <span class="bu">TreeMap</span>&lt;K,V&gt; {</span>
496−<span id="cb83-2"><a href="#cb83-2"></a> Optional&lt;V&gt; <span class="fu">get</span>(<span class="bu">Object</span> key) {</span>
496+<span id="cb83-2"><a href="#cb83-2"></a> Optional&lt;V&gt; <span class="fu">get</span>(K key) {</span>
497497<span id="cb83-3"><a href="#cb83-3"></a> ...</span></code></pre></div>
498498</section>
499499<section class="slide level1">
@@ -583,20 +583,26 @@
583583<div class="sourceCode" id="cb108"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb108-1"><a href="#cb108-1"></a><span class="kw">class</span> <span class="dt">Functor</span> f <span class="kw">where</span></span>
584584<span id="cb108-2"><a href="#cb108-2"></a><span class="ot"> fmap ::</span> (a <span class="ot">-&gt;</span> b) <span class="ot">-&gt;</span> f a <span class="ot">-&gt;</span> f b</span></code></pre></div>
585585<div class="sourceCode" id="cb109"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb109-1"><a href="#cb109-1"></a><span class="kw">class</span> <span class="dt">Functor</span> [] <span class="kw">where</span></span>
586−<span id="cb109-2"><a href="#cb109-2"></a> <span class="fu">fmap</span> _ [] <span class="ot">=</span> []</span>
587−<span id="cb109-3"><a href="#cb109-3"></a> <span class="fu">fmap</span> f (x <span class="op">:</span> xs) <span class="ot">=</span> f x <span class="op">:</span> <span class="fu">fmap</span> f xs</span></code></pre></div>
588−<div class="sourceCode" id="cb110"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb110-1"><a href="#cb110-1"></a><span class="kw">class</span> <span class="dt">Functor</span> [] <span class="kw">where</span></span>
589−<span id="cb110-2"><a href="#cb110-2"></a><span class="ot"> fmap ::</span> (a <span class="ot">-&gt;</span> b) <span class="ot">-&gt;</span> [a] <span class="ot">-&gt;</span> [b]</span>
590−<span id="cb110-3"><a href="#cb110-3"></a> <span class="fu">fmap</span> _ [] <span class="ot">=</span> []</span>
591−<span id="cb110-4"><a href="#cb110-4"></a> <span class="fu">fmap</span> f (x <span class="op">:</span> xs) <span class="ot">=</span> f x <span class="op">:</span> <span class="fu">fmap</span> f xs</span></code></pre></div>
592−<div class="sourceCode" id="cb111"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb111-1"><a href="#cb111-1"></a><span class="kw">class</span> <span class="dt">Functor</span> <span class="dt">Maybe</span> <span class="kw">where</span></span>
593−<span id="cb111-2"><a href="#cb111-2"></a><span class="ot"> fmap ::</span> (a <span class="ot">-&gt;</span> b) <span class="ot">-&gt;</span> <span class="dt">Maybe</span> a <span class="ot">-&gt;</span> <span class="dt">Maybe</span> b</span>
594−<span id="cb111-3"><a href="#cb111-3"></a> <span class="fu">fmap</span> _ <span class="dt">Nothing</span> <span class="ot">=</span> <span class="dt">Nothing</span></span>
595−<span id="cb111-4"><a href="#cb111-4"></a> <span class="fu">fmap</span> f (<span class="dt">Just</span> x) <span class="ot">=</span> <span class="dt">Just</span> (f x)</span></code></pre></div>
596−<div class="sourceCode" id="cb112"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb112-1"><a href="#cb112-1"></a><span class="kw">class</span> <span class="dt">Functor</span> (<span class="dt">Either</span> e) <span class="kw">where</span></span>
597−<span id="cb112-2"><a href="#cb112-2"></a><span class="ot"> fmap ::</span> (a <span class="ot">-&gt;</span> b) <span class="ot">-&gt;</span> <span class="dt">Either</span> e a <span class="ot">-&gt;</span> <span class="dt">Either</span> e b</span>
598−<span id="cb112-3"><a href="#cb112-3"></a> <span class="fu">fmap</span> _ (<span class="dt">Left</span> e) <span class="ot">=</span> <span class="dt">Left</span> e</span>
599−<span id="cb112-4"><a href="#cb112-4"></a> <span class="fu">fmap</span> f (<span class="dt">Just</span> x) <span class="ot">=</span> <span class="dt">Just</span> (f x)</span></code></pre></div>
586+<span id="cb109-2"><a href="#cb109-2"></a><span class="ot"> fmap ::</span> (a <span class="ot">-&gt;</span> b) <span class="ot">-&gt;</span> [a] <span class="ot">-&gt;</span> [b]</span>
587+<span id="cb109-3"><a href="#cb109-3"></a> <span class="fu">fmap</span> _ [] <span class="ot">=</span> []</span>
588+<span id="cb109-4"><a href="#cb109-4"></a> <span class="fu">fmap</span> f (x <span class="op">:</span> xs) <span class="ot">=</span> f x <span class="op">:</span> <span class="fu">fmap</span> f xs</span></code></pre></div>
589+<div class="sourceCode" id="cb110"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb110-1"><a href="#cb110-1"></a><span class="kw">class</span> <span class="dt">Functor</span> <span class="dt">Maybe</span> <span class="kw">where</span></span>
590+<span id="cb110-2"><a href="#cb110-2"></a><span class="ot"> fmap ::</span> (a <span class="ot">-&gt;</span> b) <span class="ot">-&gt;</span> <span class="dt">Maybe</span> a <span class="ot">-&gt;</span> <span class="dt">Maybe</span> b</span>
591+<span id="cb110-3"><a href="#cb110-3"></a> <span class="fu">fmap</span> _ <span class="dt">Nothing</span> <span class="ot">=</span> <span class="dt">Nothing</span></span>
592+<span id="cb110-4"><a href="#cb110-4"></a> <span class="fu">fmap</span> f (<span class="dt">Just</span> x) <span class="ot">=</span> <span class="dt">Just</span> (f x)</span></code></pre></div>
593+<div class="sourceCode" id="cb111"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb111-1"><a href="#cb111-1"></a><span class="kw">class</span> <span class="dt">Functor</span> (<span class="dt">Either</span> e) <span class="kw">where</span></span>
594+<span id="cb111-2"><a href="#cb111-2"></a><span class="ot"> fmap ::</span> (a <span class="ot">-&gt;</span> b) <span class="ot">-&gt;</span> <span class="dt">Either</span> e a <span class="ot">-&gt;</span> <span class="dt">Either</span> e b</span>
595+<span id="cb111-3"><a href="#cb111-3"></a> <span class="fu">fmap</span> _ (<span class="dt">Left</span> e) <span class="ot">=</span> <span class="dt">Left</span> e</span>
596+<span id="cb111-4"><a href="#cb111-4"></a> <span class="fu">fmap</span> f (<span class="dt">Right</span> x) <span class="ot">=</span> <span class="dt">Right</span> (f x)</span></code></pre></div>
597+</section>
598+<section class="slide level1">
599+
600+<div class="sourceCode" id="cb112"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb112-1"><a href="#cb112-1"></a><span class="ot">updateAccount ::</span> <span class="dt">Account</span> <span class="ot">-&gt;</span> <span class="dt">Card</span> <span class="ot">-&gt;</span> <span class="dt">Account</span></span>
601+<span id="cb112-2"><a href="#cb112-2"></a><span class="ot">makePayment ::</span> <span class="dt">Card</span> <span class="ot">-&gt;</span> <span class="dt">Amount</span> <span class="ot">-&gt;</span> <span class="dt">Either</span> <span class="dt">PaymentError</span> <span class="dt">Card</span></span>
602+<span id="cb112-3"><a href="#cb112-3"></a></span>
603+<span id="cb112-4"><a href="#cb112-4"></a><span class="ot">newAcccount ::</span> <span class="dt">Either</span> <span class="dt">PaymentError</span> <span class="dt">Account</span></span>
604+<span id="cb112-5"><a href="#cb112-5"></a>newAcccount <span class="ot">=</span></span>
605+<span id="cb112-6"><a href="#cb112-6"></a> <span class="fu">fmap</span> (updateAccount account) (makePayment card (<span class="dt">RUB</span> <span class="dv">150</span>))</span></code></pre></div>
600606</section>
601607<section class="slide level1">
602608
@@ -604,7 +610,7 @@
604610<span id="cb113-2"><a href="#cb113-2"></a><span class="ot"> fmap ::</span> (a <span class="ot">-&gt;</span> b) <span class="ot">-&gt;</span> f a <span class="ot">-&gt;</span> f b</span></code></pre></div>
605611<div class="sourceCode" id="cb114"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb114-1"><a href="#cb114-1"></a><span class="kw">class</span> <span class="dt">Functor</span> (x <span class="ot">-&gt;</span>) <span class="kw">where</span></span>
606612<span id="cb114-2"><a href="#cb114-2"></a><span class="ot"> fmap ::</span> (a <span class="ot">-&gt;</span> b) <span class="ot">-&gt;</span> (x <span class="ot">-&gt;</span> a) <span class="ot">-&gt;</span> (x <span class="ot">-&gt;</span> b)</span>
607−<span id="cb114-3"><a href="#cb114-3"></a> <span class="fu">fmap</span> (<span class="ot">f ::</span> a <span class="ot">-&gt;</span> b) (<span class="ot">g ::</span> x <span class="ot">-&gt;</span> a) <span class="ot">=</span> \x <span class="ot">-&gt;</span> f (g x)</span></code></pre></div>
613+<span id="cb114-3"><a href="#cb114-3"></a> <span class="fu">fmap</span> (<span class="ot">f ::</span> a <span class="ot">-&gt;</span> b) (<span class="ot">g ::</span> x <span class="ot">-&gt;</span> a) <span class="ot">=</span> \(<span class="ot">u ::</span> x) <span class="ot">-&gt;</span> f (g u)</span></code></pre></div>
608614<div class="sourceCode" id="cb115"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb115-1"><a href="#cb115-1"></a> <span class="fu">fmap</span> (<span class="ot">f ::</span> a <span class="ot">-&gt;</span> b) (<span class="ot">g ::</span> x <span class="ot">-&gt;</span> a) <span class="ot">=</span> f <span class="op">.</span> g</span></code></pre></div>
609615<div class="sourceCode" id="cb116"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb116-1"><a href="#cb116-1"></a> <span class="fu">fmap</span> <span class="ot">=</span> (<span class="op">.</span>)</span></code></pre></div>
610616</section>
@@ -612,10 +618,10 @@
612618
613619<h2 id="functor-monoid">Functor + Monoid</h2>
614620<h2 id="alternative"><span class="fragment">= Alternative!</span></h2>
615−<div class="sourceCode" id="cb117"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb117-1"><a href="#cb117-1"></a><span class="ot">foo ::</span> f a <span class="ot">-&gt;</span> f a <span class="ot">-&gt;</span> f a</span></code></pre></div>
616−<div class="sourceCode" id="cb118"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb118-1"><a href="#cb118-1"></a><span class="kw">class</span> <span class="dt">Monoid</span> s <span class="kw">where</span></span>
617−<span id="cb118-2"><a href="#cb118-2"></a><span class="ot"> (&lt;&gt;) ::</span> s <span class="ot">-&gt;</span> s <span class="ot">-&gt;</span> s</span>
618−<span id="cb118-3"><a href="#cb118-3"></a><span class="ot"> mempty ::</span> s</span></code></pre></div>
621+<div class="sourceCode" id="cb117"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb117-1"><a href="#cb117-1"></a><span class="kw">class</span> <span class="dt">Monoid</span> s <span class="kw">where</span></span>
622+<span id="cb117-2"><a href="#cb117-2"></a><span class="ot"> (&lt;&gt;) ::</span> s <span class="ot">-&gt;</span> s <span class="ot">-&gt;</span> s</span>
623+<span id="cb117-3"><a href="#cb117-3"></a><span class="ot"> mempty ::</span> s</span></code></pre></div>
624+<div class="sourceCode" id="cb118"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb118-1"><a href="#cb118-1"></a><span class="ot">foo ::</span> f a <span class="ot">-&gt;</span> f a <span class="ot">-&gt;</span> f a</span></code></pre></div>
619625<div class="sourceCode" id="cb119"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb119-1"><a href="#cb119-1"></a><span class="kw">class</span> <span class="dt">Functor</span> f <span class="ot">=&gt;</span> <span class="dt">Alternative</span> f <span class="kw">where</span></span>
620626<span id="cb119-2"><a href="#cb119-2"></a><span class="ot"> (&lt;|&gt;) ::</span> f a <span class="ot">-&gt;</span> f a <span class="ot">-&gt;</span> f a</span>
621627<span id="cb119-3"><a href="#cb119-3"></a><span class="ot"> empty ::</span> f a</span></code></pre></div>
@@ -627,13 +633,13 @@
627633<span id="cb120-3"><a href="#cb120-3"></a><span class="ot"> empty ::</span> f a</span></code></pre></div>
628634<div class="sourceCode" id="cb121"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb121-1"><a href="#cb121-1"></a><span class="kw">instance</span> <span class="dt">Alternative</span> <span class="dt">Maybe</span> <span class="kw">where</span></span>
629635<span id="cb121-2"><a href="#cb121-2"></a> (<span class="dt">Just</span> x) <span class="op">&lt;|&gt;</span> _ <span class="ot">=</span> <span class="dt">Just</span> x</span>
630−<span id="cb121-3"><a href="#cb121-3"></a> _ <span class="op">&lt;|&gt;</span> y <span class="ot">=</span> y</span>
636+<span id="cb121-3"><a href="#cb121-3"></a> <span class="dt">Nothing</span> <span class="op">&lt;|&gt;</span> y <span class="ot">=</span> y</span>
631637<span id="cb121-4"><a href="#cb121-4"></a></span>
632638<span id="cb121-5"><a href="#cb121-5"></a> empty <span class="ot">=</span> <span class="dt">Nothing</span></span></code></pre></div>
633639<div class="sourceCode" id="cb122"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb122-1"><a href="#cb122-1"></a><span class="dt">Just</span> <span class="dv">42</span> <span class="op">&lt;|&gt;</span> <span class="dt">Just</span> <span class="dv">69</span></span>
634640<span id="cb122-2"><a href="#cb122-2"></a><span class="co">-- Just 42</span></span></code></pre></div>
635641<div class="sourceCode" id="cb123"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb123-1"><a href="#cb123-1"></a><span class="dt">Nothing</span> <span class="op">&lt;|&gt;</span> <span class="dt">Just</span> <span class="dv">69</span></span>
636−<span id="cb123-2"><a href="#cb123-2"></a><span class="co">-- Nothing</span></span></code></pre></div>
642+<span id="cb123-2"><a href="#cb123-2"></a><span class="co">-- Just 69</span></span></code></pre></div>
637643</section>
638644<section class="slide level1">
639645
2.md+23−18
@@ -572,7 +572,7 @@ m.get("five");
572572
573573```{ .java .fragment }
574574class TreeMap<K,V> {
575− V get(Object key) {
575+ V get(K key) {
576576 ...
577577```
578578
@@ -582,7 +582,7 @@ class TreeMap<K,V> {
582582
583583```{ .java }
584584class TreeMap<K,V> {
585− Pair<V, Boolean> get(Object key) {
585+ Pair<V, Boolean> get(K key) {
586586 ...
587587```
588588
@@ -612,7 +612,7 @@ if (result.second()) {
612612
613613```{ .java }
614614class TreeMap<K,V> {
615− V get(Object key) throws NoElementException {
615+ V get(K key) throws NoElementException {
616616 ...
617617```
618618
@@ -634,7 +634,7 @@ class Optional<T> {
634634
635635```{ .java .fragment }
636636class TreeMap<K,V> {
637− Optional<V> get(Object key) {
637+ Optional<V> get(K key) {
638638 ...
639639```
640640
@@ -798,12 +798,6 @@ class Functor f where
798798 fmap :: (a -> b) -> f a -> f b
799799```
800800
801−```{ .haskell .fragment }
802−class Functor [] where
803− fmap _ [] = []
804− fmap f (x : xs) = f x : fmap f xs
805−```
806−
807801```{ .haskell .fragment }
808802class Functor [] where
809803 fmap :: (a -> b) -> [a] -> [b]
@@ -822,7 +816,18 @@ class Functor Maybe where
822816class Functor (Either e) where
823817 fmap :: (a -> b) -> Either e a -> Either e b
824818 fmap _ (Left e) = Left e
825− fmap f (Just x) = Just (f x)
819+ fmap f (Right x) = Right (f x)
820+```
821+
822+---
823+
824+```{ .haskell }
825+updateAccount :: Account -> Card -> Account
826+makePayment :: Card -> Amount -> Either PaymentError Card
827+
828+newAcccount :: Either PaymentError Account
829+newAcccount =
830+ fmap (updateAccount account) (makePayment card (RUB 150))
826831```
827832
828833---
@@ -835,7 +840,7 @@ class Functor f where
835840```{ .haskell .fragment }
836841class Functor (x ->) where
837842 fmap :: (a -> b) -> (x -> a) -> (x -> b)
838− fmap (f :: a -> b) (g :: x -> a) = \x -> f (g x)
843+ fmap (f :: a -> b) (g :: x -> a) = \(u :: x) -> f (g u)
839844```
840845
841846```{ .haskell .fragment }
@@ -852,16 +857,16 @@ class Functor (x ->) where
852857## [= Alternative!]{.fragment}
853858
854859
855−```{ .haskell .fragment }
856−foo :: f a -> f a -> f a
857−```
858−
859860```{ .haskell .fragment }
860861class Monoid s where
861862 (<>) :: s -> s -> s
862863 mempty :: s
863864```
864865
866+```{ .haskell .fragment }
867+foo :: f a -> f a -> f a
868+```
869+
865870```{ .haskell .fragment }
866871class Functor f => Alternative f where
867872 (<|>) :: f a -> f a -> f a
@@ -879,7 +884,7 @@ class Functor f => Alternative f where
879884```{ .haskell .fragment }
880885instance Alternative Maybe where
881886 (Just x) <|> _ = Just x
882− _ <|> y = y
887+ Nothing <|> y = y
883888
884889 empty = Nothing
885890```
@@ -891,7 +896,7 @@ Just 42 <|> Just 69
891896
892897```{ .haskell .fragment }
893898Nothing <|> Just 69
894−-- Nothing
899+-- Just 69
895900```
896901
897902---
3.html+526−54
@@ -47,41 +47,41 @@
4747 }
4848 pre.numberSource { margin-left: 3em; border-left: 1px solid #7a7c7d; padding-left: 4px; }
4949 div.sourceCode
50− { color: #cfcfc2; background-color: #232629; }
50+ { color: #ffffff; background-color: #000000; }
5151 @media screen {
5252 pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
5353 }
54− code span. { color: #cfcfc2; } /* Normal */
54+ code span. { color: #ffffff; } /* Normal */
5555 code span.al { color: #95da4c; background-color: #4d1f24; font-weight: bold; } /* Alert */
56− code span.an { color: #3f8058; } /* Annotation */
57− code span.at { color: #2980b9; } /* Attribute */
58− code span.bn { color: #f67400; } /* BaseN */
59− code span.bu { color: #7f8c8d; } /* BuiltIn */
60− code span.cf { color: #fdbc4b; font-weight: bold; } /* ControlFlow */
61− code span.ch { color: #3daee9; } /* Char */
62− code span.cn { color: #27aeae; font-weight: bold; } /* Constant */
63− code span.co { color: #7a7c7d; } /* Comment */
64− code span.cv { color: #7f8c8d; } /* CommentVar */
56+ code span.an { color: #86d5a4; } /* Annotation */
57+ code span.at { color: #94cbf0; } /* Attribute */
58+ code span.bn { color: #ffb06a; } /* BaseN */
59+ code span.bu { color: #bdd1d3; } /* BuiltIn */
60+ code span.cf { color: #ffd998; font-weight: bold; } /* ControlFlow */
61+ code span.ch { color: #a4e0ff; } /* Char */
62+ code span.cn { color: #73d9d9; font-weight: bold; } /* Constant */
63+ code span.co { color: #a1a6a8; } /* Comment */
64+ code span.cv { color: #b6c8c9; } /* CommentVar */
6565 code span.do { color: #a43340; } /* Documentation */
66− code span.dt { color: #2980b9; } /* DataType */
67− code span.dv { color: #f67400; } /* DecVal */
68− code span.er { color: #da4453; text-decoration: underline; } /* Error */
69− code span.ex { color: #0099ff; font-weight: bold; } /* Extension */
70− code span.fl { color: #f67400; } /* Float */
71− code span.fu { color: #8e44ad; } /* Function */
72− code span.im { color: #27ae60; } /* Import */
73− code span.in { color: #c45b00; } /* Information */
74− code span.kw { color: #cfcfc2; font-weight: bold; } /* Keyword */
75− code span.op { color: #cfcfc2; } /* Operator */
76− code span.ot { color: #27ae60; } /* Other */
77− code span.pp { color: #27ae60; } /* Preprocessor */
78− code span.re { color: #2980b9; background-color: #153042; } /* RegionMarker */
79− code span.sc { color: #3daee9; } /* SpecialChar */
80− code span.ss { color: #da4453; } /* SpecialString */
81− code span.st { color: #f44f4f; } /* String */
82− code span.va { color: #27aeae; } /* Variable */
83− code span.vs { color: #da4453; } /* VerbatimString */
84− code span.wa { color: #da4453; } /* Warning */
66+ code span.dt { color: #7cc0ec; } /* DataType */
67+ code span.dv { color: #f6b77f; } /* DecVal */
68+ code span.er { color: #e9848e; text-decoration: underline; } /* Error */
69+ code span.ex { color: #96d5ff; font-weight: bold; } /* Extension */
70+ code span.fl { color: #fdae67; } /* Float */
71+ code span.fu { color: #d487f4; } /* Function */
72+ code span.im { color: #76e8a6; } /* Import */
73+ code span.in { color: #f6b176; } /* Information */
74+ code span.kw { color: #ebebc9; font-weight: bold; } /* Keyword */
75+ code span.op { color: #ececde; } /* Operator */
76+ code span.ot { color: #86e9b0; } /* Other */
77+ code span.pp { color: #62e298; } /* Preprocessor */
78+ code span.re { color: #83c7f4; background-color: #153042; } /* RegionMarker */
79+ code span.sc { color: #80ccf4; } /* SpecialChar */
80+ code span.ss { color: #ff909b; } /* SpecialString */
81+ code span.st { color: #ff9f9f; } /* String */
82+ code span.va { color: #56d4d4; } /* Variable */
83+ code span.vs { color: #eca2a9; } /* VerbatimString */
84+ code span.wa { color: #eca2a9; } /* Warning */
8585 </style>
8686 <link rel="stylesheet" href="reveal.js/css/theme/superblack.css" id="theme">
8787 <!-- Printing and PDF exports -->
@@ -112,31 +112,46 @@
112112 <div class="slides">
113113
114114
115−<section id="библиотека-про-математику" class="slide level3">
116−<h3>Библиотека про математику</h3>
115+<section>
116+<section id="функциональное-программирование" class="title-slide slide level1">
117+<h1>Функциональное программирование</h1>
118+
119+</section>
120+<section id="напоминалочка" class="slide level2">
121+<h2>Напоминалочка</h2>
122+<div class="sourceCode" id="cb1"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1"></a><span class="kw">class</span> <span class="dt">Functor</span> f <span class="kw">where</span></span>
123+<span id="cb1-2"><a href="#cb1-2"></a><span class="ot"> fmap ::</span> (a <span class="ot">-&gt;</span> b) <span class="ot">-&gt;</span> f a <span class="ot">-&gt;</span> f b</span></code></pre></div>
124+<div class="sourceCode" id="cb2"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1"></a><span class="kw">class</span> <span class="dt">Functor</span> f <span class="ot">=&gt;</span> <span class="dt">Alternative</span> f <span class="kw">where</span></span>
125+<span id="cb2-2"><a href="#cb2-2"></a><span class="ot"> (&lt;|&gt;) ::</span> f a <span class="ot">-&gt;</span> f a <span class="ot">-&gt;</span> f a</span>
126+<span id="cb2-3"><a href="#cb2-3"></a><span class="ot"> empty ::</span> f a</span></code></pre></div>
127+</section>
128+<section id="библиотека-про-математику" class="slide level2">
129+<h2>Библиотека про математику</h2>
117130<h4 id="на-джаве">(на джаве)</h4>
118−<div class="sourceCode" id="cb1"><pre class="sourceCode java fragment"><code class="sourceCode java"><span id="cb1-1"><a href="#cb1-1"></a><span class="dt">static</span> <span class="dt">int</span> <span class="fu">add</span>(<span class="dt">int</span> x, <span class="dt">int</span> y) {</span>
119−<span id="cb1-2"><a href="#cb1-2"></a> <span class="kw">return</span> x + y;</span>
120−<span id="cb1-3"><a href="#cb1-3"></a>}</span></code></pre></div>
131+<div class="sourceCode" id="cb3"><pre class="sourceCode java fragment"><code class="sourceCode java"><span id="cb3-1"><a href="#cb3-1"></a><span class="dt">static</span> <span class="dt">int</span> <span class="fu">add</span>(<span class="dt">int</span> x, <span class="dt">int</span> y) {</span>
132+<span id="cb3-2"><a href="#cb3-2"></a> <span class="kw">return</span> x + y;</span>
133+<span id="cb3-3"><a href="#cb3-3"></a>}</span></code></pre></div>
121134<p><span class="fragment">“Нам для сертификации надо чтобы каждая функция логировала свой вызов.”</span></p>
122135</section>
123−<section id="вариант-1" class="slide level3">
124−<h3>Вариант 1</h3>
125−<div class="sourceCode" id="cb2"><pre class="sourceCode java fragment"><code class="sourceCode java"><span id="cb2-1"><a href="#cb2-1"></a><span class="dt">static</span> <span class="dt">int</span> <span class="fu">add</span>(<span class="dt">int</span> x, <span class="dt">int</span> y) {</span>
126−<span id="cb2-2"><a href="#cb2-2"></a> log += <span class="st">&quot;add&quot;</span>;</span>
127−<span id="cb2-3"><a href="#cb2-3"></a> <span class="kw">return</span> x + y;</span>
128−<span id="cb2-4"><a href="#cb2-4"></a>}</span></code></pre></div>
136+<section class="slide level2">
137+
138+<h3 id="вариант-1">Вариант 1</h3>
139+<div class="sourceCode" id="cb4"><pre class="sourceCode java fragment"><code class="sourceCode java"><span id="cb4-1"><a href="#cb4-1"></a><span class="dt">static</span> <span class="dt">int</span> <span class="fu">add</span>(<span class="dt">int</span> x, <span class="dt">int</span> y) {</span>
140+<span id="cb4-2"><a href="#cb4-2"></a> log += <span class="st">&quot;add&quot;</span>;</span>
141+<span id="cb4-3"><a href="#cb4-3"></a> <span class="kw">return</span> x + y;</span>
142+<span id="cb4-4"><a href="#cb4-4"></a>}</span></code></pre></div>
129143<ol type="1">
130144<li class="fragment">Неявная зависимость</li>
131145<li class="fragment">Невозможно рефакторить</li>
132146<li class="fragment">Почему функция для складывания чисел умеет логи?</li>
133147</ol>
134148</section>
135−<section id="вариант-2" class="slide level3">
136−<h3>Вариант 2</h3>
137−<div class="sourceCode" id="cb3"><pre class="sourceCode java fragment"><code class="sourceCode java"><span id="cb3-1"><a href="#cb3-1"></a><span class="dt">static</span> Pair&lt;<span class="bu">Integer</span>, <span class="bu">String</span>&gt; <span class="fu">add</span>(<span class="dt">int</span> x, <span class="dt">int</span> y, string log) {</span>
138−<span id="cb3-2"><a href="#cb3-2"></a> <span class="kw">return</span> <span class="kw">new</span> <span class="fu">Pair</span>(x + y, log + <span class="st">&quot;add&quot;</span>);</span>
139−<span id="cb3-3"><a href="#cb3-3"></a>}</span></code></pre></div>
149+<section class="slide level2">
150+
151+<h3 id="вариант-2">Вариант 2</h3>
152+<div class="sourceCode" id="cb5"><pre class="sourceCode java fragment"><code class="sourceCode java"><span id="cb5-1"><a href="#cb5-1"></a><span class="dt">static</span> Pair&lt;<span class="bu">Integer</span>, <span class="bu">String</span>&gt; <span class="fu">add</span>(<span class="dt">int</span> x, <span class="dt">int</span> y, string log) {</span>
153+<span id="cb5-2"><a href="#cb5-2"></a> <span class="kw">return</span> <span class="kw">new</span> <span class="fu">Pair</span>(x + y, log + <span class="st">&quot;add&quot;</span>);</span>
154+<span id="cb5-3"><a href="#cb5-3"></a>}</span></code></pre></div>
140155<ol type="1">
141156<li class="fragment"><del>Неявная зависимость</del></li>
142157<li class="fragment"><del>Невозможно рефакторить</del></li>
@@ -144,12 +159,13 @@
144159<li class="fragment">Почему функция для складывания чисел умеет логи?</li>
145160</ol>
146161</section>
147−<section id="вариант-ооп" class="slide level3">
148−<h3>Вариант ООП</h3>
149−<div class="sourceCode" id="cb4"><pre class="sourceCode java fragment"><code class="sourceCode java"><span id="cb4-1"><a href="#cb4-1"></a><span class="dt">static</span> <span class="dt">int</span> <span class="fu">add</span>(<span class="dt">int</span> x, <span class="dt">int</span> y, <span class="bu">Logger</span> log) {</span>
150−<span id="cb4-2"><a href="#cb4-2"></a> <span class="bu">Logger</span>.<span class="fu">log</span>(<span class="st">&quot;add&quot;</span>);</span>
151−<span id="cb4-3"><a href="#cb4-3"></a> <span class="kw">return</span> x + y;</span>
152−<span id="cb4-4"><a href="#cb4-4"></a>}</span></code></pre></div>
162+<section class="slide level2">
163+
164+<h3 id="вариант-ооп">Вариант ООП</h3>
165+<div class="sourceCode" id="cb6"><pre class="sourceCode java fragment"><code class="sourceCode java"><span id="cb6-1"><a href="#cb6-1"></a><span class="dt">static</span> <span class="dt">int</span> <span class="fu">add</span>(<span class="dt">int</span> x, <span class="dt">int</span> y, <span class="bu">Logger</span> log) {</span>
166+<span id="cb6-2"><a href="#cb6-2"></a> <span class="bu">Logger</span>.<span class="fu">log</span>(<span class="st">&quot;add&quot;</span>);</span>
167+<span id="cb6-3"><a href="#cb6-3"></a> <span class="kw">return</span> x + y;</span>
168+<span id="cb6-4"><a href="#cb6-4"></a>}</span></code></pre></div>
153169<ol type="1">
154170<li class="fragment"><del>Неявная зависимость</del></li>
155171<li class="fragment"><del>Невозможно рефакторить</del></li>
@@ -157,10 +173,466 @@
157173<li class="fragment"><del>Почему функция для складывания чисел умеет логи?</del></li>
158174</ol>
159175</section>
160−<section class="slide level3">
176+<section class="slide level2">
177+
178+<div class="sourceCode" id="cb7"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb7-1"><a href="#cb7-1"></a><span class="ot">add ::</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> (<span class="dt">Int</span>, <span class="dt">String</span>)</span>
179+<span id="cb7-2"><a href="#cb7-2"></a>add x y <span class="ot">=</span> (x <span class="op">+</span> y, <span class="st">&quot;add &quot;</span> <span class="op">+</span> <span class="fu">show</span> x <span class="op">+</span> <span class="fu">show</span> y)</span></code></pre></div>
180+<p><span class="fragment">Неудобно программировать</span></p>
181+<div class="sourceCode" id="cb8"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb8-1"><a href="#cb8-1"></a><span class="ot">add ::</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">Int</span></span>
182+<span id="cb8-2"><a href="#cb8-2"></a><span class="ot">times ::</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">Int</span></span>
183+<span id="cb8-3"><a href="#cb8-3"></a></span>
184+<span id="cb8-4"><a href="#cb8-4"></a><span class="ot">add8AndDouble ::</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">Int</span></span>
185+<span id="cb8-5"><a href="#cb8-5"></a>add8AndDouble <span class="ot">=</span> times <span class="dv">2</span> <span class="op">.</span> add <span class="dv">8</span></span></code></pre></div>
186+</section>
187+<section class="slide level2">
188+
189+<div class="sourceCode" id="cb9"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb9-1"><a href="#cb9-1"></a><span class="ot">add ::</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> (<span class="dt">Int</span>, <span class="dt">String</span>)</span>
190+<span id="cb9-2"><a href="#cb9-2"></a><span class="ot">times ::</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> (<span class="dt">Int</span>, <span class="dt">String</span>)</span></code></pre></div>
191+<div class="sourceCode" id="cb10"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb10-1"><a href="#cb10-1"></a><span class="ot">add8AndDouble ::</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> (<span class="dt">Int</span>, <span class="dt">String</span>)</span>
192+<span id="cb10-2"><a href="#cb10-2"></a>add8AndDouble x <span class="ot">=</span> (y2, log1 <span class="op">&lt;&gt;</span> log2)</span>
193+<span id="cb10-3"><a href="#cb10-3"></a> <span class="kw">where</span></span>
194+<span id="cb10-4"><a href="#cb10-4"></a> (y1, log1) <span class="ot">=</span> add <span class="dv">8</span> x</span>
195+<span id="cb10-5"><a href="#cb10-5"></a> (y2, log2) <span class="ot">=</span> times <span class="dv">2</span> y1</span></code></pre></div>
196+<p><img data-src="images/ohno.png" class="fragment" height="200" /></p>
197+<div class="sourceCode" id="cb11"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb11-1"><a href="#cb11-1"></a><span class="ot">add8AndDouble ::</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">Int</span></span>
198+<span id="cb11-2"><a href="#cb11-2"></a>add8AndDouble <span class="ot">=</span> times <span class="dv">2</span> <span class="op">.</span> add <span class="dv">8</span></span></code></pre></div>
199+</section>
200+<section class="slide level2">
201+
202+<div class="sourceCode" id="cb12"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb12-1"><a href="#cb12-1"></a><span class="kw">data</span> <span class="dt">WithLog</span> a <span class="ot">=</span> <span class="dt">WithLog</span> a <span class="dt">String</span></span></code></pre></div>
203+<div class="sourceCode" id="cb13"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb13-1"><a href="#cb13-1"></a><span class="ot">add ::</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">WithLog</span> <span class="dt">Int</span></span>
204+<span id="cb13-2"><a href="#cb13-2"></a><span class="ot">times ::</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">WithLog</span> <span class="dt">Int</span></span></code></pre></div>
205+<div class="sourceCode" id="cb14"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb14-1"><a href="#cb14-1"></a><span class="ot">add8AndDouble ::</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">WithLog</span> <span class="dt">Int</span></span>
206+<span id="cb14-2"><a href="#cb14-2"></a>add8AndDouble <span class="ot">=</span> times <span class="dv">2</span> <span class="ot">`magic`</span> add <span class="dv">8</span></span></code></pre></div>
207+<div class="sourceCode" id="cb15"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb15-1"><a href="#cb15-1"></a><span class="ot">magic ::</span></span>
208+<span id="cb15-2"><a href="#cb15-2"></a> (<span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">WithLog</span> <span class="dt">Int</span>) <span class="ot">-&gt;</span></span>
209+<span id="cb15-3"><a href="#cb15-3"></a> (<span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">WithLog</span> <span class="dt">Int</span>) <span class="ot">-&gt;</span></span>
210+<span id="cb15-4"><a href="#cb15-4"></a> (<span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">WithLog</span> <span class="dt">Int</span>)</span></code></pre></div>
211+<div class="sourceCode" id="cb16"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb16-1"><a href="#cb16-1"></a>magic f g x1 <span class="ot">=</span> <span class="dt">WithLog</span> x3 (log1 <span class="op">&lt;&gt;</span> log2)</span>
212+<span id="cb16-2"><a href="#cb16-2"></a> <span class="kw">where</span></span>
213+<span id="cb16-3"><a href="#cb16-3"></a> (<span class="dt">WithLog</span> x2 log1) <span class="ot">=</span> g x1</span>
214+<span id="cb16-4"><a href="#cb16-4"></a> (<span class="dt">WithLog</span> x3 log2) <span class="ot">=</span> f x2</span></code></pre></div>
215+</section>
216+<section class="slide level2">
217+
218+<div class="sourceCode" id="cb17"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb17-1"><a href="#cb17-1"></a><span class="ot">magic ::</span></span>
219+<span id="cb17-2"><a href="#cb17-2"></a> (<span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">WithLog</span> <span class="dt">Int</span>) <span class="ot">-&gt;</span></span>
220+<span id="cb17-3"><a href="#cb17-3"></a> (<span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">WithLog</span> <span class="dt">Int</span>) <span class="ot">-&gt;</span></span>
221+<span id="cb17-4"><a href="#cb17-4"></a> (<span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">WithLog</span> <span class="dt">Int</span>)</span></code></pre></div>
222+<div class="sourceCode" id="cb18"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb18-1"><a href="#cb18-1"></a>(<span class="op">&lt;=&lt;</span>) <span class="ot">::</span></span>
223+<span id="cb18-2"><a href="#cb18-2"></a> (<span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">WithLog</span> <span class="dt">Int</span>) <span class="ot">-&gt;</span></span>
224+<span id="cb18-3"><a href="#cb18-3"></a> (<span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">WithLog</span> <span class="dt">Int</span>) <span class="ot">-&gt;</span></span>
225+<span id="cb18-4"><a href="#cb18-4"></a> (<span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">WithLog</span> <span class="dt">Int</span>)</span></code></pre></div>
226+<div class="sourceCode" id="cb19"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb19-1"><a href="#cb19-1"></a><span class="ot">add8AndDouble ::</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">WithLog</span> <span class="dt">Int</span></span>
227+<span id="cb19-2"><a href="#cb19-2"></a>add8AndDouble <span class="ot">=</span> times <span class="dv">2</span> <span class="op">&lt;=&lt;</span> add <span class="dv">8</span></span></code></pre></div>
228+</section>
229+<section class="slide level2">
230+
231+<div class="sourceCode" id="cb20"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb20-1"><a href="#cb20-1"></a><span class="ot">factor ::</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">WithLog</span> [<span class="dt">Int</span>]</span>
232+<span id="cb20-2"><a href="#cb20-2"></a></span>
233+<span id="cb20-3"><a href="#cb20-3"></a><span class="fu">sum</span><span class="ot"> ::</span> [<span class="dt">Int</span>] <span class="ot">-&gt;</span> <span class="dt">WithLog</span> <span class="dt">Int</span></span></code></pre></div>
234+<div class="sourceCode" id="cb21"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb21-1"><a href="#cb21-1"></a><span class="ot">sumFactors ::</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">WithLog</span> [<span class="dt">Int</span>]</span>
235+<span id="cb21-2"><a href="#cb21-2"></a>sumFactors <span class="ot">=</span> <span class="fu">sum</span> <span class="op">&lt;=&lt;</span> factor <span class="co">-- Doesn&#39;t work :(</span></span></code></pre></div>
236+<div class="sourceCode" id="cb22"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb22-1"><a href="#cb22-1"></a>(<span class="op">&lt;=&lt;</span>) <span class="ot">::</span></span>
237+<span id="cb22-2"><a href="#cb22-2"></a> (<span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">WithLog</span> <span class="dt">Int</span>) <span class="ot">-&gt;</span></span>
238+<span id="cb22-3"><a href="#cb22-3"></a> (<span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">WithLog</span> <span class="dt">Int</span>) <span class="ot">-&gt;</span></span>
239+<span id="cb22-4"><a href="#cb22-4"></a> (<span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">WithLog</span> <span class="dt">Int</span>)</span></code></pre></div>
240+<div class="sourceCode" id="cb23"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb23-1"><a href="#cb23-1"></a>(<span class="op">&lt;=&lt;</span>) <span class="ot">::</span></span>
241+<span id="cb23-2"><a href="#cb23-2"></a> (b <span class="ot">-&gt;</span> <span class="dt">WithLog</span> c ) <span class="ot">-&gt;</span></span>
242+<span id="cb23-3"><a href="#cb23-3"></a> (a <span class="ot">-&gt;</span> <span class="dt">WithLog</span> b ) <span class="ot">-&gt;</span></span>
243+<span id="cb23-4"><a href="#cb23-4"></a> (a <span class="ot">-&gt;</span> <span class="dt">WithLog</span> c )</span></code></pre></div>
244+<div class="sourceCode" id="cb24"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb24-1"><a href="#cb24-1"></a>(<span class="op">.</span>) <span class="ot">::</span></span>
245+<span id="cb24-2"><a href="#cb24-2"></a> (b <span class="ot">-&gt;</span> c ) <span class="ot">-&gt;</span></span>
246+<span id="cb24-3"><a href="#cb24-3"></a> (a <span class="ot">-&gt;</span> b ) <span class="ot">-&gt;</span></span>
247+<span id="cb24-4"><a href="#cb24-4"></a> (a <span class="ot">-&gt;</span> c )</span></code></pre></div>
248+</section>
249+<section class="slide level2">
250+
251+<div class="sourceCode" id="cb25"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb25-1"><a href="#cb25-1"></a><span class="ot">getCoffee ::</span> <span class="dt">Order</span> <span class="ot">-&gt;</span> <span class="dt">Maybe</span> <span class="dt">Coffee</span></span>
252+<span id="cb25-2"><a href="#cb25-2"></a><span class="ot">payForCoffee ::</span> <span class="dt">Coffee</span> <span class="ot">-&gt;</span> <span class="dt">Maybe</span> <span class="dt">Payment</span></span></code></pre></div>
253+<div class="sourceCode" id="cb26"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb26-1"><a href="#cb26-1"></a><span class="ot">buyCoffee ::</span> <span class="dt">Order</span> <span class="ot">-&gt;</span> <span class="dt">Maybe</span> <span class="dt">Payment</span></span>
254+<span id="cb26-2"><a href="#cb26-2"></a>buyCoffee <span class="ot">=</span> payForCoffee <span class="op">&lt;=&lt;</span> getCoffee</span></code></pre></div>
255+<div class="sourceCode" id="cb27"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb27-1"><a href="#cb27-1"></a><span class="ot">getCoffee ::</span> <span class="dt">Order</span> <span class="ot">-&gt;</span> <span class="dt">Either</span> <span class="dt">CoffeeError</span> <span class="dt">Coffee</span></span>
256+<span id="cb27-2"><a href="#cb27-2"></a><span class="ot">payForCoffee ::</span> <span class="dt">Coffee</span> <span class="ot">-&gt;</span> <span class="dt">Either</span> <span class="dt">CoffeeError</span> <span class="dt">Payment</span></span></code></pre></div>
257+<div class="sourceCode" id="cb28"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb28-1"><a href="#cb28-1"></a><span class="ot">buyCoffee ::</span> <span class="dt">Order</span> <span class="ot">-&gt;</span> <span class="dt">Either</span> <span class="dt">CoffeeError</span> <span class="dt">Payment</span></span>
258+<span id="cb28-2"><a href="#cb28-2"></a>buyCoffee <span class="ot">=</span> payForCoffee <span class="op">&lt;=&lt;</span> getCoffee</span></code></pre></div>
259+<div class="sourceCode" id="cb29"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb29-1"><a href="#cb29-1"></a>(<span class="op">&lt;=&lt;</span>) <span class="ot">::</span></span>
260+<span id="cb29-2"><a href="#cb29-2"></a> <span class="dt">Composable</span> m <span class="ot">=&gt;</span></span>
261+<span id="cb29-3"><a href="#cb29-3"></a> (b <span class="ot">-&gt;</span> m c) <span class="ot">-&gt;</span></span>
262+<span id="cb29-4"><a href="#cb29-4"></a> (a <span class="ot">-&gt;</span> m b) <span class="ot">-&gt;</span></span>
263+<span id="cb29-5"><a href="#cb29-5"></a> (a <span class="ot">-&gt;</span> m c)</span></code></pre></div>
264+</section>
265+<section class="slide level2">
266+
267+<div class="sourceCode" id="cb30"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb30-1"><a href="#cb30-1"></a><span class="kw">class</span> <span class="dt">Applicative</span> m <span class="ot">=&gt;</span> <span class="dt">Monad</span> m <span class="kw">where</span></span>
268+<span id="cb30-2"><a href="#cb30-2"></a><span class="ot"> (&lt;=&lt;) ::</span> (b <span class="ot">-&gt;</span> m c) <span class="ot">-&gt;</span> (a <span class="ot">-&gt;</span> m b) <span class="ot">-&gt;</span> (a <span class="ot">-&gt;</span> m c)</span></code></pre></div>
269+<div class="sourceCode" id="cb31"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb31-1"><a href="#cb31-1"></a><span class="kw">instance</span> <span class="dt">Monad</span> <span class="dt">Maybe</span> <span class="kw">where</span></span>
270+<span id="cb31-2"><a href="#cb31-2"></a> (<span class="op">&lt;=&lt;</span>) f g x <span class="ot">=</span> <span class="kw">case</span> g x <span class="kw">of</span></span>
271+<span id="cb31-3"><a href="#cb31-3"></a> <span class="dt">Nothing</span> <span class="ot">-&gt;</span> <span class="dt">Nothing</span></span>
272+<span id="cb31-4"><a href="#cb31-4"></a> <span class="dt">Just</span> x2 <span class="ot">-&gt;</span> f x2</span></code></pre></div>
273+<div class="sourceCode" id="cb32"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb32-1"><a href="#cb32-1"></a><span class="kw">instance</span> <span class="dt">Monad</span> (<span class="dt">Either</span> e) <span class="kw">where</span></span>
274+<span id="cb32-2"><a href="#cb32-2"></a> (<span class="op">&lt;=&lt;</span>) f g x <span class="ot">=</span> <span class="kw">case</span> g x <span class="kw">of</span></span>
275+<span id="cb32-3"><a href="#cb32-3"></a> <span class="dt">Left</span> e <span class="ot">-&gt;</span> <span class="dt">Left</span> e</span>
276+<span id="cb32-4"><a href="#cb32-4"></a> <span class="dt">Right</span> x2 <span class="ot">-&gt;</span> f x2</span></code></pre></div>
277+<div class="sourceCode" id="cb33"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb33-1"><a href="#cb33-1"></a><span class="kw">instance</span> <span class="dt">Monad</span> <span class="dt">WithLog</span> <span class="kw">where</span></span>
278+<span id="cb33-2"><a href="#cb33-2"></a> (<span class="op">&lt;=&lt;</span>) f g x <span class="ot">=</span> <span class="dt">WithLog</span> x3 (log1 <span class="op">&lt;&gt;</span> log2)</span>
279+<span id="cb33-3"><a href="#cb33-3"></a> <span class="kw">where</span></span>
280+<span id="cb33-4"><a href="#cb33-4"></a> (<span class="dt">WithLog</span> x2 log1) <span class="ot">=</span> g x1</span>
281+<span id="cb33-5"><a href="#cb33-5"></a> (<span class="dt">WithLog</span> x3 log2) <span class="ot">=</span> f x2</span></code></pre></div>
282+</section>
283+<section class="slide level2">
284+
285+<h3 id="больше-операторов">Больше операторов!</h3>
286+<div class="sourceCode" id="cb34"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb34-1"><a href="#cb34-1"></a><span class="ot">(&lt;=&lt;) ::</span> <span class="dt">Monad</span> m <span class="ot">=&gt;</span> (b <span class="ot">-&gt;</span> m c) <span class="ot">-&gt;</span> (a <span class="ot">-&gt;</span> m b) <span class="ot">-&gt;</span> (a <span class="ot">-&gt;</span> m c)</span></code></pre></div>
287+<div class="sourceCode" id="cb35"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb35-1"><a href="#cb35-1"></a><span class="ot">buyCoffee ::</span> <span class="dt">Order</span> <span class="ot">-&gt;</span> <span class="dt">Maybe</span> <span class="dt">Payment</span></span>
288+<span id="cb35-2"><a href="#cb35-2"></a>buyCoffee <span class="ot">=</span> payForCoffee <span class="op">&lt;=&lt;</span> getCoffee</span></code></pre></div>
289+<div class="sourceCode" id="cb36"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb36-1"><a href="#cb36-1"></a><span class="fu">flip</span><span class="ot"> ::</span> (a <span class="ot">-&gt;</span> b <span class="ot">-&gt;</span> c) <span class="ot">-&gt;</span> (b <span class="ot">-&gt;</span> a <span class="ot">-&gt;</span> c)</span>
290+<span id="cb36-2"><a href="#cb36-2"></a><span class="fu">flip</span> f b a <span class="ot">=</span> f a b</span></code></pre></div>
291+<div class="sourceCode" id="cb37"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb37-1"><a href="#cb37-1"></a><span class="ot">(&gt;=&gt;) ::</span> <span class="dt">Monad</span> m <span class="ot">=&gt;</span> (a <span class="ot">-&gt;</span> m b) <span class="ot">-&gt;</span> (b <span class="ot">-&gt;</span> m c) <span class="ot">-&gt;</span> (a <span class="ot">-&gt;</span> m c)</span>
292+<span id="cb37-2"><a href="#cb37-2"></a>(<span class="op">&gt;=&gt;</span>) <span class="ot">=</span> <span class="fu">flip</span> (<span class="op">&lt;=&lt;</span>)</span></code></pre></div>
293+<div class="sourceCode" id="cb38"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb38-1"><a href="#cb38-1"></a>buyCoffee <span class="ot">=</span> getCoffee <span class="op">&gt;=&gt;</span> payForCoffee</span></code></pre></div>
294+</section>
295+<section class="slide level2">
296+
297+<h3 id="маленькое-отступление">Маленькое отступление</h3>
298+<p><code>f :: () -&gt; a</code> эквивалентно <code>f :: a</code></p>
299+<p><span class="fragment">Потому что у <code>()</code> всего одно значение (<code>()</code>), а любая функция для одинаковых аргументов всегда возвращает одинаковые значения (потому что по-другому невозможно).</span></p>
300+</section>
301+<section class="slide level2">
302+
303+<div class="sourceCode" id="cb39"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb39-1"><a href="#cb39-1"></a><span class="ot">(&gt;=&gt;) ::</span> <span class="dt">Monad</span> m <span class="ot">=&gt;</span> (a <span class="ot">-&gt;</span> m b) <span class="ot">-&gt;</span> (b <span class="ot">-&gt;</span> m c) <span class="ot">-&gt;</span> (a <span class="ot">-&gt;</span> m c)</span></code></pre></div>
304+<div class="sourceCode" id="cb40"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb40-1"><a href="#cb40-1"></a><span class="ot">(&gt;&gt;=) ::</span> <span class="dt">Monad</span> m <span class="ot">=&gt;</span> m b <span class="ot">-&gt;</span> (b <span class="ot">-&gt;</span> m c) <span class="ot">-&gt;</span> m c</span></code></pre></div>
305+<div class="sourceCode" id="cb41"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb41-1"><a href="#cb41-1"></a><span class="ot">buyCoffee ::</span> <span class="dt">Order</span> <span class="ot">-&gt;</span> <span class="dt">Maybe</span> <span class="dt">Payment</span></span>
306+<span id="cb41-2"><a href="#cb41-2"></a>buyCoffee order <span class="ot">=</span> getCoffee order <span class="op">&gt;&gt;=</span> payForCoffee</span></code></pre></div>
307+<div class="sourceCode" id="cb42"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb42-1"><a href="#cb42-1"></a><span class="ot">maybeBuyCoffee ::</span> <span class="dt">Myabe</span> <span class="dt">Order</span> <span class="ot">-&gt;</span> <span class="dt">Maybe</span> <span class="dt">Payment</span></span>
308+<span id="cb42-2"><a href="#cb42-2"></a>maybeBuyCoffee order <span class="ot">=</span> order <span class="op">&gt;&gt;=</span> buyCoffee</span></code></pre></div>
309+<div class="sourceCode" id="cb43"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb43-1"><a href="#cb43-1"></a><span class="ot">(&gt;&gt;=) ::</span> <span class="dt">Monad</span> m <span class="ot">=&gt;</span> m b <span class="ot">-&gt;</span> (b <span class="ot">-&gt;</span> m c) <span class="ot">-&gt;</span> m c</span></code></pre></div>
310+<div class="sourceCode" id="cb44"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb44-1"><a href="#cb44-1"></a><span class="ot">(&gt;=&gt;) ::</span> <span class="dt">Monad</span> m <span class="ot">=&gt;</span> (a <span class="ot">-&gt;</span> m b) <span class="ot">-&gt;</span> (b <span class="ot">-&gt;</span> m c) <span class="ot">-&gt;</span> (a <span class="ot">-&gt;</span> m c)</span></code></pre></div>
311+<div class="sourceCode" id="cb45"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb45-1"><a href="#cb45-1"></a> (() <span class="ot">-&gt;</span> m b) <span class="ot">-&gt;</span> (b <span class="ot">-&gt;</span> m c) <span class="ot">-&gt;</span> (() <span class="ot">-&gt;</span> m c)</span></code></pre></div>
312+<div class="sourceCode" id="cb46"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb46-1"><a href="#cb46-1"></a> m b <span class="ot">-&gt;</span> (b <span class="ot">-&gt;</span> m c) <span class="ot">-&gt;</span> m c</span></code></pre></div>
313+</section>
314+<section class="slide level2">
315+
316+<div class="sourceCode" id="cb47"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb47-1"><a href="#cb47-1"></a><span class="ot">(&gt;=&gt;) ::</span> <span class="dt">Monad</span> m <span class="ot">=&gt;</span> (a <span class="ot">-&gt;</span> m b) <span class="ot">-&gt;</span> (b <span class="ot">-&gt;</span> m c) <span class="ot">-&gt;</span> (a <span class="ot">-&gt;</span> m c)</span></code></pre></div>
317+<div class="sourceCode" id="cb48"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb48-1"><a href="#cb48-1"></a><span class="ot">(&gt;&gt;=) ::</span> <span class="dt">Monad</span> m <span class="ot">=&gt;</span> m b <span class="ot">-&gt;</span> (b <span class="ot">-&gt;</span> m c) <span class="ot">-&gt;</span> m c</span>
318+<span id="cb48-2"><a href="#cb48-2"></a>(<span class="op">&gt;&gt;=</span>) mb f <span class="ot">=</span> ( (\() <span class="ot">-&gt;</span> mb) <span class="op">&gt;=&gt;</span> f ) ()</span></code></pre></div>
319+<div class="sourceCode" id="cb49"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb49-1"><a href="#cb49-1"></a>(<span class="op">&gt;&gt;=</span>) mb f <span class="ot">=</span> ( (\() <span class="ot">-&gt;</span> mb) <span class="op">&gt;=&gt;</span> f ) ()</span>
320+<span id="cb49-2"><a href="#cb49-2"></a><span class="co">-- () -&gt; m b |</span></span>
321+<span id="cb49-3"><a href="#cb49-3"></a><span class="co">-- b -&gt; m c</span></span>
322+<span id="cb49-4"><a href="#cb49-4"></a><span class="co">--</span></span>
323+<span id="cb49-5"><a href="#cb49-5"></a><span class="co">-- ^-------------------^</span></span>
324+<span id="cb49-6"><a href="#cb49-6"></a><span class="co">-- () -&gt; m c</span></span></code></pre></div>
325+</section>
326+<section class="slide level2">
327+
328+<h3 id="время-раскрыть-ложь">Время раскрыть ложь</h3>
329+<div class="sourceCode" id="cb50"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb50-1"><a href="#cb50-1"></a><span class="kw">class</span> <span class="dt">Applicative</span> m <span class="ot">=&gt;</span> <span class="dt">Monad</span> m <span class="kw">where</span></span>
330+<span id="cb50-2"><a href="#cb50-2"></a><span class="ot"> (&gt;&gt;=) ::</span> m a <span class="ot">-&gt;</span> (a <span class="ot">-&gt;</span> m b) <span class="ot">-&gt;</span> m b</span>
331+<span id="cb50-3"><a href="#cb50-3"></a><span class="ot"> return ::</span> a <span class="ot">-&gt;</span> m a</span></code></pre></div>
332+<div class="sourceCode" id="cb51"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb51-1"><a href="#cb51-1"></a> <span class="co">-- Law:</span></span>
333+<span id="cb51-2"><a href="#cb51-2"></a><span class="ot"> ma ::</span> m a</span>
334+<span id="cb51-3"><a href="#cb51-3"></a> (ma <span class="op">&gt;&gt;=</span> <span class="fu">return</span>) <span class="op">==</span> ma</span></code></pre></div>
335+<div class="sourceCode" id="cb52"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb52-1"><a href="#cb52-1"></a> <span class="co">-- Law:</span></span>
336+<span id="cb52-2"><a href="#cb52-2"></a><span class="ot"> f ::</span> a <span class="ot">-&gt;</span> m b</span>
337+<span id="cb52-3"><a href="#cb52-3"></a> (f <span class="op">&gt;=&gt;</span> <span class="fu">return</span>) <span class="op">==</span> f</span></code></pre></div>
338+<p><span class="fragment"><code>return</code> – нейтральный элемент по <code>&gt;=&gt;</code></span></p>
339+<div class="sourceCode" id="cb53"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb53-1"><a href="#cb53-1"></a> <span class="co">-- Law:</span></span>
340+<span id="cb53-2"><a href="#cb53-2"></a><span class="ot"> x ::</span> a</span>
341+<span id="cb53-3"><a href="#cb53-3"></a><span class="ot"> f ::</span> a <span class="ot">-&gt;</span> m b</span>
342+<span id="cb53-4"><a href="#cb53-4"></a> (<span class="fu">return</span> x <span class="op">&gt;&gt;=</span> f) <span class="op">==</span> f x</span></code></pre></div>
343+</section>
344+<section class="slide level2">
161345
162−<div class="sourceCode" id="cb5"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"></code></pre></div>
346+<div class="sourceCode" id="cb54"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb54-1"><a href="#cb54-1"></a><span class="kw">instance</span> <span class="dt">Monad</span> <span class="dt">Maybe</span> <span class="kw">where</span></span>
347+<span id="cb54-2"><a href="#cb54-2"></a> ma <span class="op">&gt;&gt;=</span> f <span class="ot">=</span> <span class="kw">case</span> ma <span class="kw">of</span></span>
348+<span id="cb54-3"><a href="#cb54-3"></a> <span class="dt">Nothing</span> <span class="ot">-&gt;</span> <span class="dt">Nothing</span></span>
349+<span id="cb54-4"><a href="#cb54-4"></a> <span class="dt">Just</span> a <span class="ot">-&gt;</span> f a</span>
350+<span id="cb54-5"><a href="#cb54-5"></a></span>
351+<span id="cb54-6"><a href="#cb54-6"></a> <span class="fu">return</span> a <span class="ot">=</span> <span class="dt">Just</span> a</span></code></pre></div>
352+<div class="sourceCode" id="cb55"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb55-1"><a href="#cb55-1"></a><span class="kw">instance</span> <span class="dt">Monad</span> (<span class="dt">Either</span> e) <span class="kw">where</span></span>
353+<span id="cb55-2"><a href="#cb55-2"></a> ma <span class="op">&gt;&gt;=</span> f <span class="ot">=</span> <span class="kw">case</span> ma <span class="kw">of</span></span>
354+<span id="cb55-3"><a href="#cb55-3"></a> <span class="dt">Left</span> e <span class="ot">-&gt;</span> <span class="dt">Left</span> e</span>
355+<span id="cb55-4"><a href="#cb55-4"></a> <span class="dt">Right</span> a <span class="ot">-&gt;</span> f a</span>
356+<span id="cb55-5"><a href="#cb55-5"></a></span>
357+<span id="cb55-6"><a href="#cb55-6"></a> <span class="fu">return</span> a <span class="ot">=</span> <span class="dt">Right</span> a</span></code></pre></div>
358+<div class="sourceCode" id="cb56"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb56-1"><a href="#cb56-1"></a><span class="kw">instance</span> <span class="dt">Monad</span> <span class="dt">WithLog</span> <span class="kw">where</span></span>
359+<span id="cb56-2"><a href="#cb56-2"></a> (<span class="dt">WithLog</span> a log1) <span class="op">&gt;&gt;=</span> f <span class="ot">=</span> <span class="dt">WithLog</span> b (log1 <span class="op">&lt;&gt;</span> log2)</span>
360+<span id="cb56-3"><a href="#cb56-3"></a> <span class="kw">where</span></span>
361+<span id="cb56-4"><a href="#cb56-4"></a> <span class="dt">WithLog</span> b log2 <span class="ot">=</span> f a</span>
362+<span id="cb56-5"><a href="#cb56-5"></a></span>
363+<span id="cb56-6"><a href="#cb56-6"></a> <span class="fu">return</span> a <span class="ot">=</span> <span class="dt">WithLog</span> a <span class="st">&quot;&quot;</span></span></code></pre></div>
163364</section>
365+<section id="more-monads" class="slide level2">
366+<h2>More Monads!</h2>
367+<div class="sourceCode" id="cb57"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb57-1"><a href="#cb57-1"></a><span class="kw">type</span> <span class="dt">Markup</span> <span class="ot">=</span> <span class="dt">Int</span></span>
368+<span id="cb57-2"><a href="#cb57-2"></a></span>
369+<span id="cb57-3"><a href="#cb57-3"></a><span class="ot">getCoffee ::</span> <span class="dt">Markup</span> <span class="ot">-&gt;</span> <span class="dt">Order</span> <span class="ot">-&gt;</span> <span class="dt">Coffee</span></span>
370+<span id="cb57-4"><a href="#cb57-4"></a><span class="ot">payForCoffee ::</span> <span class="dt">Markup</span> <span class="ot">-&gt;</span> <span class="dt">Coffee</span> <span class="ot">-&gt;</span> <span class="dt">Payment</span></span>
371+<span id="cb57-5"><a href="#cb57-5"></a></span>
372+<span id="cb57-6"><a href="#cb57-6"></a><span class="ot">buyCoffee ::</span> <span class="dt">Markup</span> <span class="ot">-&gt;</span> <span class="dt">Order</span> <span class="ot">-&gt;</span> <span class="dt">Payment</span></span>
373+<span id="cb57-7"><a href="#cb57-7"></a>buyCoffee markup <span class="ot">=</span> payForCoffee markup <span class="op">.</span> getCoffee markup</span></code></pre></div>
374+<div class="sourceCode" id="cb58"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb58-1"><a href="#cb58-1"></a><span class="kw">data</span> <span class="dt">Reader</span> r a <span class="ot">=</span> <span class="dt">Reader</span></span>
375+<span id="cb58-2"><a href="#cb58-2"></a> {<span class="ot"> runReader ::</span> r <span class="ot">-&gt;</span> a</span>
376+<span id="cb58-3"><a href="#cb58-3"></a> }</span></code></pre></div>
377+<p><span class="fragment"><code>r</code> – то, что у нас в “окружении”.</span></p>
378+<div class="sourceCode" id="cb59"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb59-1"><a href="#cb59-1"></a><span class="ot">getCoffee ::</span> <span class="dt">Order</span> <span class="ot">-&gt;</span> <span class="dt">Reader</span> <span class="dt">Markup</span> <span class="dt">Coffee</span></span>
379+<span id="cb59-2"><a href="#cb59-2"></a><span class="ot">payForCoffee ::</span> <span class="dt">Coffee</span> <span class="ot">-&gt;</span> <span class="dt">Reader</span> <span class="dt">Markup</span> <span class="dt">Payment</span></span></code></pre></div>
380+<div class="sourceCode" id="cb60"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb60-1"><a href="#cb60-1"></a><span class="ot">payment ::</span> <span class="dt">Payment</span></span>
381+<span id="cb60-2"><a href="#cb60-2"></a>payment <span class="ot">=</span> runReader (payForCoffee coffee) markup</span></code></pre></div>
382+</section>
383+<section class="slide level2">
384+
385+<div class="sourceCode" id="cb61"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb61-1"><a href="#cb61-1"></a><span class="kw">data</span> <span class="dt">Reader</span> r a <span class="ot">=</span> <span class="dt">Reader</span> {<span class="ot"> runReader ::</span> r <span class="ot">-&gt;</span> a }</span>
386+<span id="cb61-2"><a href="#cb61-2"></a></span>
387+<span id="cb61-3"><a href="#cb61-3"></a><span class="ot">getCoffee ::</span> <span class="dt">Order</span> <span class="ot">-&gt;</span> <span class="dt">Reader</span> <span class="dt">Markup</span> <span class="dt">Coffee</span></span>
388+<span id="cb61-4"><a href="#cb61-4"></a><span class="ot">payForCoffee ::</span> <span class="dt">Coffee</span> <span class="ot">-&gt;</span> <span class="dt">Reader</span> <span class="dt">Markup</span> <span class="dt">Payment</span></span></code></pre></div>
389+<div class="sourceCode" id="cb62"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb62-1"><a href="#cb62-1"></a><span class="ot">buyCoffee ::</span> <span class="dt">Order</span> <span class="ot">-&gt;</span> <span class="dt">Reader</span> <span class="dt">Markup</span> <span class="dt">Payment</span></span>
390+<span id="cb62-2"><a href="#cb62-2"></a>buyCoffee <span class="ot">=</span> payForCoffee <span class="op">&lt;=&lt;</span> getCoffee</span></code></pre></div>
391+<div class="sourceCode" id="cb63"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb63-1"><a href="#cb63-1"></a><span class="kw">type</span> <span class="dt">PricingEnv</span> <span class="ot">=</span> <span class="dt">Reader</span> <span class="dt">Markup</span></span></code></pre></div>
392+<div class="sourceCode" id="cb64"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb64-1"><a href="#cb64-1"></a><span class="ot">getCoffee ::</span> <span class="dt">Order</span> <span class="ot">-&gt;</span> <span class="dt">PricingEnv</span> <span class="dt">Coffee</span></span>
393+<span id="cb64-2"><a href="#cb64-2"></a><span class="ot">payForCoffee ::</span> <span class="dt">Coffee</span> <span class="ot">-&gt;</span> <span class="dt">PricingEnv</span> <span class="dt">Payment</span></span>
394+<span id="cb64-3"><a href="#cb64-3"></a><span class="ot">buyCoffee ::</span> <span class="dt">Order</span> <span class="ot">-&gt;</span> <span class="dt">PricingEnv</span> <span class="dt">Payment</span></span>
395+<span id="cb64-4"><a href="#cb64-4"></a>buyCoffee <span class="ot">=</span> payForCoffee <span class="op">&lt;=&lt;</span> getCoffee</span></code></pre></div>
396+</section>
397+<section class="slide level2">
398+
399+<div class="sourceCode" id="cb65"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb65-1"><a href="#cb65-1"></a><span class="kw">data</span> <span class="dt">Reader</span> r a <span class="ot">=</span> <span class="dt">Reader</span></span>
400+<span id="cb65-2"><a href="#cb65-2"></a> {<span class="ot"> runReader ::</span> r <span class="ot">-&gt;</span> a</span>
401+<span id="cb65-3"><a href="#cb65-3"></a> }</span>
402+<span id="cb65-4"><a href="#cb65-4"></a></span>
403+<span id="cb65-5"><a href="#cb65-5"></a><span class="kw">instance</span> <span class="dt">Monad</span> (<span class="dt">Reader</span> r) <span class="kw">where</span></span>
404+<span id="cb65-6"><a href="#cb65-6"></a> <span class="fu">return</span> a <span class="ot">=</span> <span class="dt">Reader</span> (\_ <span class="ot">-&gt;</span> a)</span>
405+<span id="cb65-7"><a href="#cb65-7"></a></span>
406+<span id="cb65-8"><a href="#cb65-8"></a> (<span class="dt">Reader</span> g) <span class="op">&gt;&gt;=</span> f <span class="ot">=</span> <span class="dt">Reader</span> ( \r <span class="ot">-&gt;</span> runReader (f (g r)) r )</span></code></pre></div>
407+<div class="sourceCode" id="cb66"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb66-1"><a href="#cb66-1"></a><span class="ot"> (&gt;&gt;=) ::</span> <span class="dt">Reader</span> r a <span class="ot">-&gt;</span> (a <span class="ot">-&gt;</span> <span class="dt">Reader</span> r b) <span class="ot">-&gt;</span> <span class="dt">Reader</span> r b</span>
408+<span id="cb66-2"><a href="#cb66-2"></a></span>
409+<span id="cb66-3"><a href="#cb66-3"></a> (<span class="dt">Reader</span> g) <span class="op">&gt;&gt;=</span> f <span class="ot">=</span> <span class="dt">Reader</span> ( \r <span class="ot">-&gt;</span> runReader (f (g r)) r )</span>
410+<span id="cb66-4"><a href="#cb66-4"></a><span class="co">-- ^---^</span></span>
411+<span id="cb66-5"><a href="#cb66-5"></a><span class="co">-- a</span></span>
412+<span id="cb66-6"><a href="#cb66-6"></a><span class="co">-- ^-------^</span></span>
413+<span id="cb66-7"><a href="#cb66-7"></a><span class="co">-- Reader r b</span></span>
414+<span id="cb66-8"><a href="#cb66-8"></a><span class="co">-- ^-----------------^</span></span>
415+<span id="cb66-9"><a href="#cb66-9"></a><span class="co">-- r -&gt; b</span></span></code></pre></div>
416+</section>
417+<section class="slide level2">
418+
419+<div class="sourceCode" id="cb67"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb67-1"><a href="#cb67-1"></a><span class="kw">type</span> <span class="dt">Price</span> <span class="ot">=</span> <span class="dt">Int</span></span>
420+<span id="cb67-2"><a href="#cb67-2"></a><span class="ot">getCoffeePrice ::</span> <span class="dt">Markup</span> <span class="ot">-&gt;</span> <span class="dt">Coffee</span> <span class="ot">-&gt;</span> <span class="dt">Price</span></span>
421+<span id="cb67-3"><a href="#cb67-3"></a><span class="ot">getDiscount ::</span> <span class="dt">Markup</span> <span class="ot">-&gt;</span> <span class="dt">Coffee</span> <span class="ot">-&gt;</span> <span class="dt">Price</span></span>
422+<span id="cb67-4"><a href="#cb67-4"></a><span class="ot">getPayment ::</span> <span class="dt">Markup</span> <span class="ot">-&gt;</span> <span class="dt">Price</span> <span class="ot">-&gt;</span> <span class="dt">Payment</span></span>
423+<span id="cb67-5"><a href="#cb67-5"></a></span>
424+<span id="cb67-6"><a href="#cb67-6"></a><span class="ot">payForCoffee ::</span> <span class="dt">Markup</span> <span class="ot">-&gt;</span> <span class="dt">Coffee</span> <span class="ot">-&gt;</span> <span class="dt">Payment</span></span>
425+<span id="cb67-7"><a href="#cb67-7"></a>payForCoffee markup coffee <span class="ot">=</span> getPayment markup amount</span>
426+<span id="cb67-8"><a href="#cb67-8"></a> <span class="kw">where</span></span>
427+<span id="cb67-9"><a href="#cb67-9"></a> coffeePrice <span class="ot">=</span> getCoffeePrice markup coffee</span>
428+<span id="cb67-10"><a href="#cb67-10"></a> discount <span class="ot">=</span> getDiscount markup coffee</span>
429+<span id="cb67-11"><a href="#cb67-11"></a> amount <span class="ot">=</span> coffeePrice <span class="op">-</span> discount</span></code></pre></div>
430+<div class="sourceCode" id="cb68"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb68-1"><a href="#cb68-1"></a><span class="kw">type</span> <span class="dt">PricingEnv</span> <span class="ot">=</span> <span class="dt">Reader</span> <span class="dt">Markup</span></span>
431+<span id="cb68-2"><a href="#cb68-2"></a></span>
432+<span id="cb68-3"><a href="#cb68-3"></a><span class="ot">getCoffeePrice ::</span> <span class="dt">Coffee</span> <span class="ot">-&gt;</span> <span class="dt">PricingEnv</span> <span class="dt">Price</span></span>
433+<span id="cb68-4"><a href="#cb68-4"></a><span class="ot">getDiscount ::</span> <span class="dt">Coffee</span> <span class="ot">-&gt;</span> <span class="dt">PricingEnv</span> <span class="dt">Price</span></span>
434+<span id="cb68-5"><a href="#cb68-5"></a><span class="ot">getPayment ::</span> <span class="dt">Price</span> <span class="ot">-&gt;</span> <span class="dt">PricingEnv</span> <span class="dt">Payment</span></span>
435+<span id="cb68-6"><a href="#cb68-6"></a></span>
436+<span id="cb68-7"><a href="#cb68-7"></a><span class="ot">payForCoffee ::</span> <span class="dt">Coffee</span> <span class="ot">-&gt;</span> <span class="dt">PricingEnv</span> <span class="dt">Payment</span></span>
437+<span id="cb68-8"><a href="#cb68-8"></a>payForCoffee coffee <span class="ot">=</span></span>
438+<span id="cb68-9"><a href="#cb68-9"></a> coffee <span class="op">&gt;&gt;=</span> getCoffeePrice <span class="op">&gt;&gt;=</span> \coffeePrice <span class="ot">-&gt;</span></span>
439+<span id="cb68-10"><a href="#cb68-10"></a> coffee <span class="op">&gt;&gt;=</span> getDiscount <span class="op">&gt;&gt;=</span> \discount <span class="ot">-&gt;</span></span>
440+<span id="cb68-11"><a href="#cb68-11"></a> getPayment (coffeePrice <span class="op">-</span> discount)</span></code></pre></div>
441+</section>
442+<section id="do-syntax" class="slide level2">
443+<h2>Do syntax</h2>
444+<div class="sourceCode" id="cb69"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb69-1"><a href="#cb69-1"></a><span class="ot">bar ::</span> <span class="dt">Reader</span> r a</span>
445+<span id="cb69-2"><a href="#cb69-2"></a><span class="ot">qux ::</span> a <span class="ot">-&gt;</span> <span class="dt">Reader</span> r b</span>
446+<span id="cb69-3"><a href="#cb69-3"></a></span>
447+<span id="cb69-4"><a href="#cb69-4"></a><span class="ot">foo ::</span> <span class="dt">Reader</span> r b</span>
448+<span id="cb69-5"><a href="#cb69-5"></a>foo <span class="ot">=</span> bar <span class="op">&gt;&gt;=</span> \a <span class="ot">-&gt;</span> qux a</span></code></pre></div>
449+<div class="sourceCode" id="cb70"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb70-1"><a href="#cb70-1"></a>foo <span class="ot">=</span> <span class="kw">do</span></span>
450+<span id="cb70-2"><a href="#cb70-2"></a> a <span class="ot">&lt;-</span> bar</span>
451+<span id="cb70-3"><a href="#cb70-3"></a> qux a</span></code></pre></div>
452+<div class="sourceCode" id="cb71"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb71-1"><a href="#cb71-1"></a>foo <span class="ot">=</span> <span class="kw">do</span></span>
453+<span id="cb71-2"><a href="#cb71-2"></a> a <span class="ot">&lt;-</span> bar</span>
454+<span id="cb71-3"><a href="#cb71-3"></a> b <span class="ot">&lt;-</span> qux a</span>
455+<span id="cb71-4"><a href="#cb71-4"></a> <span class="fu">return</span> b</span></code></pre></div>
456+</section>
457+<section class="slide level2">
458+
459+<div class="sourceCode" id="cb72"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb72-1"><a href="#cb72-1"></a><span class="kw">type</span> <span class="dt">PricingEnv</span> <span class="ot">=</span> <span class="dt">Reader</span> <span class="dt">Markup</span></span>
460+<span id="cb72-2"><a href="#cb72-2"></a></span>
461+<span id="cb72-3"><a href="#cb72-3"></a><span class="ot">getCoffeePrice ::</span> <span class="dt">Coffee</span> <span class="ot">-&gt;</span> <span class="dt">PricingEnv</span> <span class="dt">Price</span></span>
462+<span id="cb72-4"><a href="#cb72-4"></a><span class="ot">getDiscount ::</span> <span class="dt">Coffee</span> <span class="ot">-&gt;</span> <span class="dt">PricingEnv</span> <span class="dt">Price</span></span>
463+<span id="cb72-5"><a href="#cb72-5"></a><span class="ot">getPayment ::</span> <span class="dt">Price</span> <span class="ot">-&gt;</span> <span class="dt">PricingEnv</span> <span class="dt">Payment</span></span>
464+<span id="cb72-6"><a href="#cb72-6"></a></span>
465+<span id="cb72-7"><a href="#cb72-7"></a><span class="ot">payForCoffee ::</span> <span class="dt">Coffee</span> <span class="ot">-&gt;</span> <span class="dt">PricingEnv</span> <span class="dt">Payment</span></span>
466+<span id="cb72-8"><a href="#cb72-8"></a>payForCoffee coffee <span class="ot">=</span></span>
467+<span id="cb72-9"><a href="#cb72-9"></a> coffee <span class="op">&gt;&gt;=</span> getCoffeePrice <span class="op">&gt;&gt;=</span> \coffeePrice <span class="ot">-&gt;</span></span>
468+<span id="cb72-10"><a href="#cb72-10"></a> coffee <span class="op">&gt;&gt;=</span> getDiscount <span class="op">&gt;&gt;=</span> \discount <span class="ot">-&gt;</span></span>
469+<span id="cb72-11"><a href="#cb72-11"></a> getPayment (coffeePrice <span class="op">-</span> discount)</span></code></pre></div>
470+<div class="sourceCode" id="cb73"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb73-1"><a href="#cb73-1"></a><span class="ot">payForCoffee ::</span> <span class="dt">Coffee</span> <span class="ot">-&gt;</span> <span class="dt">PricingEnv</span> <span class="dt">Payment</span></span>
471+<span id="cb73-2"><a href="#cb73-2"></a>payForCoffee coffee <span class="ot">=</span> <span class="kw">do</span></span>
472+<span id="cb73-3"><a href="#cb73-3"></a> coffeePrice <span class="ot">&lt;-</span> getCoffeePrice coffee</span>
473+<span id="cb73-4"><a href="#cb73-4"></a> discount <span class="ot">&lt;-</span> getDiscount coffee</span>
474+<span id="cb73-5"><a href="#cb73-5"></a> getPayment (coffeePrice <span class="op">-</span> discount)</span></code></pre></div>
475+</section>
476+<section id="let-statement" class="slide level2">
477+<h2>Let statement</h2>
478+<div class="sourceCode" id="cb74"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb74-1"><a href="#cb74-1"></a><span class="ot">payForCoffee ::</span> <span class="dt">Coffee</span> <span class="ot">-&gt;</span> <span class="dt">PricingEnv</span> <span class="dt">Payment</span></span>
479+<span id="cb74-2"><a href="#cb74-2"></a>payForCoffee coffee <span class="ot">=</span> <span class="kw">do</span></span>
480+<span id="cb74-3"><a href="#cb74-3"></a> coffeePrice <span class="ot">&lt;-</span> getCoffeePrice coffee</span>
481+<span id="cb74-4"><a href="#cb74-4"></a> discount <span class="ot">&lt;-</span> getDiscount coffee</span>
482+<span id="cb74-5"><a href="#cb74-5"></a> getPayment (coffeePrice <span class="op">-</span> discount)</span></code></pre></div>
483+<div class="sourceCode" id="cb75"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb75-1"><a href="#cb75-1"></a><span class="ot">payForCoffee ::</span> <span class="dt">Coffee</span> <span class="ot">-&gt;</span> <span class="dt">PricingEnv</span> <span class="dt">Payment</span></span>
484+<span id="cb75-2"><a href="#cb75-2"></a>payForCoffee coffee <span class="ot">=</span> <span class="kw">do</span></span>
485+<span id="cb75-3"><a href="#cb75-3"></a> coffeePrice <span class="ot">&lt;-</span> getCoffeePrice coffee</span>
486+<span id="cb75-4"><a href="#cb75-4"></a> discount <span class="ot">&lt;-</span> getDiscount coffee</span>
487+<span id="cb75-5"><a href="#cb75-5"></a> <span class="kw">let</span> amount <span class="ot">=</span> coffeePrice <span class="op">-</span> discount</span>
488+<span id="cb75-6"><a href="#cb75-6"></a> getPayment amount</span></code></pre></div>
489+</section>
490+<section class="slide level2">
491+
492+<div class="sourceCode" id="cb76"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb76-1"><a href="#cb76-1"></a><span class="kw">type</span> <span class="dt">PricingEnv</span> <span class="ot">=</span> <span class="dt">Reader</span> <span class="dt">Markup</span></span>
493+<span id="cb76-2"><a href="#cb76-2"></a><span class="kw">type</span> <span class="dt">Price</span> <span class="ot">=</span> <span class="dt">Int</span></span>
494+<span id="cb76-3"><a href="#cb76-3"></a></span>
495+<span id="cb76-4"><a href="#cb76-4"></a><span class="kw">data</span> <span class="dt">Coffee</span> <span class="ot">=</span> <span class="dt">Coffee</span> {<span class="ot"> getCoffeePrice ::</span> <span class="dt">Price</span> }</span>
496+<span id="cb76-5"><a href="#cb76-5"></a></span>
497+<span id="cb76-6"><a href="#cb76-6"></a><span class="ot">getCoffeePrice ::</span> <span class="dt">Coffee</span> <span class="ot">-&gt;</span> <span class="dt">PricingEnv</span> <span class="dt">Price</span></span></code></pre></div>
498+<div class="sourceCode" id="cb77"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb77-1"><a href="#cb77-1"></a><span class="kw">data</span> <span class="dt">Reader</span> r a <span class="ot">=</span> <span class="dt">Reader</span> {<span class="ot"> runReader ::</span> r <span class="ot">-&gt;</span> a}</span></code></pre></div>
499+<div class="sourceCode" id="cb78"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb78-1"><a href="#cb78-1"></a><span class="ot">ask ::</span> <span class="dt">Reader</span> r r</span>
500+<span id="cb78-2"><a href="#cb78-2"></a>ask <span class="ot">=</span> <span class="dt">Reader</span> (\r <span class="ot">-&gt;</span> r)</span></code></pre></div>
501+<div class="sourceCode" id="cb79"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb79-1"><a href="#cb79-1"></a><span class="ot">getCoffeePrice ::</span> <span class="dt">Coffee</span> <span class="ot">-&gt;</span> <span class="dt">PricingEnv</span> <span class="dt">Price</span></span>
502+<span id="cb79-2"><a href="#cb79-2"></a>getCoffeePrice coffee <span class="ot">=</span> <span class="kw">do</span></span>
503+<span id="cb79-3"><a href="#cb79-3"></a> markup <span class="ot">&lt;-</span> ask</span>
504+<span id="cb79-4"><a href="#cb79-4"></a> <span class="kw">let</span> coffePrice <span class="ot">=</span> getCoffeePrice coffee</span>
505+<span id="cb79-5"><a href="#cb79-5"></a> <span class="fu">return</span> (coffee <span class="op">+</span> markup)</span></code></pre></div>
506+</section>
507+<section class="slide level2">
508+
509+<div class="sourceCode" id="cb80"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb80-1"><a href="#cb80-1"></a><span class="kw">data</span> <span class="dt">Order</span> <span class="ot">=</span> <span class="dt">Order</span> {<span class="ot"> orderCoffee ::</span> <span class="dt">Coffee</span>,<span class="ot"> orderId ::</span> <span class="dt">Int</span> }</span></code></pre></div>
510+<div class="sourceCode" id="cb81"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb81-1"><a href="#cb81-1"></a><span class="ot">createOrder ::</span> <span class="dt">Coffee</span> <span class="ot">-&gt;</span> <span class="dt">Order</span></span></code></pre></div>
511+<p><span class="fragment">Откуда брать <code>orderId</code>?</span></p>
512+<div class="sourceCode" id="cb82"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb82-1"><a href="#cb82-1"></a><span class="ot">createOrder ::</span> <span class="dt">Coffee</span> <span class="ot">-&gt;</span> <span class="dt">Reader</span> <span class="dt">Int</span> <span class="dt">Order</span></span>
513+<span id="cb82-2"><a href="#cb82-2"></a>createOrder coffee <span class="ot">=</span> <span class="kw">do</span></span>
514+<span id="cb82-3"><a href="#cb82-3"></a> newId <span class="ot">&lt;-</span> ask</span>
515+<span id="cb82-4"><a href="#cb82-4"></a> <span class="fu">return</span> (<span class="dt">Order</span> coffee newId)</span></code></pre></div>
516+<p><span class="fragment">🎉</span></p>
517+<div class="sourceCode" id="cb83"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb83-1"><a href="#cb83-1"></a><span class="ot">createOrders ::</span> [<span class="dt">Coffee</span>] <span class="ot">-&gt;</span> <span class="dt">Reader</span> <span class="dt">Int</span> [<span class="dt">Order</span>]</span></code></pre></div>
518+<div class="sourceCode" id="cb84"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb84-1"><a href="#cb84-1"></a><span class="fu">mapM</span><span class="ot"> ::</span> (<span class="dt">Monad</span> m) <span class="ot">=&gt;</span> (a <span class="ot">-&gt;</span> m b) <span class="ot">-&gt;</span> [a] <span class="ot">-&gt;</span> m [b]</span></code></pre></div>
519+<div class="sourceCode" id="cb85"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb85-1"><a href="#cb85-1"></a>createOrders <span class="ot">=</span> <span class="fu">mapM</span> createOrder</span></code></pre></div>
520+</section>
521+<section class="slide level2">
522+
523+<div class="sourceCode" id="cb86"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb86-1"><a href="#cb86-1"></a><span class="ot">createOrders ::</span> [<span class="dt">Coffee</span>] <span class="ot">-&gt;</span> <span class="dt">Reader</span> <span class="dt">Int</span> [<span class="dt">Order</span>]</span>
524+<span id="cb86-2"><a href="#cb86-2"></a>createOrders <span class="ot">=</span> <span class="fu">mapM</span> createOrder</span></code></pre></div>
525+<p><span class="fragment">Все <code>id</code> будут одинаковые.</span></p>
526+<p><span class="fragment"><code>Reader</code> эквивалентно глобальной <strong>константе</strong>.</span></p>
527+<p><span class="fragment">Айдишники – скорее глобальная <strong>переменная</strong>.</span></p>
528+<p><span class="fragment">– Но у нас же нет переменных!</span></p>
529+<p><span class="fragment">– Да, нет!</span></p>
530+</section>
531+<section id="state" class="slide level2">
532+<h2>State!</h2>
533+<div class="sourceCode" id="cb87"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb87-1"><a href="#cb87-1"></a><span class="kw">data</span> <span class="dt">State</span> s a <span class="ot">=</span> <span class="op">...</span> <span class="co">-- s -- само состояние</span></span>
534+<span id="cb87-2"><a href="#cb87-2"></a></span>
535+<span id="cb87-3"><a href="#cb87-3"></a><span class="ot">get ::</span> <span class="dt">State</span> s s</span>
536+<span id="cb87-4"><a href="#cb87-4"></a><span class="ot">put ::</span> s <span class="ot">-&gt;</span> <span class="dt">State</span> s ()</span></code></pre></div>
537+<div class="sourceCode" id="cb88"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb88-1"><a href="#cb88-1"></a><span class="kw">data</span> <span class="dt">State</span> s a <span class="ot">=</span> <span class="dt">State</span> {<span class="ot"> runState ::</span> s <span class="ot">-&gt;</span> (a, s) }</span>
538+<span id="cb88-2"><a href="#cb88-2"></a></span>
539+<span id="cb88-3"><a href="#cb88-3"></a><span class="ot">get ::</span> <span class="dt">State</span> s s</span>
540+<span id="cb88-4"><a href="#cb88-4"></a>get <span class="ot">=</span> <span class="dt">State</span> (\s <span class="ot">-&gt;</span> (s, s))</span>
541+<span id="cb88-5"><a href="#cb88-5"></a></span>
542+<span id="cb88-6"><a href="#cb88-6"></a><span class="ot">put ::</span> s <span class="ot">-&gt;</span> <span class="dt">State</span> s ()</span>
543+<span id="cb88-7"><a href="#cb88-7"></a>put s <span class="ot">=</span> <span class="dt">State</span> (\_ <span class="ot">-&gt;</span> ((), s))</span></code></pre></div>
544+</section>
545+<section class="slide level2">
546+
547+<div class="sourceCode" id="cb89"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb89-1"><a href="#cb89-1"></a><span class="kw">data</span> <span class="dt">State</span> s a <span class="ot">=</span> <span class="dt">State</span> {<span class="ot"> runState ::</span> s <span class="ot">-&gt;</span> (a, s) }</span></code></pre></div>
548+<div class="sourceCode" id="cb90"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb90-1"><a href="#cb90-1"></a><span class="kw">class</span> <span class="dt">Monad</span> (<span class="dt">State</span> s) <span class="kw">where</span></span>
549+<span id="cb90-2"><a href="#cb90-2"></a> <span class="fu">return</span> x <span class="ot">=</span> <span class="dt">State</span> (\s <span class="ot">-&gt;</span> (x, s))</span>
550+<span id="cb90-3"><a href="#cb90-3"></a></span>
551+<span id="cb90-4"><a href="#cb90-4"></a><span class="ot"> (&gt;&gt;=) ::</span> <span class="dt">State</span> s a <span class="ot">-&gt;</span> (a <span class="ot">-&gt;</span> <span class="dt">State</span> s b) <span class="ot">-&gt;</span> <span class="dt">State</span> s b</span>
552+<span id="cb90-5"><a href="#cb90-5"></a> (<span class="dt">State</span> f) <span class="op">&gt;&gt;=</span> g <span class="ot">=</span> <span class="dt">State</span> go</span>
553+<span id="cb90-6"><a href="#cb90-6"></a> <span class="kw">where</span></span>
554+<span id="cb90-7"><a href="#cb90-7"></a> go s <span class="ot">=</span> runState (g a) s&#39;</span>
555+<span id="cb90-8"><a href="#cb90-8"></a> <span class="kw">where</span></span>
556+<span id="cb90-9"><a href="#cb90-9"></a> (a, s&#39;) <span class="ot">=</span> f s</span></code></pre></div>
557+</section>
558+<section class="slide level2">
559+
560+<h3 id="айдишники">Айдишники!</h3>
561+<div class="sourceCode" id="cb91"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb91-1"><a href="#cb91-1"></a><span class="ot">getNewId ::</span> <span class="dt">State</span> <span class="dt">Int</span> <span class="dt">Int</span></span>
562+<span id="cb91-2"><a href="#cb91-2"></a>getNewId <span class="ot">=</span> <span class="kw">do</span></span>
563+<span id="cb91-3"><a href="#cb91-3"></a> newId <span class="ot">&lt;-</span> get</span>
564+<span id="cb91-4"><a href="#cb91-4"></a> put (newId <span class="op">+</span> <span class="dv">1</span>)</span>
565+<span id="cb91-5"><a href="#cb91-5"></a> <span class="fu">return</span> newId</span></code></pre></div>
566+<p><span class="fragment">– Это какой-то процедурный языке получается!</span></p>
567+<p><span class="fragment">– Лучше!*</span></p>
568+<div class="sourceCode" id="cb92"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb92-1"><a href="#cb92-1"></a><span class="ot">createOrder ::</span> <span class="dt">Coffee</span> <span class="ot">-&gt;</span> <span class="dt">State</span> <span class="dt">Int</span> <span class="dt">Order</span></span>
569+<span id="cb92-2"><a href="#cb92-2"></a>createOrder coffee <span class="ot">=</span> <span class="kw">do</span></span>
570+<span id="cb92-3"><a href="#cb92-3"></a> newId <span class="ot">&lt;-</span> getNewId</span>
571+<span id="cb92-4"><a href="#cb92-4"></a> <span class="fu">return</span> (<span class="dt">Order</span> coffee newId)</span>
572+<span id="cb92-5"><a href="#cb92-5"></a></span>
573+<span id="cb92-6"><a href="#cb92-6"></a><span class="ot">createOrders ::</span> [<span class="dt">Coffee</span>] <span class="ot">-&gt;</span> <span class="dt">State</span> <span class="dt">Int</span> [<span class="dt">Order</span>]</span>
574+<span id="cb92-7"><a href="#cb92-7"></a>createOrders <span class="ot">=</span> <span class="fu">mapM</span> createOrder</span></code></pre></div>
575+</section>
576+<section id="еще-монады" class="slide level2">
577+<h2>Еще монады!</h2>
578+<div class="sourceCode" id="cb93"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb93-1"><a href="#cb93-1"></a><span class="kw">class</span> <span class="dt">Monad</span> [] <span class="kw">where</span></span>
579+<span id="cb93-2"><a href="#cb93-2"></a> <span class="fu">return</span> x <span class="ot">=</span> [x]</span>
580+<span id="cb93-3"><a href="#cb93-3"></a></span>
581+<span id="cb93-4"><a href="#cb93-4"></a><span class="ot"> (&gt;&gt;=) ::</span> [a] <span class="ot">-&gt;</span> (a <span class="ot">-&gt;</span> [b]) <span class="ot">-&gt;</span> [b]</span>
582+<span id="cb93-5"><a href="#cb93-5"></a> [] <span class="op">&gt;&gt;=</span> _ <span class="ot">=</span> []</span>
583+<span id="cb93-6"><a href="#cb93-6"></a> (a <span class="op">:</span> aa) <span class="op">&gt;&gt;=</span> f <span class="ot">=</span> f a <span class="op">&lt;&gt;</span> (a <span class="op">&gt;&gt;=</span> f)</span></code></pre></div>
584+<p><span class="fragment">Контекст недетерменированности (нескольких вариантов)</span></p>
585+<div class="sourceCode" id="cb94"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb94-1"><a href="#cb94-1"></a>grid <span class="ot">=</span> <span class="kw">do</span></span>
586+<span id="cb94-2"><a href="#cb94-2"></a> x <span class="ot">&lt;-</span> [<span class="dv">1</span><span class="op">..</span><span class="dv">5</span>]</span>
587+<span id="cb94-3"><a href="#cb94-3"></a> y <span class="ot">&lt;-</span> [<span class="dv">1</span><span class="op">..</span><span class="dv">5</span>]</span>
588+<span id="cb94-4"><a href="#cb94-4"></a> <span class="fu">return</span> (x, y)</span>
589+<span id="cb94-5"><a href="#cb94-5"></a></span>
590+<span id="cb94-6"><a href="#cb94-6"></a><span class="co">-- [(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)]</span></span></code></pre></div>
591+</section>
592+<section class="slide level2">
593+
594+<p>Тривиальная монада</p>
595+<div class="sourceCode" id="cb95"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb95-1"><a href="#cb95-1"></a><span class="kw">data</span> <span class="dt">Identity</span> a <span class="ot">=</span> <span class="dt">Identity</span> {<span class="ot"> runIdentity ::</span> a }</span>
596+<span id="cb95-2"><a href="#cb95-2"></a></span>
597+<span id="cb95-3"><a href="#cb95-3"></a><span class="kw">class</span> <span class="dt">Monad</span> <span class="dt">Identity</span> <span class="kw">where</span></span>
598+<span id="cb95-4"><a href="#cb95-4"></a> <span class="fu">return</span> x <span class="ot">=</span> <span class="dt">Identity</span> x</span>
599+<span id="cb95-5"><a href="#cb95-5"></a></span>
600+<span id="cb95-6"><a href="#cb95-6"></a><span class="ot"> (&gt;&gt;=) ::</span> <span class="dt">Identity</span> a <span class="ot">-&gt;</span> (a <span class="ot">-&gt;</span> <span class="dt">Identity</span> b) <span class="ot">-&gt;</span> <span class="dt">Identity</span> b</span>
601+<span id="cb95-7"><a href="#cb95-7"></a> (<span class="dt">Identity</span> a) <span class="op">&gt;&gt;=</span> f <span class="ot">=</span> <span class="dt">Identity</span> (f a)</span></code></pre></div>
602+</section>
603+<section class="slide level2">
604+
605+<div class="sourceCode" id="cb96"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb96-1"><a href="#cb96-1"></a><span class="kw">class</span> <span class="dt">Applicative</span> m <span class="ot">=&gt;</span> <span class="dt">Monad</span> m <span class="kw">where</span></span>
606+<span id="cb96-2"><a href="#cb96-2"></a><span class="ot"> return ::</span> a <span class="ot">-&gt;</span> m a</span>
607+<span id="cb96-3"><a href="#cb96-3"></a><span class="ot"> (&gt;&gt;=) ::</span> m a <span class="ot">-&gt;</span> (a <span class="ot">-&gt;</span> m b) <span class="ot">-&gt;</span> m b</span></code></pre></div>
608+<p><span class="fragment">Монада – перегрузка композиции функций.</span></p>
609+<div class="sourceCode" id="cb97"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb97-1"><a href="#cb97-1"></a><span class="kw">class</span> <span class="dt">Functor</span> m <span class="ot">=&gt;</span> <span class="dt">Applicative</span> m <span class="kw">where</span></span>
610+<span id="cb97-2"><a href="#cb97-2"></a><span class="ot"> pure ::</span> a <span class="ot">-&gt;</span> m a</span>
611+<span id="cb97-3"><a href="#cb97-3"></a><span class="ot"> (&lt;*&gt;) ::</span> m (a <span class="ot">-&gt;</span> b) <span class="ot">-&gt;</span> m a <span class="ot">-&gt;</span> m b</span></code></pre></div>
612+<p><span class="fragment">Аппликативный функтор – перегрузка применения функций.</span></p>
613+<p><span class="fragment">– Почему не <code>(a -&gt; b) -&gt; f a -&gt; f b</code>.</span></p>
614+<p><span class="fragment">– Это <code>fmap</code>. (И функции нескольких аргументов)</span></p>
615+</section>
616+<section class="slide level2">
617+
618+<div class="sourceCode" id="cb98"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb98-1"><a href="#cb98-1"></a>(a <span class="ot">-&gt;</span> b) <span class="ot">-&gt;</span> f a <span class="ot">-&gt;</span> f b</span></code></pre></div>
619+<div class="sourceCode" id="cb99"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb99-1"><a href="#cb99-1"></a>(a <span class="ot">-&gt;</span> (b <span class="ot">-&gt;</span> c)) <span class="ot">-&gt;</span> f a <span class="ot">-&gt;</span> f (b <span class="ot">-&gt;</span> c)</span></code></pre></div>
620+<div class="sourceCode" id="cb100"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb100-1"><a href="#cb100-1"></a><span class="ot">getMarkup ::</span> <span class="dt">Env</span> <span class="dt">Markup</span></span>
621+<span id="cb100-2"><a href="#cb100-2"></a><span class="ot">getPrice ::</span> <span class="dt">Env</span> <span class="dt">Price</span></span>
622+<span id="cb100-3"><a href="#cb100-3"></a><span class="ot">getPayment ::</span> <span class="dt">Markup</span> <span class="ot">-&gt;</span> <span class="dt">Price</span> <span class="ot">-&gt;</span> <span class="dt">Payment</span></span></code></pre></div>
623+<div class="sourceCode" id="cb101"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb101-1"><a href="#cb101-1"></a><span class="ot">payment ::</span> <span class="dt">Env</span> <span class="dt">Payment</span></span>
624+<span id="cb101-2"><a href="#cb101-2"></a>payment <span class="ot">=</span> <span class="fu">fmap</span> getPayment getMarkup <span class="op">&lt;*&gt;</span> getPrice</span></code></pre></div>
625+<div class="sourceCode" id="cb102"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb102-1"><a href="#cb102-1"></a>payment <span class="ot">=</span> <span class="fu">fmap</span> getPayment getMarkup <span class="op">&lt;*&gt;</span> getPrice</span>
626+<span id="cb102-2"><a href="#cb102-2"></a><span class="co">-- ^-------------^</span></span>
627+<span id="cb102-3"><a href="#cb102-3"></a><span class="co">-- Env Markup -&gt; Env (Price -&gt; Payment)</span></span></code></pre></div>
628+<div class="sourceCode" id="cb103"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb103-1"><a href="#cb103-1"></a>(<span class="op">&lt;$&gt;</span>) <span class="ot">=</span> <span class="fu">fmap</span></span></code></pre></div>
629+<div class="sourceCode" id="cb104"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb104-1"><a href="#cb104-1"></a>payment <span class="ot">=</span> getPayment <span class="op">&lt;$&gt;</span> getMarkup <span class="op">&lt;*&gt;</span> getPrice</span></code></pre></div>
630+</section>
631+<section class="slide level2">
632+
633+<div class="sourceCode" id="cb105"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb105-1"><a href="#cb105-1"></a><span class="ot">(&lt;*&gt;) ::</span> m (a <span class="ot">-&gt;</span> b) <span class="ot">-&gt;</span> m a <span class="ot">-&gt;</span> m b</span>
634+<span id="cb105-2"><a href="#cb105-2"></a>f <span class="op">&lt;*&gt;</span> ma <span class="ot">=</span> ma <span class="op">&gt;&gt;=</span> \a <span class="ot">-&gt;</span> <span class="fu">fmap</span> (\f&#39; <span class="ot">-&gt;</span> f&#39; a) f</span></code></pre></div>
635+</section></section>
164636 </div>
165637 </div>
166638
3.md+775−1
@@ -3,7 +3,26 @@ theme: superblack
33author: Ilya Kostyuchenko
44---
55
6−### Библиотека про математику
6+# Функциональное программирование
7+
8+---
9+
10+## Напоминалочка
11+
12+```{ .haskell }
13+class Functor f where
14+ fmap :: (a -> b) -> f a -> f b
15+```
16+
17+```{ .haskell .fragment }
18+class Functor f => Alternative f where
19+ (<|>) :: f a -> f a -> f a
20+ empty :: f a
21+```
22+
23+---
24+
25+## Библиотека про математику
726#### (на джаве)
827
928```{ .java .fragment }
@@ -62,6 +81,761 @@ static int add(int x, int y, Logger log) {
6281
6382---
6483
84+```{ .haskell }
85+add :: Int -> Int -> (Int, String)
86+add x y = (x + y, "add " + show x + show y)
87+```
88+
89+[Неудобно программировать]{ .fragment }
90+
91+```{ .haskell .fragment }
92+add :: Int -> Int -> Int
93+times :: Int -> Int -> Int
94+
95+add8AndDouble :: Int -> Int
96+add8AndDouble = times 2 . add 8
97+```
98+
99+---
100+
101+```{ .haskell }
102+add :: Int -> Int -> (Int, String)
103+times :: Int -> Int -> (Int, String)
104+```
105+
106+```{ .haskell .fragment }
107+add8AndDouble :: Int -> (Int, String)
108+add8AndDouble x = (y2, log1 <> log2)
109+ where
110+ (y1, log1) = add 8 x
111+ (y2, log2) = times 2 y1
112+```
113+
114+![](images/ohno.png){height=200px .fragment}
115+
116+```{ .haskell .fragment }
117+add8AndDouble :: Int -> Int
118+add8AndDouble = times 2 . add 8
119+```
120+
121+---
122+
123+```{ .haskell }
124+data WithLog a = WithLog a String
125+```
126+
127+```{ .haskell .fragment }
128+add :: Int -> Int -> WithLog Int
129+times :: Int -> Int -> WithLog Int
130+```
131+
132+```{ .haskell .fragment }
133+add8AndDouble :: Int -> WithLog Int
134+add8AndDouble = times 2 `magic` add 8
135+```
136+
137+```{ .haskell .fragment }
138+magic ::
139+ (Int -> WithLog Int) ->
140+ (Int -> WithLog Int) ->
141+ (Int -> WithLog Int)
142+```
143+
144+```{ .haskell .fragment }
145+magic f g x1 = WithLog x3 (log1 <> log2)
146+ where
147+ (WithLog x2 log1) = g x1
148+ (WithLog x3 log2) = f x2
149+```
150+
151+---
152+
153+```{ .haskell }
154+magic ::
155+ (Int -> WithLog Int) ->
156+ (Int -> WithLog Int) ->
157+ (Int -> WithLog Int)
158+```
159+
160+```{ .haskell .fragment }
161+(<=<) ::
162+ (Int -> WithLog Int) ->
163+ (Int -> WithLog Int) ->
164+ (Int -> WithLog Int)
165+```
166+
167+```{ .haskell .fragment }
168+add8AndDouble :: Int -> WithLog Int
169+add8AndDouble = times 2 <=< add 8
170+```
171+
172+---
173+
174+```{ .haskell }
175+factor :: Int -> WithLog [Int]
176+
177+sum :: [Int] -> WithLog Int
178+```
179+
180+```{ .haskell .fragment }
181+sumFactors :: Int -> WithLog [Int]
182+sumFactors = sum <=< factor -- Doesn't work :(
183+```
184+
185+```{ .haskell .fragment }
186+(<=<) ::
187+ (Int -> WithLog Int) ->
188+ (Int -> WithLog Int) ->
189+ (Int -> WithLog Int)
190+```
191+
192+```{ .haskell .fragment }
193+(<=<) ::
194+ (b -> WithLog c ) ->
195+ (a -> WithLog b ) ->
196+ (a -> WithLog c )
197+```
198+
199+```{ .haskell .fragment }
200+(.) ::
201+ (b -> c ) ->
202+ (a -> b ) ->
203+ (a -> c )
204+```
205+
206+---
207+
208+```{ .haskell }
209+getCoffee :: Order -> Maybe Coffee
210+payForCoffee :: Coffee -> Maybe Payment
211+```
212+
213+```{ .haskell .fragment }
214+buyCoffee :: Order -> Maybe Payment
215+buyCoffee = payForCoffee <=< getCoffee
216+```
217+
218+```{ .haskell .fragment }
219+getCoffee :: Order -> Either CoffeeError Coffee
220+payForCoffee :: Coffee -> Either CoffeeError Payment
221+```
222+
223+```{ .haskell .fragment }
224+buyCoffee :: Order -> Either CoffeeError Payment
225+buyCoffee = payForCoffee <=< getCoffee
226+```
227+
228+```{ .haskell .fragment }
229+(<=<) ::
230+ Composable m =>
231+ (b -> m c) ->
232+ (a -> m b) ->
233+ (a -> m c)
234+```
235+
236+---
237+
238+```{ .haskell }
239+class Applicative m => Monad m where
240+ (<=<) :: (b -> m c) -> (a -> m b) -> (a -> m c)
241+```
242+
243+```{ .haskell .fragment }
244+instance Monad Maybe where
245+ (<=<) f g x = case g x of
246+ Nothing -> Nothing
247+ Just x2 -> f x2
248+```
249+
250+```{ .haskell .fragment }
251+instance Monad (Either e) where
252+ (<=<) f g x = case g x of
253+ Left e -> Left e
254+ Right x2 -> f x2
255+```
256+
65257```{ .haskell .fragment }
258+instance Monad WithLog where
259+ (<=<) f g x = WithLog x3 (log1 <> log2)
260+ where
261+ (WithLog x2 log1) = g x1
262+ (WithLog x3 log2) = f x2
263+```
264+
265+---
266+
267+### Больше операторов!
268+
269+```{ .haskell .fragment }
270+(<=<) :: Monad m => (b -> m c) -> (a -> m b) -> (a -> m c)
271+```
272+```{ .haskell .fragment }
273+buyCoffee :: Order -> Maybe Payment
274+buyCoffee = payForCoffee <=< getCoffee
275+```
276+
277+```{ .haskell .fragment }
278+flip :: (a -> b -> c) -> (b -> a -> c)
279+flip f b a = f a b
280+```
281+
282+```{ .haskell .fragment }
283+(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> (a -> m c)
284+(>=>) = flip (<=<)
285+```
286+
287+```{ .haskell .fragment }
288+buyCoffee = getCoffee >=> payForCoffee
289+```
290+
291+---
292+
293+### Маленькое отступление
294+
295+`f :: () -> a` эквивалентно `f :: a`
296+
297+[Потому что у `()` всего одно значение (`()`), а любая функция для одинаковых аргументов всегда возвращает одинаковые значения (потому что по-другому невозможно).]{ .fragment }
298+
299+---
300+
301+```{ .haskell }
302+(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> (a -> m c)
303+```
304+
305+```{ .haskell .fragment }
306+(>>=) :: Monad m => m b -> (b -> m c) -> m c
307+```
308+
309+```{ .haskell .fragment }
310+buyCoffee :: Order -> Maybe Payment
311+buyCoffee order = getCoffee order >>= payForCoffee
312+```
313+
314+```{ .haskell .fragment }
315+maybeBuyCoffee :: Myabe Order -> Maybe Payment
316+maybeBuyCoffee order = order >>= buyCoffee
317+```
318+
319+```{ .haskell .fragment }
320+(>>=) :: Monad m => m b -> (b -> m c) -> m c
321+```
322+
323+```{ .haskell .fragment }
324+(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> (a -> m c)
325+```
326+
327+```{ .haskell .fragment }
328+ (() -> m b) -> (b -> m c) -> (() -> m c)
329+```
330+```{ .haskell .fragment }
331+ m b -> (b -> m c) -> m c
332+```
333+
334+---
335+
336+```{ .haskell }
337+(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> (a -> m c)
338+```
339+
340+```{ .haskell }
341+(>>=) :: Monad m => m b -> (b -> m c) -> m c
342+(>>=) mb f = ( (\() -> mb) >=> f ) ()
343+```
344+
345+```{ .haskell .fragment }
346+(>>=) mb f = ( (\() -> mb) >=> f ) ()
347+-- () -> m b |
348+-- b -> m c
349+--
350+-- ^-------------------^
351+-- () -> m c
352+```
353+
354+---
355+
356+### Время раскрыть ложь
357+
358+```{ .haskell }
359+class Applicative m => Monad m where
360+ (>>=) :: m a -> (a -> m b) -> m b
361+ return :: a -> m a
362+```
363+
364+```{ .haskell .fragment }
365+ -- Law:
366+ ma :: m a
367+ (ma >>= return) == ma
368+```
369+
370+```{ .haskell .fragment }
371+ -- Law:
372+ f :: a -> m b
373+ (f >=> return) == f
374+```
375+
376+[`return` -- нейтральный элемент по `>=>`]{.fragment}
377+
378+```{ .haskell .fragment }
379+ -- Law:
380+ x :: a
381+ f :: a -> m b
382+ (return x >>= f) == f x
383+```
384+
385+---
386+
387+```{ .haskell }
388+instance Monad Maybe where
389+ ma >>= f = case ma of
390+ Nothing -> Nothing
391+ Just a -> f a
392+
393+ return a = Just a
394+```
395+
396+```{ .haskell .fragment }
397+instance Monad (Either e) where
398+ ma >>= f = case ma of
399+ Left e -> Left e
400+ Right a -> f a
401+
402+ return a = Right a
403+```
404+
405+```{ .haskell .fragment }
406+instance Monad WithLog where
407+ (WithLog a log1) >>= f = WithLog b (log1 <> log2)
408+ where
409+ WithLog b log2 = f a
410+
411+ return a = WithLog a ""
412+```
413+
414+---
415+
416+## More Monads!
417+
418+```{ .haskell }
419+type Markup = Int
420+
421+getCoffee :: Markup -> Order -> Coffee
422+payForCoffee :: Markup -> Coffee -> Payment
423+
424+buyCoffee :: Markup -> Order -> Payment
425+buyCoffee markup = payForCoffee markup . getCoffee markup
426+```
427+
428+```{ .haskell .fragment }
429+data Reader r a = Reader
430+ { runReader :: r -> a
431+ }
432+```
433+
434+[`r` -- то, что у нас в "окружении".]{ .fragment }
435+
436+```{ .haskell .fragment }
437+getCoffee :: Order -> Reader Markup Coffee
438+payForCoffee :: Coffee -> Reader Markup Payment
439+```
440+
441+```{ .haskell .fragment }
442+payment :: Payment
443+payment = runReader (payForCoffee coffee) markup
444+```
66445
446+---
447+
448+```{ .haskell }
449+data Reader r a = Reader { runReader :: r -> a }
450+
451+getCoffee :: Order -> Reader Markup Coffee
452+payForCoffee :: Coffee -> Reader Markup Payment
453+```
454+
455+```{ .haskell .fragment }
456+buyCoffee :: Order -> Reader Markup Payment
457+buyCoffee = payForCoffee <=< getCoffee
458+```
459+
460+
461+```{ .haskell .fragment }
462+type PricingEnv = Reader Markup
463+```
464+
465+```{ .haskell .fragment }
466+getCoffee :: Order -> PricingEnv Coffee
467+payForCoffee :: Coffee -> PricingEnv Payment
468+buyCoffee :: Order -> PricingEnv Payment
469+buyCoffee = payForCoffee <=< getCoffee
470+```
471+
472+---
473+
474+```{ .haskell }
475+data Reader r a = Reader
476+ { runReader :: r -> a
477+ }
478+
479+instance Monad (Reader r) where
480+ return a = Reader (\_ -> a)
481+
482+ (Reader g) >>= f = Reader ( \r -> runReader (f (g r)) r )
483+```
484+
485+```{ .haskell .fragment}
486+ (>>=) :: Reader r a -> (a -> Reader r b) -> Reader r b
487+
488+ (Reader g) >>= f = Reader ( \r -> runReader (f (g r)) r )
489+-- ^---^
490+-- a
491+-- ^-------^
492+-- Reader r b
493+-- ^-----------------^
494+-- r -> b
495+```
496+
497+---
498+
499+```{ .haskell }
500+type Price = Int
501+getCoffeePrice :: Markup -> Coffee -> Price
502+getDiscount :: Markup -> Coffee -> Price
503+getPayment :: Markup -> Price -> Payment
504+
505+payForCoffee :: Markup -> Coffee -> Payment
506+payForCoffee markup coffee = getPayment markup amount
507+ where
508+ coffeePrice = getCoffeePrice markup coffee
509+ discount = getDiscount markup coffee
510+ amount = coffeePrice - discount
511+```
512+
513+```{ .haskell .fragment }
514+type PricingEnv = Reader Markup
515+
516+getCoffeePrice :: Coffee -> PricingEnv Price
517+getDiscount :: Coffee -> PricingEnv Price
518+getPayment :: Price -> PricingEnv Payment
519+
520+payForCoffee :: Coffee -> PricingEnv Payment
521+payForCoffee coffee =
522+ coffee >>= getCoffeePrice >>= \coffeePrice ->
523+ coffee >>= getDiscount >>= \discount ->
524+ getPayment (coffeePrice - discount)
525+```
526+
527+---
528+
529+## Do syntax
530+
531+```{ .haskell .fragment }
532+bar :: Reader r a
533+qux :: a -> Reader r b
534+
535+foo :: Reader r b
536+foo = bar >>= \a -> qux a
537+```
538+
539+```{ .haskell .fragment }
540+foo = do
541+ a <- bar
542+ qux a
543+```
544+
545+```{ .haskell .fragment }
546+foo = do
547+ a <- bar
548+ b <- qux a
549+ return b
550+```
551+
552+---
553+
554+```{ .haskell }
555+type PricingEnv = Reader Markup
556+
557+getCoffeePrice :: Coffee -> PricingEnv Price
558+getDiscount :: Coffee -> PricingEnv Price
559+getPayment :: Price -> PricingEnv Payment
560+
561+payForCoffee :: Coffee -> PricingEnv Payment
562+payForCoffee coffee =
563+ coffee >>= getCoffeePrice >>= \coffeePrice ->
564+ coffee >>= getDiscount >>= \discount ->
565+ getPayment (coffeePrice - discount)
566+```
567+
568+```{ .haskell .fragment }
569+payForCoffee :: Coffee -> PricingEnv Payment
570+payForCoffee coffee = do
571+ coffeePrice <- getCoffeePrice coffee
572+ discount <- getDiscount coffee
573+ getPayment (coffeePrice - discount)
574+```
575+
576+---
577+
578+## Let statement
579+
580+```{ .haskell }
581+payForCoffee :: Coffee -> PricingEnv Payment
582+payForCoffee coffee = do
583+ coffeePrice <- getCoffeePrice coffee
584+ discount <- getDiscount coffee
585+ getPayment (coffeePrice - discount)
586+```
587+
588+
589+```{ .haskell .fragment }
590+payForCoffee :: Coffee -> PricingEnv Payment
591+payForCoffee coffee = do
592+ coffeePrice <- getCoffeePrice coffee
593+ discount <- getDiscount coffee
594+ let amount = coffeePrice - discount
595+ getPayment amount
596+```
597+
598+---
599+
600+```{ .haskell }
601+type PricingEnv = Reader Markup
602+type Price = Int
603+
604+data Coffee = Coffee { getCoffeePrice :: Price }
605+
606+getCoffeePrice :: Coffee -> PricingEnv Price
607+```
608+
609+```{ .haskell .fragment }
610+data Reader r a = Reader { runReader :: r -> a}
611+```
612+
613+```{ .haskell .fragment }
614+ask :: Reader r r
615+ask = Reader (\r -> r)
616+```
617+
618+```{ .haskell .fragment }
619+getCoffeePrice :: Coffee -> PricingEnv Price
620+getCoffeePrice coffee = do
621+ markup <- ask
622+ let coffePrice = getCoffeePrice coffee
623+ return (coffee + markup)
624+```
625+
626+---
627+
628+```{ .haskell }
629+data Order = Order { orderCoffee :: Coffee, orderId :: Int }
630+```
631+
632+```{ .haskell .fragment }
633+createOrder :: Coffee -> Order
634+```
635+
636+[Откуда брать `orderId`?]{ .fragment }
637+
638+```{ .haskell .fragment }
639+createOrder :: Coffee -> Reader Int Order
640+createOrder coffee = do
641+ newId <- ask
642+ return (Order coffee newId)
643+```
644+
645+[🎉]{ .fragment }
646+
647+```{ .haskell .fragment }
648+createOrders :: [Coffee] -> Reader Int [Order]
649+```
650+
651+```{ .haskell .fragment }
652+mapM :: (Monad m) => (a -> m b) -> [a] -> m [b]
653+```
654+
655+```{ .haskell .fragment }
656+createOrders = mapM createOrder
657+```
658+
659+---
660+
661+```{ .haskell }
662+createOrders :: [Coffee] -> Reader Int [Order]
663+createOrders = mapM createOrder
664+```
665+
666+[Все `id` будут одинаковые.]{ .fragment }
667+
668+[`Reader` эквивалентно глобальной **константе**.]{ .fragment }
669+
670+[Айдишники -- скорее глобальная **переменная**.]{ .fragment }
671+
672+[-- Но у нас же нет переменных!]{ .fragment }
673+
674+[-- Да, нет!]{ .fragment }
675+
676+---
677+
678+## State!
679+
680+```{ .haskell .fragment }
681+data State s a = ... -- s -- само состояние
682+
683+get :: State s s
684+put :: s -> State s ()
685+```
686+
687+```{ .haskell .fragment }
688+data State s a = State { runState :: s -> (a, s) }
689+
690+get :: State s s
691+get = State (\s -> (s, s))
692+
693+put :: s -> State s ()
694+put s = State (\_ -> ((), s))
695+```
696+
697+---
698+
699+```{ .haskell }
700+data State s a = State { runState :: s -> (a, s) }
701+```
702+
703+```{ .haskell .fragment }
704+class Monad (State s) where
705+ return x = State (\s -> (x, s))
706+
707+ (>>=) :: State s a -> (a -> State s b) -> State s b
708+ (State f) >>= g = State go
709+ where
710+ go s = runState (g a) s'
711+ where
712+ (a, s') = f s
713+```
714+
715+---
716+
717+### Айдишники!
718+
719+```{ .haskell .fragment }
720+getNewId :: State Int Int
721+getNewId = do
722+ newId <- get
723+ put (newId + 1)
724+ return newId
725+```
726+
727+[-- Это какой-то процедурный языке получается!]{ .fragment }
728+
729+[-- Лучше!*]{ .fragment }
730+
731+```{ .haskell .fragment }
732+createOrder :: Coffee -> State Int Order
733+createOrder coffee = do
734+ newId <- getNewId
735+ return (Order coffee newId)
736+
737+createOrders :: [Coffee] -> State Int [Order]
738+createOrders = mapM createOrder
739+```
740+
741+---
742+
743+## Еще монады!
744+
745+```{ .haskell .fragment }
746+class Monad [] where
747+ return x = [x]
748+
749+ (>>=) :: [a] -> (a -> [b]) -> [b]
750+ [] >>= _ = []
751+ (a : aa) >>= f = f a <> (a >>= f)
752+```
753+
754+[Контекст недетерменированности (нескольких вариантов)]{ .fragment }
755+
756+```{ .haskell .fragment }
757+grid = do
758+ x <- [1..5]
759+ y <- [1..5]
760+ return (x, y)
761+
762+-- [(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)]
763+```
764+
765+---
766+
767+Тривиальная монада
768+
769+```{ .haskell .fragment }
770+data Identity a = Identity { runIdentity :: a }
771+
772+class Monad Identity where
773+ return x = Identity x
774+
775+ (>>=) :: Identity a -> (a -> Identity b) -> Identity b
776+ (Identity a) >>= f = Identity (f a)
777+```
778+
779+---
780+
781+```{ .haskell }
782+class Applicative m => Monad m where
783+ return :: a -> m a
784+ (>>=) :: m a -> (a -> m b) -> m b
785+```
786+
787+[Монада -- перегрузка композиции функций.]{.fragment }
788+
789+```{ .haskell .fragment }
790+class Functor m => Applicative m where
791+ pure :: a -> m a
792+ (<*>) :: m (a -> b) -> m a -> m b
793+```
794+
795+[Аппликативный функтор -- перегрузка применения функций.]{.fragment }
796+
797+[-- Почему не `(a -> b) -> f a -> f b`.]{.fragment }
798+
799+[-- Это `fmap`. (И функции нескольких аргументов)]{.fragment }
800+
801+---
802+
803+```{ .haskell }
804+(a -> b) -> f a -> f b
805+```
806+
807+```{ .haskell .fragment }
808+(a -> (b -> c)) -> f a -> f (b -> c)
809+```
810+
811+```{ .haskell .fragment }
812+getMarkup :: Env Markup
813+getPrice :: Env Price
814+getPayment :: Markup -> Price -> Payment
815+```
816+
817+```{ .haskell .fragment }
818+payment :: Env Payment
819+payment = fmap getPayment getMarkup <*> getPrice
820+```
821+
822+```{ .haskell .fragment }
823+payment = fmap getPayment getMarkup <*> getPrice
824+-- ^-------------^
825+-- Env Markup -> Env (Price -> Payment)
826+```
827+
828+```{ .haskell .fragment }
829+(<$>) = fmap
830+```
831+
832+```{ .haskell .fragment }
833+payment = getPayment <$> getMarkup <*> getPrice
834+```
835+
836+---
837+
838+```{ .haskell .fragment }
839+(<*>) :: m (a -> b) -> m a -> m b
840+f <*> ma = ma >>= \a -> fmap (\f' -> f' a) f
67841```
README.md+11−4
@@ -1,4 +1,4 @@
1−## Lecures
1+## Lectures
22
33- Lecture 1 [[md](https://github.com/ikoHSE/sc-lectures/blob/master/1.md)] [[web](https://ikohse.github.io/sc-lectures/1.html)] [[Seminar](https://github.com/ikoHSE/sc-task-1)]
44 - [Functions](http://learnyouahaskell.com/starting-out#babys-first-functions)
@@ -18,12 +18,19 @@
1818 - [Typeclass instances](http://learnyouahaskell.com/making-our-own-types-and-typeclasses#typeclasses-102)
1919 - [Case](http://learnyouahaskell.com/syntax-in-functions#case-expressions)
2020 - [Polymorphic typeclass instances](http://learnyouahaskell.com/making-our-own-types-and-typeclasses#typeclasses-102)
21− - [`Monoid` typeclass](https://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Monoid.html#t:Monoid)
22− - [`fold`](https://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Foldable.html#v:fold)
21+ - [`Monoid` typeclass](http://learnyouahaskell.com/functors-applicative-functors-and-monoids#monoids)
22+ - [`fold`](http://learnyouahaskell.com/higher-order-functions#folds)
2323 - [Deriving](http://learnyouahaskell.com/making-our-own-types-and-typeclasses#derived-instances)
2424 - [Type synonyms](http://learnyouahaskell.com/making-our-own-types-and-typeclasses#type-synonyms)
2525 - Error handling
2626 - [`Maybe`](https://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Maybe.html#t:Maybe)
2727 - [`Either`](https://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Either.html#t:Either)
28− - [`Functor`](https://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Functor.html#t:Functor)
28+ - [`Functor`](http://learnyouahaskell.com/functors-applicative-functors-and-monoids#functors-redux)
2929 - [`Alternative`](https://hackage.haskell.org/package/base-4.12.0.0/docs/Control-Applicative.html#t:Alternative)
30+- Lecture 2 [[md](https://github.com/ikoHSE/sc-lectures/blob/master/3.md)] [[web](https://ikohse.github.io/sc-lectures/3.html)] [[Seminar](https://github.com/ikoHSE/sc-task-3)]
31+ - [`Monad`](http://www.learnyouahaskell.com/a-fistful-of-monads)
32+ - [`Reader`](http://learnyouahaskell.com/for-a-few-monads-more#reader)
33+ - [`do` syntax](https://en.wikibooks.org/wiki/Haskell/do_notation#Translating_the_bind_operator)
34+ - [`mapM`](https://hackage.haskell.org/package/base-4.12.0.0/docs/Control-Monad.html#v:mapM)
35+ - [`State`](https://wiki.haskell.org/State_Monad)
36+ - [`Applicative`](http://learnyouahaskell.com/functors-applicative-functors-and-monoids#applicative-functors)
build.sh+1−1
@@ -5,6 +5,6 @@ do
55 base=$(basename $file .md)
66 if [ $base != "README" ]
77 then
8− pandoc -i $file -t revealjs -s --highlight-style=breezeDark --include-in-header=style.html >"$base.html"
8+ pandoc -i $file -t revealjs -s --highlight-style=breezeDark --include-in-header=style.html --highlight-style=highlight.theme >"$base.html"
99 fi
1010done
highlight.themenew file+225
@@ -0,0 +1,225 @@
1+{
2+ "text-color": "#ffffff",
3+ "background-color": "#000000",
4+ "line-number-color": "#7a7c7d",
5+ "line-number-background-color": "#232629",
6+ "text-styles": {
7+ "Other": {
8+ "text-color": "#86e9b0",
9+ "background-color": null,
10+ "bold": false,
11+ "italic": false,
12+ "underline": false
13+ },
14+ "Attribute": {
15+ "text-color": "#94cbf0",
16+ "background-color": null,
17+ "bold": false,
18+ "italic": false,
19+ "underline": false
20+ },
21+ "SpecialString": {
22+ "text-color": "#ff909b",
23+ "background-color": null,
24+ "bold": false,
25+ "italic": false,
26+ "underline": false
27+ },
28+ "Annotation": {
29+ "text-color": "#86d5a4",
30+ "background-color": null,
31+ "bold": false,
32+ "italic": false,
33+ "underline": false
34+ },
35+ "RegionMarker": {
36+ "text-color": "#83c7f4",
37+ "background-color": "#153042",
38+ "bold": false,
39+ "italic": false,
40+ "underline": false
41+ },
42+ "Function": {
43+ "text-color": "#d487f4",
44+ "background-color": null,
45+ "bold": false,
46+ "italic": false,
47+ "underline": false
48+ },
49+ "String": {
50+ "text-color": "#ff9f9f",
51+ "background-color": null,
52+ "bold": false,
53+ "italic": false,
54+ "underline": false
55+ },
56+ "ControlFlow": {
57+ "text-color": "#ffd998",
58+ "background-color": null,
59+ "bold": true,
60+ "italic": false,
61+ "underline": false
62+ },
63+ "Operator": {
64+ "text-color": "#ececde",
65+ "background-color": null,
66+ "bold": false,
67+ "italic": false,
68+ "underline": false
69+ },
70+ "Error": {
71+ "text-color": "#e9848e",
72+ "background-color": null,
73+ "bold": false,
74+ "italic": false,
75+ "underline": true
76+ },
77+ "Normal": {
78+ "text-color": "#ffffff",
79+ "background-color": null,
80+ "bold": false,
81+ "italic": false,
82+ "underline": false
83+ },
84+ "BaseN": {
85+ "text-color": "#ffb06a",
86+ "background-color": null,
87+ "bold": false,
88+ "italic": false,
89+ "underline": false
90+ },
91+ "Alert": {
92+ "text-color": "#95da4c",
93+ "background-color": "#4d1f24",
94+ "bold": true,
95+ "italic": false,
96+ "underline": false
97+ },
98+ "Variable": {
99+ "text-color": "#56d4d4",
100+ "background-color": null,
101+ "bold": false,
102+ "italic": false,
103+ "underline": false
104+ },
105+ "BuiltIn": {
106+ "text-color": "#bdd1d3",
107+ "background-color": null,
108+ "bold": false,
109+ "italic": false,
110+ "underline": false
111+ },
112+ "Extension": {
113+ "text-color": "#96d5ff",
114+ "background-color": null,
115+ "bold": true,
116+ "italic": false,
117+ "underline": false
118+ },
119+ "Preprocessor": {
120+ "text-color": "#62e298",
121+ "background-color": null,
122+ "bold": false,
123+ "italic": false,
124+ "underline": false
125+ },
126+ "Information": {
127+ "text-color": "#f6b176",
128+ "background-color": null,
129+ "bold": false,
130+ "italic": false,
131+ "underline": false
132+ },
133+ "VerbatimString": {
134+ "text-color": "#eca2a9",
135+ "background-color": null,
136+ "bold": false,
137+ "italic": false,
138+ "underline": false
139+ },
140+ "Warning": {
141+ "text-color": "#eca2a9",
142+ "background-color": null,
143+ "bold": false,
144+ "italic": false,
145+ "underline": false
146+ },
147+ "Documentation": {
148+ "text-color": "#a43340",
149+ "background-color": null,
150+ "bold": false,
151+ "italic": false,
152+ "underline": false
153+ },
154+ "Import": {
155+ "text-color": "#76e8a6",
156+ "background-color": null,
157+ "bold": false,
158+ "italic": false,
159+ "underline": false
160+ },
161+ "Char": {
162+ "text-color": "#a4e0ff",
163+ "background-color": null,
164+ "bold": false,
165+ "italic": false,
166+ "underline": false
167+ },
168+ "DataType": {
169+ "text-color": "#7cc0ec",
170+ "background-color": null,
171+ "bold": false,
172+ "italic": false,
173+ "underline": false
174+ },
175+ "Float": {
176+ "text-color": "#fdae67",
177+ "background-color": null,
178+ "bold": false,
179+ "italic": false,
180+ "underline": false
181+ },
182+ "Comment": {
183+ "text-color": "#a1a6a8",
184+ "background-color": null,
185+ "bold": false,
186+ "italic": false,
187+ "underline": false
188+ },
189+ "CommentVar": {
190+ "text-color": "#b6c8c9",
191+ "background-color": null,
192+ "bold": false,
193+ "italic": false,
194+ "underline": false
195+ },
196+ "Constant": {
197+ "text-color": "#73d9d9",
198+ "background-color": null,
199+ "bold": true,
200+ "italic": false,
201+ "underline": false
202+ },
203+ "SpecialChar": {
204+ "text-color": "#80ccf4",
205+ "background-color": null,
206+ "bold": false,
207+ "italic": false,
208+ "underline": false
209+ },
210+ "DecVal": {
211+ "text-color": "#f6b77f",
212+ "background-color": null,
213+ "bold": false,
214+ "italic": false,
215+ "underline": false
216+ },
217+ "Keyword": {
218+ "text-color": "#ebebc9",
219+ "background-color": null,
220+ "bold": true,
221+ "italic": false,
222+ "underline": false
223+ }
224+ }
225+}
reveal.js/css/theme/source/superblack.scss+2−2
@@ -56,10 +56,10 @@ section.has-light-background {
5656}
5757
5858.reveal code {
59− background-color: #333;
59+ background-color: rgb(31, 31, 31);
6060 border-radius: 13px;
6161 padding: 0px 4px 0px 4px;
6262 border-width: 2px;
6363 border-style: solid;
64− border-color: #777;
64+ border-color: rgb(107, 107, 107);
6565}
reveal.js/css/theme/superblack.css+2−2
@@ -277,9 +277,9 @@ body {
277277 background-color: #222; }
278278
279279.reveal code {
280− background-color: #333;
280+ background-color: #1f1f1f;
281281 border-radius: 13px;
282282 padding: 0px 4px 0px 4px;
283283 border-width: 2px;
284284 border-style: solid;
285− border-color: #777; }
285+ border-color: #6b6b6b; }