git.iko.soy/ikoHSE/sc-lectures
on master help sign in
674 lines 83 kB history raw
1<!DOCTYPE html>
2<html>
3<head>
4 <meta charset="utf-8">
5 <meta name="generator" content="pandoc">
6 <meta name="author" content="Ilya Kostyuchenko">
7 <title>3</title>
8 <meta name="apple-mobile-web-app-capable" content="yes">
9 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
10 <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, minimal-ui">
11 <link rel="stylesheet" href="reveal.js/css/reset.css">
12 <link rel="stylesheet" href="reveal.js/css/reveal.css">
13 <style>
14 code{white-space: pre-wrap;}
15 span.smallcaps{font-variant: small-caps;}
16 span.underline{text-decoration: underline;}
17 div.column{display: inline-block; vertical-align: top; width: 50%;}
18 div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
19 ul.task-list{list-style: none;}
20 pre > code.sourceCode { white-space: pre; position: relative; }
21 pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
22 pre > code.sourceCode > span:empty { height: 1.2em; }
23 code.sourceCode > span { color: inherit; text-decoration: inherit; }
24 div.sourceCode { margin: 1em 0; }
25 pre.sourceCode { margin: 0; }
26 @media screen {
27 div.sourceCode { overflow: auto; }
28 }
29 @media print {
30 pre > code.sourceCode { white-space: pre-wrap; }
31 pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
32 }
33 pre.numberSource code
34 { counter-reset: source-line 0; }
35 pre.numberSource code > span
36 { position: relative; left: -4em; counter-increment: source-line; }
37 pre.numberSource code > span > a:first-child::before
38 { content: counter(source-line);
39 position: relative; left: -1em; text-align: right; vertical-align: baseline;
40 border: none; display: inline-block;
41 -webkit-touch-callout: none; -webkit-user-select: none;
42 -khtml-user-select: none; -moz-user-select: none;
43 -ms-user-select: none; user-select: none;
44 padding: 0 4px; width: 4em;
45 background-color: #232629;
46 color: #7a7c7d;
47 }
48 pre.numberSource { margin-left: 3em; border-left: 1px solid #7a7c7d; padding-left: 4px; }
49 div.sourceCode
50 { color: #ffffff; background-color: #000000; }
51 @media screen {
52 pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
53 }
54 code span. { color: #ffffff; } /* Normal */
55 code span.al { color: #95da4c; background-color: #4d1f24; font-weight: bold; } /* Alert */
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 */
65 code span.do { color: #a43340; } /* Documentation */
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 */
85 </style>
86 <link rel="stylesheet" href="reveal.js/css/theme/superblack.css" id="theme">
87 <!-- Printing and PDF exports -->
88 <script>
89 var link = document.createElement( 'link' );
90 link.rel = 'stylesheet';
91 link.type = 'text/css';
92 link.href = window.location.search.match( /print-pdf/gi ) ? 'reveal.js/css/print/pdf.css' : 'reveal.js/css/print/paper.css';
93 document.getElementsByTagName( 'head' )[0].appendChild( link );
94 </script>
95 <!--[if lt IE 9]>
96 <script src="reveal.js/lib/js/html5shiv.js"></script>
97 <![endif]-->
98 <style>
99 div.sourceCode {
100 background-color: transparent;
101 overflow: auto;
102 margin: 0em;
103 }
105 pre.sourceCode {
106 margin: 8px auto;
107 }
108 </style>
109</head>
110<body>
111 <div class="reveal">
112 <div class="slides">
115<section>
116<section id="функциональное-программирование" class="title-slide slide level1">
117<h1>Функциональное программирование</h1>
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>
130<h4 id="на-джаве">(на джаве)</h4>
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>
134<p><span class="fragment">“Нам для сертификации надо чтобы каждая функция логировала свой вызов.”</span></p>
135</section>
136<section class="slide level2">
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>
143<ol type="1">
144<li class="fragment">Неявная зависимость</li>
145<li class="fragment">Невозможно рефакторить</li>
146<li class="fragment">Почему функция для складывания чисел умеет логи?</li>
147</ol>
148</section>
149<section class="slide level2">
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>
155<ol type="1">
156<li class="fragment"><del>Неявная зависимость</del></li>
157<li class="fragment"><del>Невозможно рефакторить</del></li>
158<li class="fragment">Неудобно программировать</li>
159<li class="fragment">Почему функция для складывания чисел умеет логи?</li>
160</ol>
161</section>
162<section class="slide level2">
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>
169<ol type="1">
170<li class="fragment"><del>Неявная зависимость</del></li>
171<li class="fragment"><del>Невозможно рефакторить</del></li>
172<li class="fragment">Неудобно программировать</li>
173<li class="fragment"><del>Почему функция для складывания чисел умеет логи?</del></li>
174</ol>
175</section>
176<section class="slide level2">
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">
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">
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">
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">
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">
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">
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 x</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">
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">
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">
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">Maybe</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 mOrder <span class="ot">=</span> mOrder <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">
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 bmc <span class="ot">=</span> ( (\() <span class="ot">-&gt;</span> mb) <span class="op">&gt;=&gt;</span> bmc ) ()</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 bmc <span class="ot">=</span> ( (\() <span class="ot">-&gt;</span> mb) <span class="op">&gt;=&gt;</span> bmc ) ()</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">
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">
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>
364</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</section>
379<section class="slide level2">
381<div class="sourceCode" id="cb59"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb59-1"><a href="#cb59-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>
382<span id="cb59-2"><a href="#cb59-2"></a></span>
383<span id="cb59-3"><a href="#cb59-3"></a><span class="ot">getCoffee ::</span> <span class="dt">Order</span> <span class="ot">-&gt;</span> <span class="dt">Markup</span> <span class="ot">-&gt;</span> <span class="dt">Coffee</span></span>
384<span id="cb59-4"><a href="#cb59-4"></a><span class="ot">payForCoffee ::</span> <span class="dt">Coffee</span> <span class="ot">-&gt;</span> <span class="dt">Markup</span> <span class="ot">-&gt;</span> <span class="dt">Payment</span></span></code></pre></div>
385<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">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>
386<span id="cb60-2"><a href="#cb60-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>
387<div class="sourceCode" id="cb61"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb61-1"><a href="#cb61-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>
388<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">getCoffee ::</span> <span class="dt">Order</span> <span class="ot">-&gt;</span> <span class="dt">PricingEnv</span> <span class="dt">Coffee</span></span>
389<span id="cb62-2"><a href="#cb62-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></code></pre></div>
390<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="ot">buyCoffee ::</span> <span class="dt">Order</span> <span class="ot">-&gt;</span> <span class="dt">PricingEnv</span> <span class="dt">Payment</span></span>
391<span id="cb63-2"><a href="#cb63-2"></a>buyCoffee <span class="ot">=</span> payForCoffee <span class="op">&lt;=&lt;</span> getCoffee</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">payment ::</span> <span class="dt">Payment</span></span>
393<span id="cb64-2"><a href="#cb64-2"></a>payment <span class="ot">=</span> runReader (buyCoffee order) markup</span></code></pre></div>
394</section>
395<section class="slide level2">
397<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>
398<span id="cb65-2"><a href="#cb65-2"></a> {<span class="ot"> runReader ::</span> r <span class="ot">-&gt;</span> a</span>
399<span id="cb65-3"><a href="#cb65-3"></a> }</span>
400<span id="cb65-4"><a href="#cb65-4"></a></span>
401<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>
402<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>
403<span id="cb65-7"><a href="#cb65-7"></a></span>
404<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>
405<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>
406<span id="cb66-2"><a href="#cb66-2"></a></span>
407<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>
408<span id="cb66-4"><a href="#cb66-4"></a><span class="co">-- ^---^</span></span>
409<span id="cb66-5"><a href="#cb66-5"></a><span class="co">-- a</span></span>
410<span id="cb66-6"><a href="#cb66-6"></a><span class="co">-- ^-------^</span></span>
411<span id="cb66-7"><a href="#cb66-7"></a><span class="co">-- Reader r b</span></span>
412<span id="cb66-8"><a href="#cb66-8"></a><span class="co">-- ^-----------------^</span></span>
413<span id="cb66-9"><a href="#cb66-9"></a><span class="co">-- r -&gt; b</span></span></code></pre></div>
414</section>
415<section class="slide level2">
417<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>
418<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>
419<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>
420<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>
421<span id="cb67-5"><a href="#cb67-5"></a></span>
422<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>
423<span id="cb67-7"><a href="#cb67-7"></a>payForCoffee markup coffee <span class="ot">=</span> getPayment markup amount</span>
424<span id="cb67-8"><a href="#cb67-8"></a> <span class="kw">where</span></span>
425<span id="cb67-9"><a href="#cb67-9"></a> coffeePrice <span class="ot">=</span> getCoffeePrice markup coffee</span>
426<span id="cb67-10"><a href="#cb67-10"></a> discount <span class="ot">=</span> getDiscount markup coffee</span>
427<span id="cb67-11"><a href="#cb67-11"></a> amount <span class="ot">=</span> coffeePrice <span class="op">-</span> discount</span></code></pre></div>
428<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>
429<span id="cb68-2"><a href="#cb68-2"></a></span>
430<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>
431<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>
432<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>
433<span id="cb68-6"><a href="#cb68-6"></a></span>
434<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>
435<span id="cb68-8"><a href="#cb68-8"></a>payForCoffee coffee <span class="ot">=</span></span>
436<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>
437<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>
438<span id="cb68-11"><a href="#cb68-11"></a> getPayment (coffeePrice <span class="op">-</span> discount)</span></code></pre></div>
439</section>
440<section id="do-syntax" class="slide level2">
441<h2>Do syntax</h2>
442<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>
443<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>
444<span id="cb69-3"><a href="#cb69-3"></a></span>
445<span id="cb69-4"><a href="#cb69-4"></a><span class="ot">foo ::</span> <span class="dt">Reader</span> r b</span>
446<span id="cb69-5"><a href="#cb69-5"></a>foo <span class="ot">=</span> bar <span class="op">&gt;&gt;=</span> \x <span class="ot">-&gt;</span> qux x</span></code></pre></div>
447<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>
448<span id="cb70-2"><a href="#cb70-2"></a> <span class="co">-- (x :: a) &lt;- (bar :: Reader r a)</span></span>
449<span id="cb70-3"><a href="#cb70-3"></a> x <span class="ot">&lt;-</span> bar</span>
450<span id="cb70-4"><a href="#cb70-4"></a> qux x</span></code></pre></div>
451<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>
452<span id="cb71-2"><a href="#cb71-2"></a> <span class="co">-- (x :: a) &lt;- (bar :: Reader r a)</span></span>
453<span id="cb71-3"><a href="#cb71-3"></a> x <span class="ot">&lt;-</span> bar</span>
454<span id="cb71-4"><a href="#cb71-4"></a> <span class="co">-- (y :: b) &lt;- (qux x :: Reader r b)</span></span>
455<span id="cb71-5"><a href="#cb71-5"></a> y <span class="ot">&lt;-</span> qux x</span>
456<span id="cb71-6"><a href="#cb71-6"></a> <span class="fu">return</span> y</span></code></pre></div>
457<div class="sourceCode" id="cb72"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb72-1"><a href="#cb72-1"></a>foo <span class="ot">=</span> bar <span class="op">&gt;&gt;=</span> \x <span class="ot">-&gt;</span> qux x <span class="op">&gt;&gt;=</span> <span class="fu">return</span></span></code></pre></div>
458</section>
459<section class="slide level2">
461<div class="sourceCode" id="cb73"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb73-1"><a href="#cb73-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>
462<span id="cb73-2"><a href="#cb73-2"></a></span>
463<span id="cb73-3"><a href="#cb73-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>
464<span id="cb73-4"><a href="#cb73-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>
465<span id="cb73-5"><a href="#cb73-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>
466<span id="cb73-6"><a href="#cb73-6"></a></span>
467<span id="cb73-7"><a href="#cb73-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>
468<span id="cb73-8"><a href="#cb73-8"></a>payForCoffee coffee <span class="ot">=</span></span>
469<span id="cb73-9"><a href="#cb73-9"></a> coffee <span class="op">&gt;&gt;=</span> getCoffeePrice <span class="op">&gt;&gt;=</span> \coffeePrice <span class="ot">-&gt;</span></span>
470<span id="cb73-10"><a href="#cb73-10"></a> coffee <span class="op">&gt;&gt;=</span> getDiscount <span class="op">&gt;&gt;=</span> \discount <span class="ot">-&gt;</span></span>
471<span id="cb73-11"><a href="#cb73-11"></a> getPayment (coffeePrice <span class="op">-</span> discount)</span></code></pre></div>
472<div class="sourceCode" id="cb74"><pre class="sourceCode haskell fragment"><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>
473<span id="cb74-2"><a href="#cb74-2"></a>payForCoffee coffee <span class="ot">=</span> <span class="kw">do</span></span>
474<span id="cb74-3"><a href="#cb74-3"></a> coffeePrice <span class="ot">&lt;-</span> getCoffeePrice coffee</span>
475<span id="cb74-4"><a href="#cb74-4"></a> discount <span class="ot">&lt;-</span> getDiscount coffee</span>
476<span id="cb74-5"><a href="#cb74-5"></a> getPayment (coffeePrice <span class="op">-</span> discount)</span></code></pre></div>
477</section>
478<section id="let-statement" class="slide level2">
479<h2>Let statement</h2>
480<div class="sourceCode" id="cb75"><pre class="sourceCode haskell"><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>
481<span id="cb75-2"><a href="#cb75-2"></a>payForCoffee coffee <span class="ot">=</span> <span class="kw">do</span></span>
482<span id="cb75-3"><a href="#cb75-3"></a> coffeePrice <span class="ot">&lt;-</span> getCoffeePrice coffee</span>
483<span id="cb75-4"><a href="#cb75-4"></a> discount <span class="ot">&lt;-</span> getDiscount coffee</span>
484<span id="cb75-5"><a href="#cb75-5"></a> getPayment (coffeePrice <span class="op">-</span> discount)</span></code></pre></div>
485<div class="sourceCode" id="cb76"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb76-1"><a href="#cb76-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>
486<span id="cb76-2"><a href="#cb76-2"></a>payForCoffee coffee <span class="ot">=</span> <span class="kw">do</span></span>
487<span id="cb76-3"><a href="#cb76-3"></a> coffeePrice <span class="ot">&lt;-</span> getCoffeePrice coffee</span>
488<span id="cb76-4"><a href="#cb76-4"></a> discount <span class="ot">&lt;-</span> getDiscount coffee</span>
489<span id="cb76-5"><a href="#cb76-5"></a> <span class="kw">let</span> amount <span class="ot">=</span> coffeePrice <span class="op">-</span> discount</span>
490<span id="cb76-6"><a href="#cb76-6"></a> getPayment amount</span></code></pre></div>
491</section>
492<section class="slide level2">
494<div class="sourceCode" id="cb77"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb77-1"><a href="#cb77-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>
495<span id="cb77-2"><a href="#cb77-2"></a><span class="kw">type</span> <span class="dt">Price</span> <span class="ot">=</span> <span class="dt">Int</span></span>
496<span id="cb77-3"><a href="#cb77-3"></a></span>
497<span id="cb77-4"><a href="#cb77-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>
498<span id="cb77-5"><a href="#cb77-5"></a></span>
499<span id="cb77-6"><a href="#cb77-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>
500<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="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>
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">ask ::</span> <span class="dt">Reader</span> r r</span>
502<span id="cb79-2"><a href="#cb79-2"></a>ask <span class="ot">=</span> <span class="dt">Reader</span> (\r <span class="ot">-&gt;</span> r)</span></code></pre></div>
503<div class="sourceCode" id="cb80"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb80-1"><a href="#cb80-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>
504<span id="cb80-2"><a href="#cb80-2"></a>getCoffeePrice coffee <span class="ot">=</span> <span class="kw">do</span></span>
505<span id="cb80-3"><a href="#cb80-3"></a> <span class="co">-- (markup :: Markup) &lt;- (ask :: PricingEnv Markup)</span></span>
506<span id="cb80-4"><a href="#cb80-4"></a> markup <span class="ot">&lt;-</span> ask</span>
507<span id="cb80-5"><a href="#cb80-5"></a> <span class="kw">let</span> coffePrice <span class="ot">=</span> getCoffeePrice coffee</span>
508<span id="cb80-6"><a href="#cb80-6"></a> <span class="fu">return</span> (coffee <span class="op">+</span> markup)</span></code></pre></div>
509</section>
510<section class="slide level2">
512<div class="sourceCode" id="cb81"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb81-1"><a href="#cb81-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>
513<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">Order</span></span></code></pre></div>
514<p><span class="fragment">Откуда брать <code>orderId</code>?</span></p>
515<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">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>
516<span id="cb83-2"><a href="#cb83-2"></a>createOrder coffee <span class="ot">=</span> <span class="kw">do</span></span>
517<span id="cb83-3"><a href="#cb83-3"></a> newId <span class="ot">&lt;-</span> ask</span>
518<span id="cb83-4"><a href="#cb83-4"></a> <span class="fu">return</span> (<span class="dt">Order</span> coffee newId)</span></code></pre></div>
519<p><span class="fragment">🎉</span></p>
520<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="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>
521<div class="sourceCode" id="cb85"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb85-1"><a href="#cb85-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>
522<div class="sourceCode" id="cb86"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb86-1"><a href="#cb86-1"></a>createOrders <span class="ot">=</span> <span class="fu">mapM</span> createOrder</span></code></pre></div>
523</section>
524<section class="slide level2">
526<div class="sourceCode" id="cb87"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb87-1"><a href="#cb87-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>
527<span id="cb87-2"><a href="#cb87-2"></a>createOrders <span class="ot">=</span> <span class="fu">mapM</span> createOrder</span></code></pre></div>
528<p><span class="fragment">Все <code>id</code> будут одинаковые.</span></p>
529<p><span class="fragment"><code>Reader</code> эквивалентно глобальной <strong>константе</strong>.</span></p>
530<p><span class="fragment">Айдишники – скорее глобальная <strong>переменная</strong>.</span></p>
531<p><span class="fragment">– Но у нас же нет переменных!</span></p>
532<p><span class="fragment">– Да, нет!</span></p>
533</section>
534<section id="state" class="slide level2">
535<h2>State!</h2>
536<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="op">...</span> <span class="co">-- s -- само состояние</span></span>
537<span id="cb88-2"><a href="#cb88-2"></a></span>
538<span id="cb88-3"><a href="#cb88-3"></a><span class="ot">get ::</span> <span class="dt">State</span> s s</span>
539<span id="cb88-4"><a href="#cb88-4"></a><span class="ot">put ::</span> s <span class="ot">-&gt;</span> <span class="dt">State</span> s ()</span></code></pre></div>
540<div class="sourceCode" id="cb89"><pre class="sourceCode haskell fragment"><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>
541<span id="cb89-2"><a href="#cb89-2"></a></span>
542<span id="cb89-3"><a href="#cb89-3"></a><span class="ot">get ::</span> <span class="dt">State</span> s s</span>
543<span id="cb89-4"><a href="#cb89-4"></a>get <span class="ot">=</span> <span class="dt">State</span> (\s <span class="ot">-&gt;</span> (s, s))</span>
544<span id="cb89-5"><a href="#cb89-5"></a></span>
545<span id="cb89-6"><a href="#cb89-6"></a><span class="ot">put ::</span> s <span class="ot">-&gt;</span> <span class="dt">State</span> s ()</span>
546<span id="cb89-7"><a href="#cb89-7"></a>put s <span class="ot">=</span> <span class="dt">State</span> (\_ <span class="ot">-&gt;</span> ((), s))</span></code></pre></div>
547</section>
548<section class="slide level2">
550<div class="sourceCode" id="cb90"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb90-1"><a href="#cb90-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>
551<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="kw">class</span> <span class="dt">Monad</span> (<span class="dt">State</span> s) <span class="kw">where</span></span>
552<span id="cb91-2"><a href="#cb91-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>
553<span id="cb91-3"><a href="#cb91-3"></a></span>
554<span id="cb91-4"><a href="#cb91-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>
555<span id="cb91-5"><a href="#cb91-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>
556<span id="cb91-6"><a href="#cb91-6"></a> <span class="kw">where</span></span>
557<span id="cb91-7"><a href="#cb91-7"></a> go s <span class="ot">=</span> runState (g a) s&#39;</span>
558<span id="cb91-8"><a href="#cb91-8"></a> <span class="kw">where</span></span>
559<span id="cb91-9"><a href="#cb91-9"></a> (a, s&#39;) <span class="ot">=</span> f s</span></code></pre></div>
560</section>
561<section class="slide level2">
563<h3 id="айдишники">Айдишники!</h3>
564<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">getNewId ::</span> <span class="dt">State</span> <span class="dt">Int</span> <span class="dt">Int</span></span>
565<span id="cb92-2"><a href="#cb92-2"></a>getNewId <span class="ot">=</span> <span class="kw">do</span></span>
566<span id="cb92-3"><a href="#cb92-3"></a> newId <span class="ot">&lt;-</span> get</span>
567<span id="cb92-4"><a href="#cb92-4"></a> put (newId <span class="op">+</span> <span class="dv">1</span>)</span>
568<span id="cb92-5"><a href="#cb92-5"></a> <span class="fu">return</span> newId</span></code></pre></div>
569<p><span class="fragment">– Это какой-то процедурный языке получается!</span></p>
570<p><span class="fragment">– Лучше!*</span></p>
571<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="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>
572<span id="cb93-2"><a href="#cb93-2"></a>createOrder coffee <span class="ot">=</span> <span class="kw">do</span></span>
573<span id="cb93-3"><a href="#cb93-3"></a> newId <span class="ot">&lt;-</span> getNewId</span>
574<span id="cb93-4"><a href="#cb93-4"></a> <span class="fu">return</span> (<span class="dt">Order</span> coffee newId)</span>
575<span id="cb93-5"><a href="#cb93-5"></a></span>
576<span id="cb93-6"><a href="#cb93-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>
577<span id="cb93-7"><a href="#cb93-7"></a>createOrders <span class="ot">=</span> <span class="fu">mapM</span> createOrder</span></code></pre></div>
578</section>
579<section id="еще-монады" class="slide level2">
580<h2>Еще монады!</h2>
581<div class="sourceCode" id="cb94"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb94-1"><a href="#cb94-1"></a><span class="kw">class</span> <span class="dt">Monad</span> [] <span class="kw">where</span></span>
582<span id="cb94-2"><a href="#cb94-2"></a> <span class="fu">return</span> x <span class="ot">=</span> [x]</span>
583<span id="cb94-3"><a href="#cb94-3"></a></span>
584<span id="cb94-4"><a href="#cb94-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>
585<span id="cb94-5"><a href="#cb94-5"></a> [] <span class="op">&gt;&gt;=</span> _ <span class="ot">=</span> []</span>
586<span id="cb94-6"><a href="#cb94-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>
587<p><span class="fragment">Контекст недетерменированности (нескольких вариантов)</span></p>
588<div class="sourceCode" id="cb95"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb95-1"><a href="#cb95-1"></a>grid <span class="ot">=</span> <span class="kw">do</span></span>
589<span id="cb95-2"><a href="#cb95-2"></a> x <span class="ot">&lt;-</span> [<span class="dv">1</span><span class="op">..</span><span class="dv">5</span>]</span>
590<span id="cb95-3"><a href="#cb95-3"></a> y <span class="ot">&lt;-</span> [<span class="dv">1</span><span class="op">..</span><span class="dv">5</span>]</span>
591<span id="cb95-4"><a href="#cb95-4"></a> <span class="fu">return</span> (x, y)</span>
592<span id="cb95-5"><a href="#cb95-5"></a></span>
593<span id="cb95-6"><a href="#cb95-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>
594</section>
595<section class="slide level2">
597<p>Тривиальная монада</p>
598<div class="sourceCode" id="cb96"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb96-1"><a href="#cb96-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>
599<span id="cb96-2"><a href="#cb96-2"></a></span>
600<span id="cb96-3"><a href="#cb96-3"></a><span class="kw">class</span> <span class="dt">Monad</span> <span class="dt">Identity</span> <span class="kw">where</span></span>
601<span id="cb96-4"><a href="#cb96-4"></a> <span class="fu">return</span> x <span class="ot">=</span> <span class="dt">Identity</span> x</span>
602<span id="cb96-5"><a href="#cb96-5"></a></span>
603<span id="cb96-6"><a href="#cb96-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>
604<span id="cb96-7"><a href="#cb96-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>
605</section>
606<section class="slide level2">
608<div class="sourceCode" id="cb97"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb97-1"><a href="#cb97-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>
609<span id="cb97-2"><a href="#cb97-2"></a><span class="ot"> return ::</span> a <span class="ot">-&gt;</span> m a</span>
610<span id="cb97-3"><a href="#cb97-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>
611<p><span class="fragment">Монада – перегрузка композиции функций.</span></p>
612<div class="sourceCode" id="cb98"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb98-1"><a href="#cb98-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>
613<span id="cb98-2"><a href="#cb98-2"></a><span class="ot"> pure ::</span> a <span class="ot">-&gt;</span> m a</span>
614<span id="cb98-3"><a href="#cb98-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>
615<p><span class="fragment">Аппликативный функтор – перегрузка применения функций.</span></p>
616<p><span class="fragment">– Почему не <code>(a -&gt; b) -&gt; f a -&gt; f b</code>.</span></p>
617<p><span class="fragment">– Это <code>fmap</code>. (И функции нескольких аргументов)</span></p>
618</section>
619<section class="slide level2">
621<div class="sourceCode" id="cb99"><pre class="sourceCode haskell"><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> f a <span class="ot">-&gt;</span> f b</span></code></pre></div>
622<div class="sourceCode" id="cb100"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb100-1"><a href="#cb100-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>
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">getMarkup ::</span> <span class="dt">Env</span> <span class="dt">Markup</span></span>
624<span id="cb101-2"><a href="#cb101-2"></a><span class="ot">getPrice ::</span> <span class="dt">Env</span> <span class="dt">Price</span></span>
625<span id="cb101-3"><a href="#cb101-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>
626<div class="sourceCode" id="cb102"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb102-1"><a href="#cb102-1"></a><span class="ot">payment ::</span> <span class="dt">Env</span> <span class="dt">Payment</span></span>
627<span id="cb102-2"><a href="#cb102-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>
628<div class="sourceCode" id="cb103"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb103-1"><a href="#cb103-1"></a>payment <span class="ot">=</span> <span class="fu">fmap</span> getPayment getMarkup <span class="op">&lt;*&gt;</span> getPrice</span>
629<span id="cb103-2"><a href="#cb103-2"></a><span class="co">-- ^-------------^</span></span>
630<span id="cb103-3"><a href="#cb103-3"></a><span class="co">-- Env Markup -&gt; Env (Price -&gt; Payment)</span></span></code></pre></div>
631<div class="sourceCode" id="cb104"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb104-1"><a href="#cb104-1"></a>(<span class="op">&lt;$&gt;</span>) <span class="ot">=</span> <span class="fu">fmap</span></span></code></pre></div>
632<div class="sourceCode" id="cb105"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb105-1"><a href="#cb105-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>
633</section>
634<section class="slide level2">
636<div class="sourceCode" id="cb106"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb106-1"><a href="#cb106-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>
637<span id="cb106-2"><a href="#cb106-2"></a>mf <span class="op">&lt;*&gt;</span> ma <span class="ot">=</span> <span class="kw">do</span></span>
638<span id="cb106-3"><a href="#cb106-3"></a> f <span class="ot">&lt;-</span> mf</span>
639<span id="cb106-4"><a href="#cb106-4"></a> a <span class="ot">&lt;-</span> ma</span>
640<span id="cb106-5"><a href="#cb106-5"></a> <span class="fu">return</span> (f a)</span></code></pre></div>
641<div class="sourceCode" id="cb107"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb107-1"><a href="#cb107-1"></a><span class="ot">ap ::</span> <span class="dt">Monad</span> m <span class="ot">=&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>
642<span id="cb107-2"><a href="#cb107-2"></a>ap mf ma <span class="ot">=</span> <span class="kw">do</span></span>
643<span id="cb107-3"><a href="#cb107-3"></a> f <span class="ot">&lt;-</span> mf</span>
644<span id="cb107-4"><a href="#cb107-4"></a> a <span class="ot">&lt;-</span> ma</span>
645<span id="cb107-5"><a href="#cb107-5"></a> <span class="fu">return</span> (f a)</span></code></pre></div>
646<div class="sourceCode" id="cb108"><pre class="sourceCode haskell fragment"><code class="sourceCode haskell"><span id="cb108-1"><a href="#cb108-1"></a><span class="kw">instance</span> <span class="dt">Monad</span> <span class="op">...</span> <span class="kw">where</span> <span class="op">...</span></span>
647<span id="cb108-2"><a href="#cb108-2"></a></span>
648<span id="cb108-3"><a href="#cb108-3"></a><span class="kw">instance</span> <span class="dt">Applicative</span> <span class="op">...</span> <span class="kw">where</span></span>
649<span id="cb108-4"><a href="#cb108-4"></a> <span class="fu">pure</span> <span class="ot">=</span> <span class="fu">return</span></span>
650<span id="cb108-5"><a href="#cb108-5"></a> (<span class="op">&lt;*&gt;</span>) <span class="ot">=</span> ap</span></code></pre></div>
651</section></section>
652 </div>
653 </div>
655 <script src="reveal.js/js/reveal.js"></script>
657 <script>
659 // Full list of configuration options available at:
660 // https://github.com/hakimel/reveal.js#configuration
661 Reveal.initialize({
662 // Push each slide change to the browser history
663 history: true,
665 // Optional reveal.js plugins
666 dependencies: [
667 { src: 'reveal.js/lib/js/classList.js', condition: function() { return !document.body.classList; } },
668 { src: 'reveal.js/plugin/zoom-js/zoom.js', async: true },
669 { src: 'reveal.js/plugin/notes/notes.js', async: true }
670 ]
671 });
672 </script>
673 </body>
674</html>