/Programs/HabrFormat/formated_article.html
https://github.com/graninas/Haskell-Algorithms · HTML · 337 lines · 225 code · 112 blank · 0 comment · 0 complexity · 83016777068a403d1870999d77304581 MD5 · raw file
- Åùå Îäíî Ðóêîâîäñòâî ïî Ìîíàäàì (÷àñòü 4: Ìîíàäà Maybe)
- Mike Vanier
- http://mvanier.livejournal.com
-
- Ïåðåâîä: Ãðàíèí À. Ñ.
- graninas@gmail.com
-
-  ïðåäûäóùèõ ñòàòüÿõ ýòîé ñåðèè ìû èçó÷àëè êîíöåïòóàëüíûé áàçèñ ìîíàä, íî îáñóæäåíèå íàøå áûëî ñëèøêîì àáñòðàêòíûì. Òåïåðü, êîãäà âû, ÿ íàäåþñü, ïîíÿëè, ÷òî ìîíàäû òàêîå è äëÿ ÷åãî îíè íóæíû, ïðèøëî âðåìÿ äëÿ äåòàëüíîãî ðàññìîòðåíèÿ ñïåöèôè÷åñêèõ ìîíàä. Ýòî çíà÷èò, ÷òî ìû îïðåäåëèì êîððåêòíûå âîïëîùåíèÿ êëàññà òèïîâ <font color=blue>Monad</font> äëÿ ìíîæåñòâà ðàçëè÷íûõ ïîíÿòèé âû÷èñëåíèé, êîòîðûå ìû óâèäåëè ðàíüøå. Ìû èñïîëüçóåì íàøè çíàíèÿ, ÷òîáû ïîëó÷èòü ìîíàäè÷åñêóþ êîìïîçèöèþ â êàæäîì êîíêðåòíîì ñëó÷àå ÷åðåç ìîíàäè÷åñêîå ïðèìåíåíèå (îïåðàòîð <font color=blue>>>=</font>), è ñ ïîìîùüþ ìîíàäíûõ çàêîíîâ ìû âûâåäåì îïðåäåëåíèå <font color=blue>return</font>.
-
- Ìîíàäà <font color=blue>Maybe</font>
-
- Ìîíàäó <font color=blue>Maybe</font> îáû÷íî ïåðâîé ïðåäñòàâëÿþò â ðóêîâîäñòâàõ ïî Haskell, ïîòîìó ÷òî îíà î÷åíü ïðîñòà â èñïîëüçîâàíèè, ðåàëèçàöèè è ïîíèìàíèè. Äëÿ íà÷àëà âçãëÿíåì íà îïðåäåëåíèå òèïà äàííûõ <font color=blue>Maybe</font>:
-
- <blockquote><font color="#06c">data</font> <font color=green><a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:Maybe">Maybe</a></font> a <font color="#66cc66"><b>=</b></font> Nothing <font color="#339933">|</font> Just a</blockquote>
-
- Çäåñü óêàçàíî, ÷òî <font color=blue>Maybe</font> - ýòî êîíñòðóêòîð òèïà, â êîòîðûé ïîìåùàåòñÿ îïðåäåëåííûé òèï <font color=blue>a</font>, ÷òîáû ïîëó÷èòü (êîíêðåòíûé) òèï äàííûõ. Åùå ãîâîðÿò, ÷òî <font color=blue>Maybe</font> - ýòî "ïîëèìîðôíûé" òèï äàííûõ, ñìûñë òîò æå. Òàê, åñëè áû <font color=blue>a</font> áûë <font color=blue>Int</font>, ìû áû ïîëó÷èëè:
-
- <blockquote><font color="#06c">data</font> <font color=green><a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:Maybe">Maybe</a></font> <font color=green><a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:Int">Int</a></font> <font color="#66cc66"><b>=</b></font> Nothing <font color="#339933">|</font> Just <font color=green><a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:Int">Int</a></font></blockquote>
-
- Òîëüêî âîò íàì íå íóæíî ýòî ïèñàòü íåïîñðåäñòâåííî, òàê êàê àáñòðàêòíîå îïðåäåëåíèå âûøå ïîäõîäèò êî âñåì òèïàì.
-
- Çíà÷åíèå òèïà <font color=blue>Maybe a</font> ìîæåò ëèáî áûòü, ëèáî îòñóòñòâîâàòü. Åñëè çíà÷åíèå ðàâíî <font color=blue>Nothing</font> ("Íè÷òî"), òî åãî "êàê áû è íåò", à åñëè îíî ðàâíî <font color=blue>Just x</font> äëÿ íåêîòîðîãî çíà÷åíèÿ <font color=blue>x</font>, òî ýòî "ïðîñòî" çíà÷åíèå <font color=blue>x</font>. Ìîæíî äóìàòü îá ýòîì êàê î êîíòåéíåðå, â êîòîðîì ëèáî 0 ýëåìåíòîâ, ëèáî îí îäèí. (Âñïîìíèòå: ÿ êîãäà-òî ãîâîðèë, ÷òî ìîíàäè÷åñêèå çíà÷åíèÿ èíîãäà îøèáî÷íî ïðåäñòàâëÿþòñÿ â âèäå êîíòåéíåðîâ. Ýòî òîò ñàìûé ñëó÷àé.)
-
- Ïîëèìîðôíûé òèï <font color=blue>Maybe</font> ïîëåçåí òåì, ÷òî ìû ìîæåì èñïîëüçîâàòü åãî êàê ìîäåëü "ðàñøèðåííîé ôóíêöèè", êîòîðàÿ ëèáî ïðîèçâîäèò ÷òî-òî êàê âûõîäíîå çíà÷åíèå, ëèáî òåðïèò â ýòîì êðàõ è íå ìîæåò âåðíóòü íèêàêîå çíà÷åíèå. (Òî åñòü, òàêàÿ ôóíêöèÿ ìîæåò ïðîâàëèòüñÿ.) Ýòî çàïèñûâàåòñÿ òàê:
-
- <blockquote>f <font color="#66cc66"><b>::</b></font> a <font color="#339933">-></font> <font color=green><a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:Maybe">Maybe</a></font> b</blockquote>
-
- Ôóíêöèÿ <font color=blue>f</font> áåðåò çíà÷åíèå òèïà <font color=blue>a</font> è ëèáî âîçâðàùàåò <font color=blue>Nothing</font> (ïðèçíàê íåóäà÷è), ëèáî çíà÷åíèå <font color=blue>Just x</font>, ãäå ó <font color=blue>x</font> òèï <font color=blue>b</font>. Ôóíêöèè âðîäå <font color=blue>f</font> áóäóò ðàáîòàòü â ìîíàäå <font color=blue>Maybe</font>, è êîìïîçèöèÿ äâóõ òàêèõ ôóíêöèé âûãëÿäèò ñëåäóþùèì îáðàçîì:
-
- <blockquote>f <font color="#66cc66"><b>::</b></font> a <font color="#339933">-></font> <font color=green><a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:Maybe">Maybe</a></font> b <font color="#5d478b">-- ïðåäïîëàãàåì, ÷òî f ãäå-òî îïðåäåëåíà</font><br/>
- g <font color="#66cc66"><b>::</b></font> b <font color="#339933">-></font> <font color=green><a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:Maybe">Maybe</a></font> c <font color="#5d478b">-- ïðåäïîëàãàåì, ÷òî g ãäå-òî îïðåäåëåíà</font><br/>
- <br/>
- h <font color="#66cc66"><b>::</b></font> a <font color="#339933">-></font> <font color=green><a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:Maybe">Maybe</a></font> c <font color="#5d478b">-- ìîíàäè÷åñêàÿ êîìïîçèöèÿ f è g</font><br/>
- h <font color="#66cc66"><b>=</b></font> f <font color="#339933">>=></font> g <font color="#5d478b">-- âñïîìíèì: >=> - ýòî îïåðàòîð ìîíàäè÷åñêîé êîìïîçèöèè</font></blockquote>
-
- Ìû ãîâîðèëè, ÷òî âñå ìîíàäû äîëæíû áûòü êîíñòðóêòîðàìè òèïîâ. <font color=blue>Maybe</font> - ýòî êîíñòðóêòîð òèïà, òàê ÷òî òóò âñå õîðîøî. Íî äëÿ òîãî ÷òîáû <font color=blue>Maybe</font> ñòàë ìîíàäîé, íàì íóæíî ñîçäàòü ýêçåìïëÿð êëàññà òèïîâ <font color=blue>Monad</font>, à ýòî çíà÷èò, ÷òî ìû äîëæíû çàïîëíèòü ñëåäóþùåå îïðåäåëåíèå:
-
- <blockquote><font color="#06c">instance</font> <font color=green><a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:Monad">Monad</a></font> <font color=green><a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:Maybe">Maybe</a></font> <font color="#06c">where</font><br/>
- <font>(</font><font color="#339933">>>=</font><font>)</font> <font color="#66cc66"><b>=</b></font> <i><font color="#5d478b">{- îïðåäåëåíèå >>= äëÿ Maybe -}</font></i><br/>
- <font>return</font> <font color="#66cc66"><b>=</b></font> <i><font color="#5d478b">{- îïðåäåëåíèå return äëÿ Maybe -}</font></i></blockquote>
-
- Êàê ìû ìîæåì çàäàòü <font color=blue>(>>=)</font> è <font color=blue>return</font> äëÿ <font color=blue>Maybe</font>?
-
- Ñíà÷àëà íàïèøåì êàðêàñ îïðåäåëåíèÿ äëÿ <font color=blue>>>=</font>, ïîêðûâàþùèé äâà âîçìîæíûõ ñëó÷àÿ ëåâîãî îïåðàíäà òèïà <font color=blue>Maybe a</font>:
-
- <blockquote>Nothing <font color="#339933">>>=</font> f <font color="#66cc66"><b>=</b></font> <i><font color="#5d478b">{- íóæíî äîïèñàòü -}</font></i><br/>
- Just x <font color="#339933">>>=</font> f <font color="#66cc66"><b>=</b></font> <i><font color="#5d478b">{- íóæíî äîïèñàòü -}</font></i></blockquote>
-
- ãäå <font color=blue>x</font> èìååò òèï <font color=blue>a</font>. Ëåâóþ ÷àñòü îïðåäåëåíèÿ ìîæíî íàïèñàòü è ïî-äðóãîìó:
-
- <blockquote><font>(</font><font color="#339933">>>=</font><font>)</font> Nothing f <font color="#66cc66"><b>=</b></font> <i><font color="#5d478b">{- íóæíî äîïèñàòü -}</font></i><br/>
- <font>(</font><font color="#339933">>>=</font><font>)</font> <font>(</font>Just x<font>)</font> f <font color="#66cc66"><b>=</b></font> <i><font color="#5d478b">{- íóæíî äîïèñàòü -}</font></i></blockquote>
-
- Íî ëó÷øå âñå-òàêè, åñëè îïåðàòîð <font color=blue>(>>=)</font> çàäàí êàê îïåðàòîð, à íå êàê ôóíêöèÿ, è Haskell íàì ýòî ïîçâîëÿåò.
-
- Äëÿ çàâåðøåíèÿ ýòîãî îïðåäåëåíèÿ ïîäóìàåì, ÷òî ìû õîòèì ïîëó÷èòü îò ìîíàäè÷åñêîé êîìïîçèöèè â ìîíàäå <font color=blue>Maybe</font>. Äàâàéòå âîçüìåì íàø ïðèìåð ñ ôóíêöèÿìè <font color=blue>f</font> è <font color=blue>g</font>, ìîíàäè÷åñêè èõ ñêîìïîíóåì è ïîëó÷èì ôóíêöèþ <font color=blue>h</font>:
-
- <blockquote>f <font color="#66cc66"><b>::</b></font> a <font color="#339933">-></font> <font color=green><a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:Maybe">Maybe</a></font> b<br/>
- g <font color="#66cc66"><b>::</b></font> b <font color="#339933">-></font> <font color=green><a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:Maybe">Maybe</a></font> c<br/>
- h <font color="#66cc66"><b>::</b></font> a <font color="#339933">-></font> <font color=green><a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:Maybe">Maybe</a></font> c<br/>
- h <font color="#66cc66"><b>=</b></font> f <font color="#339933">>=></font> g</blockquote>
-
- Åñëè ìû ïåðåäàäèì àðãóìåíò â ôóíêöèþ <font color=blue>f</font>, è îíà âåðíåò <font color=blue>Nothing</font> (òî åñòü, ïîòåðïèò íåóäà÷ó), òî ÷òî äîëæíà âåðíóòü ôóíêöèÿ <font color=blue>h</font>?
-
- <blockquote>f x <font color="#66cc66"><b>=</b></font> Nothing<br/>
- h x <font color="#66cc66"><b>=</b></font> <font>(</font>f <font color="#339933">>=></font> g<font>)</font> x <font color="#66cc66"><b>=</b></font> <font color="#339933">???</font></blockquote>
-
- Êàæåòñÿ î÷åâèäíûì, ÷òî åñëè <font color=blue>f x</font> âåðíåò <font color=blue>Nothing</font>, òî è <font color=blue>h</font> òîæå äîëæíà âåðíóòü <font color=blue>Nothing</font>, ïîñêîëüêó åñëè ÷àñòü âûðàæåíèÿ (ôóíêöèÿ <font color=blue>f</font>) íå ñìîãëà âåðíóòü ðåçóëüòàò, òî è âñå âûðàæåíèå (ôóíêöèÿ <font color=blue>h</font>) íå ñìîæåò åãî âåðíóòü. Åäèíñòâåííûé âàðèàíò, êîãäà <font color=blue>h</font> âîçâðàùàåò çíà÷åíèå, ýòî êîãäà <font color=blue>f</font> âåðíåò ðåçóëüòàò (íàçîâåì åãî <font color=blue>y</font>), îí áóäåò ïåðåäàí ôóíêöèè <font color=blue>g</font>, è <font color=blue>g y</font> - òîæå áóäåò êîððåêòíûé ðåçóëüòàò. Åñëè ïðîâàëèòñÿ <font color=blue>f</font> èëè <font color=blue>g</font>, òî è <font color=blue>h</font> çàâåðøèòñÿ íåóäà÷åé, òî åñòü, âû÷èñëåíèåì <font color=blue>h x</font> áóäåò <font color=blue>Nothing</font>.
-
- Èìåÿ ýòî â âèäó, èç íàøåãî îïðåäåëåíèÿ <font color=blue>h</font> ïîëó÷èì:
-
- <blockquote>h <font color="#66cc66"><b>=</b></font> f <font color="#339933">>=></font> g<br/>
- h <font color="#66cc66"><b>=</b></font> \x <font color="#339933">-></font> <font>(</font>f x <font color="#339933">>>=</font> g<font>)</font> <font color="#5d478b">-- ýêâèâàëåíò (èç îïðåäåëåíèÿ >=>)</font><br/>
- h x <font color="#66cc66"><b>=</b></font> f x <font color="#339933">>>=</font> g <font color="#5d478b">-- ýêâèâàëåíò</font><br/>
- <font color="#5d478b">-- ïðåäïîëîæèì, ÷òî f x == Nothing</font><br/>
- h x <font color="#66cc66"><b>=</b></font> <font>(</font>Nothing <font color="#339933">>>=</font> g<font>)</font><br/>
- <font color="#66cc66"><b>=</b></font> Nothing<br/>
- <font color="#5d478b">-- òàêèì îáðàçîì:</font><br/>
- Nothing <font color="#339933">>>=</font> g <font color="#66cc66"><b>=</b></font> Nothing</blockquote>
-
- Òåïåðü ìû çíàåì, êàê îïåðàòîð <font color=blue>(>>=)</font> ðåàãèðóåò íà àðãóìåíò <font color=blue>Nothing</font>, - îí ïðîñòî âîçâðàùàåò òîò æå <font color=blue>Nothing</font>:
-
- <blockquote>Nothing <font color="#339933">>>=</font> f <font color="#66cc66"><b>=</b></font> Nothing<br/>
- Just x <font color="#339933">>>=</font> f <font color="#66cc66"><b>=</b></font> <i><font color="#5d478b">{- íóæíî äîïèñàòü -}</font></i></blockquote>
-
- Îáðàòèòå âíèìàíèå, ÿ çäåñü çàìåíèë <font color=blue>g</font> íà <font color=blue>f</font>, è ýòî êîððåêòíî, âåäü èìåíà ôóíêöèé íå âàæíû. Íà ïðàêòèêå ìû âîîáùå èçáàâëÿåìñÿ îò èìåí ôóíêöèé, åñëè ýòî âîçìîæíî, è çàìåíÿåì èõ ñïåöèàëüíûì îïåðàòîðîì <font color=blue>_</font> (íèæíåå ïîä÷åðêèâàíèå), âîò òàê:
-
- <blockquote>Nothing <font color="#339933">>>=</font> <font color="#339933">_</font> <font color="#66cc66"><b>=</b></font> Nothing</blockquote>
-
- Ñî âòîðûì óðàâíåíèåì ýòîãî ñäåëàòü íåëüçÿ, ïîòîìó ÷òî ôóíêöèþ <font color=blue>f</font> ìû åùå áóäåì èñïîëüçîâàòü â îïðåäåëåíèè.
-
- Òåïåðü äàâàéòå ïîäîéäåì ñ äðóãîé ñòîðîíû. Åñëè <font color=blue>f x</font> <i>íå</i> ïðîâàëèòñÿ, ðåçóëüòàòîì áóäåò çíà÷åíèå <font color=blue>Just y</font> äëÿ íåêîòîðîãî <font color=blue>y</font>. Íàì íóæíî "ðàñïàêîâàòü" çíà÷åíèå <font color=blue>y</font> èç <font color=blue>Just y</font>, êîòîðîå ìû áû ïîòîì ïåðåäàëè ôóíêöèè <font color=blue>g</font>, è <font color=blue>g y</font> - ýòî ðåçóëüòàò âñåé ôóíêöèè <font color=blue>h</font>:
-
- <blockquote>h <font color="#66cc66"><b>=</b></font> f <font color="#339933">>=></font> g<br/>
- h <font color="#66cc66"><b>=</b></font> \x <font color="#339933">-></font> <font>(</font>f x <font color="#339933">>>=</font> g<font>)</font> <font color="#5d478b">-- ýêâèâàëåíò (èç îïðåäåëåíèÿ >=>)</font><br/>
- h x <font color="#66cc66"><b>=</b></font> f x <font color="#339933">>>=</font> g <font color="#5d478b">-- ýêâèâàëåíò</font><br/>
- <font color="#5d478b">-- ïðåäïîëîæèì, ÷òî f x == Just y </font><br/>
- h x <font color="#66cc66"><b>=</b></font> <font>(</font>Just y <font color="#339933">>>=</font> g<font>)</font><br/>
- <font color="#66cc66"><b>=</b></font> g y</blockquote>
-
- ×òî äàåò íàì âòîðóþ ÷àñòü îïðåäåëåíèÿ:
-
- <blockquote>Nothing <font color="#339933">>>=</font> f <font color="#66cc66"><b>=</b></font> Nothing<br/>
- Just x <font color="#339933">>>=</font> f <font color="#66cc66"><b>=</b></font> f x</blockquote>
-
- Çàìåòüòå, ÷òî ÿ çàìåíèë <font color=blue>y</font> íà <font color=blue>x</font> è <font color=blue>g</font> íà <font color=blue>f</font>. Îïÿòü æå, èìåíà ïåðåìåííûõ è ôóíêöèé íå èìåþò çíà÷åíèÿ äî òåõ ïîð, ïîêà âû ïîñëåäîâàòåëüíû.
-
- Íà ýòîì çàâåðøàåòñÿ îïðåäåëåíèå îïåðàòîðà <font color=blue>>>=</font> äëÿ ìîíàäû <font color=blue>Maybe</font>. Òåïåðü íàì íóæíî ïîëó÷èòü <font color=blue>return</font> äëÿ ýòîé ìîíàäû:
-
- <blockquote><font>return</font> x <font color="#66cc66"><b>=</b></font> <font color="#339933">???</font></blockquote>
-
- äëÿ ëþáîãî çíà÷åíèÿ <font color=blue>x</font>. Êàêèå ó íàñ åñòü âàðèàíòû? Ìû ìîãëè áû ïðîñòî ñêàçàòü, ÷òî
-
- <blockquote><font>return</font> x <font color="#66cc66"><b>=</b></font> Nothing</blockquote>
-
- äëÿ ëþáîãî <font color=blue>x</font>. Îäíàêî ìû áû íàðóøèëè ìîíàäíûå çàêîíû, åñëè áû òàê ñäåëàëè:
-
- <blockquote><font>return</font> x <font color="#339933">>>=</font> f <font color="#339933">==</font> f x<br/>
- Nothing <font color="#339933">>>=</font> f <font color="#339933">==</font> f x<br/>
- Nothing <font color="#339933">==</font> f x <font color="#5d478b">-- ÍÅÂÅÐÍÎ!</font></blockquote>
-
- Ïðåäïîëàãàÿ, ÷òî ïî êðàéíåé ìåðå <i>íåêîòîðûå</i> <font color=blue>f x</font> íå <font color=blue>Nothing</font> (íàïðèìåð, ðàññìîòðèì ìîíàäè÷åñêóþ ôóíêöèþ <font color=blue>f x</font> = <font color=blue>Just x</font>), ïîëó÷èì îøèáêó. Åñòü è äðóãîé âàðèàíò:
-
- <blockquote><font>return</font> x <font color="#66cc66"><b>=</b></font> Just x</blockquote>
-
- è îí óäîâëåòâîðÿåò ìîíàäíûì çàêîíàì:
-
- <blockquote><font>return</font> x <font color="#339933">>>=</font> f<br/>
- <font color="#66cc66"><b>=</b></font> <font>(</font>Just x<font>)</font> <font color="#339933">>>=</font> f <font color="#5d478b">-- ïî îïðåäåëåíèþ return äëÿ ìîíàäû Maybe</font><br/>
- <font color="#66cc66"><b>=</b></font> f x <font color="#5d478b">-- ïî îïðåäåëåíèþ >>= äëÿ ìîíàäû Maybe</font><br/>
- <font color="#5d478b">-- âûïîëíåíèå ïåðâîãî ìîíàäíîãî çàêîíà</font><br/>
- <br/>
- Just x <font color="#339933">>>=</font> <font>return</font><br/>
- <font color="#66cc66"><b>=</b></font> <font>return</font> x <font color="#5d478b">-- ïî îïðåäåëåíèþ >>= äëÿ ìîíàäû Maybe</font><br/>
- <font color="#66cc66"><b>=</b></font> Just x <font color="#5d478b">-- ïî îïðåäåëåíèþ return äëÿ ìîíàäû Maybe</font><br/>
- <font color="#5d478b">-- âûïîëíåíèå âòîðîãî ìîíàäíîãî çàêîíà</font><br/>
- <br/>
- Nothing <font color="#339933">>>=</font> <font>return</font><br/>
- <font color="#66cc66"><b>=</b></font> Nothing <font color="#5d478b">-- ïî îïðåäåëåíèþ >>= äëÿ ìîíàäû Maybe</font><br/>
- <font color="#5d478b">-- âûïîëíåíèå âòîðîãî ìîíàäíîãî çàêîíà</font></blockquote>
-
- Ðàç çàêîíû ñîáëþäàþòñÿ, ýòîò âàðèàíò è âîçüìåì. Ïîëíîå îïðåäåëåíèå ìîíàäû <font color=blue>Maybe</font> âûãëÿäèò òàê:
-
- <blockquote><font color="#06c">instance</font> <font color=green><a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:Monad">Monad</a></font> <font color=green><a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:Maybe">Maybe</a></font> <font color="#06c">where</font><br/>
- <font>return</font> x <font color="#66cc66"><b>=</b></font> Just x<br/>
- <br/>
- Nothing <font color="#339933">>>=</font> f <font color="#66cc66"><b>=</b></font> Nothing<br/>
- Just x <font color="#339933">>>=</font> f <font color="#66cc66"><b>=</b></font> f x</blockquote>
-
- Âàó! Ìû òîëüêî ÷òî ñîçäàëè íàøó ïåðâóþ ìîíàäó!
-
- Ïðîñòî ÷òîáû îáåçîïàñèòü ñåáÿ, ïðîâåðèì, ÷òî îíà óäîâëåòâîðÿåò òðåòüåìó ìîíàäíîìó çàêîíó, êîòîðûé ãëàñèò:
-
- <blockquote><font>(</font>mv <font color="#339933">>>=</font> f<font>)</font> <font color="#339933">>>=</font> g <font color="#339933">==</font> mv <font color="#339933">>>=</font> <font>(</font>\x <font color="#339933">-></font> <font>(</font>f x <font color="#339933">>>=</font> g<font>)</font><font>)</font></blockquote>
-
- Ñíà÷àëà ïðîâåðèì çàêîí äëÿ ñëó÷àÿ, êîãäà mv = Nothing:
-
- <blockquote><font>(</font>Nothing <font color="#339933">>>=</font> f<font>)</font> <font color="#339933">>>=</font> g <font color="#5d478b">-- ñ ëåâîé ñòîðîíû</font><br/>
- <font color="#66cc66"><b>=</b></font> Nothing <font color="#339933">>>=</font> g <font color="#5d478b">-- ïî îïðåäåëåíèþ >>=</font><br/>
- <font color="#66cc66"><b>=</b></font> Nothing <font color="#5d478b">-- ïî îïðåäåëåíèþ >>=</font><br/>
- <br/>
- Nothing <font color="#339933">>>=</font> <font>(</font>\x <font color="#339933">-></font> <font>(</font>f x <font color="#339933">>>=</font> g<font>)</font><font>)</font> <font color="#5d478b">-- ñ ïðàâîé ñòîðîíû</font><br/>
- <font color="#66cc66"><b>=</b></font> Nothing <font color="#5d478b">-- ïî îïðåäåëåíèþ >>=</font></blockquote>
-
- Õîðîøî, ïðîâåðêà ïðîøëà óñïåøíî. Òåïåðü ïîñìîòðèì, ðàáîòàåò ëè îí äëÿ <font color=blue>mv = Just v</font>, ãäå <font color=blue>v</font> - íåêîòîðîå çíà÷åíèå:
-
- <blockquote><font>(</font><font>(</font>Just v<font>)</font> <font color="#339933">>>=</font> f<font>)</font> <font color="#339933">>>=</font> g <font color="#5d478b">-- ñ ëåâîé ñòîðîíû</font><br/>
- <font color="#66cc66"><b>=</b></font> f v <font color="#339933">>>=</font> g <font color="#5d478b">-- ïî îïðåäåëåíèþ >>=</font><br/>
- <br/>
- <font>(</font>Just v<font>)</font> <font color="#339933">>>=</font> <font>(</font>\x <font color="#339933">-></font> <font>(</font>f x <font color="#339933">>>=</font> g<font>)</font><font>)</font> <font color="#5d478b">-- ñ ïðàâîé ñòîðîíû</font><br/>
- <font color="#66cc66"><b>=</b></font> <font>(</font>\x <font color="#339933">-></font> <font>(</font>f x <font color="#339933">>>=</font> g<font>)</font><font>)</font> v <font color="#5d478b">-- ïî îïðåäåëåíèþ >>=</font><br/>
- <font color="#66cc66"><b>=</b></font> f v <font color="#339933">>>=</font> g <font color="#5d478b">-- íîðìàëüíîå ïðèìåíåíèå ôóíêöèè (áåòà-ðåäóêöèÿ)</font></blockquote>
-
- È òîæå óñïåøíî. Çíà÷èò, çàêîí âûïîëíÿåòñÿ! Ýòî <i>äåéñòâèòåëüíî</i> ïðàâèëüíîå îïðåäåëåíèå ìîíàäû <font color=blue>Maybe</font>! È ïóáëèêà ñõîäèò ñ óìà!
-
-  ÷åì ñìûñë âñåãî ýòîãî? Ýòî çíà÷èò, ÷òî òåïåðü ìû ëåãêî ìîæåì ñîåäèíèòü êó÷ó ìîíàäè÷åñêèõ ôóíêöèé ìîíàäû <font color=blue>Maybe</font>. Âû, âîçìîæíî, çàäàåòåñü âîïðîñîì, ïî÷åìó ýòî âàæíî? Ñîâñåì íåòðóäíî ïðåäñòàâèòü ñåáå ìíîãî ìîíàäè÷åñêèõ ôóíêöèé â ìîíàäå <font color=blue>Maybe</font>, òî åñòü, òàêèõ, êîòîðûå ìîãóò ïðîâàëèòüñÿ. Ñêàæåì, ïóñòü ó íèõ áóäåò òèï <font color=blue>Int -> Maybe Int</font>. Âîò òðè ïîäîáíûõ ôóíêöèè:
-
- <blockquote>f <font color="#66cc66"><b>::</b></font> <font color=green><a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:Int">Int</a></font> <font color="#339933">-></font> <font color=green><a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:Maybe">Maybe</a></font> <font color=green><a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:Int">Int</a></font><br/>
- f x <font color="#66cc66"><b>=</b></font> <font color="#06c">if</font> x `<font>mod</font>` <font color=red>2</font> <font color="#339933">==</font> <font color=red>0</font> <font color="#06c">then</font> Nothing <font color="#06c">else</font> Just <font>(</font><font color=red>2</font> <font color="#339933">*</font> x<font>)</font><br/>
- <br/>
- g <font color="#66cc66"><b>::</b></font> <font color=green><a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:Int">Int</a></font> <font color="#339933">-></font> <font color=green><a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:Maybe">Maybe</a></font> <font color=green><a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:Int">Int</a></font><br/>
- g x <font color="#66cc66"><b>=</b></font> <font color="#06c">if</font> x `<font>mod</font>` <font color=red>3</font> <font color="#339933">==</font> <font color=red>0</font> <font color="#06c">then</font> Nothing <font color="#06c">else</font> Just <font>(</font><font color=red>3</font> <font color="#339933">*</font> x<font>)</font><br/>
- <br/>
- h <font color="#66cc66"><b>::</b></font> <font color=green><a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:Int">Int</a></font> <font color="#339933">-></font> <font color=green><a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:Maybe">Maybe</a></font> <font color=green><a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:Int">Int</a></font><br/>
- h x <font color="#66cc66"><b>=</b></font> <font color="#06c">if</font> x `<font>mod</font>` <font color=red>5</font> <font color="#339933">==</font> <font color=red>0</font> <font color="#06c">then</font> Nothing <font color="#06c">else</font> Just <font>(</font><font color=red>5</font> <font color="#339933">*</font> x<font>)</font></blockquote>
-
- Íàì áû õîòåëîñü ñîåäèíèòü èõ â îäíó ôóíêöèþ, êîòîðàÿ åñòü ðåçóëüòàò ïðèìåíåíèÿ ïî ïîðÿäêó <font color=blue>f</font>, <font color=blue>g</font>, <font color=blue>h</font>:
-
- <blockquote>k <font color="#66cc66"><b>::</b></font> <font color=green><a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:Int">Int</a></font> <font color="#339933">-></font> <font color=green><a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:Maybe">Maybe</a></font> <font color=green><a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:Int">Int</a></font></blockquote>
-
- È åñëè êàêàÿ-òî èç òðåõ ôóíêöèé ïîòåðïèò íåóäà÷ó, ôóíêöèÿ <font color=blue>k</font> äîëæíà âåðíóòü <font color=blue>Nothing</font>. Ýòà ôóíêöèÿ óìíîæàåò âõîäíîå ÷èñëî íà 30, åñëè îíî íå äåëèòñÿ öåëî÷èñëåííî íà 2, 3 èëè 5 (à åñëè äåëèòñÿ, ôóíêöèÿ âîçâðàùàåò <font color=blue>Nothing</font>).
-
- Èç ïðåäûäóùåãî ìàòåðèàëà, åñëè âû åãî õîðîøî ïîíÿëè, äîëæíî áûòü ïîíÿòíî, ÷òî âû ìîæåòå çàäàòü <font color=blue>k</font> ÷åðåç ìîíàäè÷åñêóþ êîìïîçèöèþ:
-
- <blockquote>k <font color="#66cc66"><b>=</b></font> f <font color="#339933">>=></font> g <font color="#339933">>=></font> h</blockquote>
-
- Èëè ìîæåòå âçÿòü îïåðàòîð <font color=blue>>>=</font>:
-
- <blockquote>k x <font color="#66cc66"><b>=</b></font> f x <font color="#339933">>>=</font> g <font color="#339933">>>=</font> h</blockquote>
-
- Èëè, âîçìîæíî, âàì íðàâèòñÿ <font color=blue>do</font>-íîòàöèÿ:
-
- <blockquote>k x <font color="#66cc66"><b>=</b></font> <font color="#06c">do</font> y <font color="#339933"><-</font> f x<br/>
- z <font color="#339933"><-</font> g y<br/>
- h z</blockquote>
-
- Ýòî ïðîñòî, êàê íè êðóòè. {1:  îðèãèíàëå - óñòîé÷èâîå âûðàæåíèå "Any way you slice it", àíàëîãè÷íîå ïî ñìûñëó. - Ïðèì. ïåð.}
-
- À âîîáùå, ôóíêöèþ <font color=blue>h</font> ìîæíî îïðåäåëèòü âîâñå áåç ìîíàäíûõ êîíñòðóêöèé, ýòî áóäåò âûãëÿäåòü òàê:
-
- <blockquote>k x <font color="#66cc66"><b>=</b></font> <font color="#06c">case</font> f x <font color="#06c">of</font><br/>
- Nothing <font color="#339933">-></font> Nothing<br/>
- Just y <font color="#339933">-></font> <font color="#06c">case</font> g y <font color="#06c">of</font><br/>
- Nothing <font color="#339933">-></font> Nothing<br/>
- Just z <font color="#339933">-></font> h z</blockquote>
-
- Òåïåðü ïîíÿòíî, ïî÷åìó ìîíàäà <font color=blue>Maybe</font> âàæíà. Îíà ðåçêî óïðîùàåò êîä, ñîåäèíÿÿ â öåïü íåñêîëüêî <font color=blue>Maybe</font>-ôóíêöèé. Ïðåäñòàâüòå ñåáå ãðóáûé íåìîíàäè÷åñêèé êîä äëÿ êîìïîçèöèè äåñÿòè <font color=blue>Maybe</font>-ôóíêöèé â òàêîì âèäå. Ïîëó÷èëñÿ áû òàêîé áîëüøîé îòñòóï âïðàâî, ÷òî ÷èòàåìîñòü ñèëüíî ïîñòðàäàëà áû, è îáùàÿ ñòðóêòóðà âû÷èñëåíèé ïîòåðÿëàñü áû â ëàáèðèíòå âëîæåííûõ <font color=blue>case</font>-âûðàæåíèé. Íî ñ ïîìîùüþ ìîíàä êîìïîçèöèÿ äåñÿòè ôóíêöèé çàïèñûâàåòñÿ ïðîñòî:
-
- <blockquote>f11 <font color="#66cc66"><b>=</b></font> f1 <font color="#339933">>=></font> f2 <font color="#339933">>=></font> f3 <font color="#339933">>=></font> f4 <font color="#339933">>=></font> f5 <font color="#339933">>=></font> f6 <font color="#339933">>=></font> f7 <font color="#339933">>=></font> f8 <font color="#339933">>=></font> f9 <font color="#339933">>=></font> f10</blockquote>
-
- èëè (ñ èñïîëüçîâàíèåì <font color=blue>>>=</font>):
-
- <blockquote>f11 x <font color="#66cc66"><b>=</b></font> f1 x <font color="#339933">>>=</font> f2 <font color="#339933">>>=</font> f3 <font color="#339933">>>=</font> f4 <font color="#339933">>>=</font> f5 <font color="#339933">>>=</font> f6 <font color="#339933">>>=</font> f7 <font color="#339933">>>=</font> f8 <font color="#339933">>>=</font> f9 <font color="#339933">>>=</font> f10</blockquote>
-
- Ñ ïîìîùüþ ìîíàä êîìïîçèöèÿ ìîíàäè÷åñêèõ ôóíêöèé òàêàÿ æå ïðîñòàÿ, êàê êîìïîçèöèÿ îáû÷íûõ (íåìîíàäè÷åñêèõ) ôóíêöèé.
-
- Ìîíàäà <font color=blue>Maybe</font> î÷åíü ïîëåçíà äëÿ ïîÿñíåíèÿ áàçîâûõ êîíöåïöèé, íî îíà ìîæåò ñáèòü ñ òîëêó: ìíîãèå ëþäè îøèáî÷íî âåðÿò, ÷òî åäèíñòâåííàÿ ðîëü ìîíàä â îáðàáîòêå íåôóíêöèîíàëüíûõ âû÷èñëåíèé, òî åñòü, òåõ âû÷èñëåíèé, êîòîðûå ðàáîòàþò ñ ââîäîì/âûâîäîì (ñ êîíñîëüþ èëè ñ ôàéëîì), ñ èçìåíÿåìûì ãëîáàëüíûì ñîñòîÿíèåì, è òàê äàëåå. À ÿ ïîêàçàë, ÷òî íåêîòîðûå ìîíàäè÷åñêèå âû÷èñëåíèÿ ìîãóò áûòü ñ òåì æå óñïåõîì âûïîëíåíû ñîâñåì áåç ìîíàä. Ïîëó÷àåòñÿ, ÷òî ìîíàäû íå ÷òî-òî îáÿçàòåëüíîå, îíè ïðîñòî <i>î÷åíü</i> óäîáíû. Èìåííî ïîýòîìó ÿ ãîâîðèë, ÷òî äàæå íåñìîòðÿ íà <i>ïåðâîíà÷àëüíóþ</i> ïðè÷èíó èçîáðåòåíèÿ ìîíàä äëÿ íåôóíêöèîíàëüíûõ âû÷èñëåíèé (ðàáîòà ñ <font color=blue>IO</font>), ó íèõ, êàê îêàçàëîñü, ãîðàçäî áîëüøàÿ ïðèìåíèìîñòü. Èç-çà ýòîãî ìîíàäû õîðîøè.
-
- À òåïåðü ïåðåéäåì ê ñëåäóþùåé ìîíàäå.
-
- Ìîíàäà <font color=blue>list</font> (ñïèñîê)
-
- Åñëè ìîíàäà <font color=blue>Maybe</font> âàì ïðîñòî ïîíðàâèëàñü, òî ìîíàäó <font color=blue>list</font> âû äàæå ïîëþáèòå. ;-)  äàííîì ñëó÷àå ìû çàïîëíèì ñëåäóþùåå îïðåäåëåíèå:
-
- <blockquote><font color="#06c">instance</font> <font color=green><a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:Monad">Monad</a></font> <font>[</font><font>]</font> <font color="#06c">where</font><br/>
- <font>(</font><font color="#339933">>>=</font><font>)</font> <font color="#66cc66"><b>=</b></font> <i><font color="#5d478b">{- definition of >>= for lists -}</font></i><br/>
- <font>return</font> <font color="#66cc66"><b>=</b></font> <i><font color="#5d478b">{- definition of return for lists -}</font></i></blockquote>
-
- Çàìåòüòå, ÷òî äëÿ ïðåäñòàâëåíèÿ ïóñòîãî ñïèñêà <font color=blue>[]</font> ìû èñïîëüçóåì ñïèñêîâûé êîíñòðóêòîð òèïà. Ýòî íåáîëüøîé õàê (äëÿ ñïèñêîâ â Haskell âøèòà ñïåöèàëüíàÿ ñèíòàêñè÷åñêàÿ ïîääåðæêà). Íî íè÷åãî íå ïîäåëàåøü.
-
- Êàê è äëÿ âñåõ ìîíàä, ïåðâîé çàäà÷åé áóäåò ïîíÿòü, ÷òî ïðåäñòàâëÿþò èç ñåáÿ ìîíàäè÷åñêèå ôóíêöèè ýòîé ìîíàäû. Äëÿ ñïèñêà ìîíàäè÷åñêàÿ ôóíêöèÿ <font color=blue>f</font> âûãëÿäèò òàê:
-
- <blockquote>f <font color="#66cc66"><b>::</b></font> a <font color="#339933">-></font> <font>[</font>b<font>]</font></blockquote>
-
- (ãäå <font color=blue>[b]</font> çíà÷èò, êîíå÷íî, "ñïèñîê ýëåìåíòîâ òèïà <font color=blue>b</font>"). Âñïîìíèòå, ÷òî îáîáùåííîå îïðåäåëåíèå ìîíàäè÷åñêîé ôóíêöèè çàïèñûâàåòñÿ ñëåäóþùèì îáðàçîì:
-
- <blockquote>f <font color="#66cc66"><b>::</b></font> a <font color="#339933">-></font> m b</blockquote>
-
- äëÿ íåêîòîðîé ìîíàäû <font color=blue>m</font>, êîòîðàÿ äîëæíà áûòü êîíñòðóêòîðîì òèïà. Ñïèñîê - î÷åâèäíûé êàíäèäàò â ìîíàäó, ïîñêîëüêó "ñïèñîê èç" - ýòî êîíñòðóêòîð òèïà (ïóñòü äàæå åãî ñèíòàêñèñ æåñòêî çàøèò â Haskell); ïî æåëàíèþ, ìû ìîãëè áû îïðåäåëèòü ñïèñîê ñàìè:
-
- <blockquote><font color="#06c">data</font> List a <font color="#66cc66"><b>=</b></font> Nil <font color="#339933">|</font> Cons a <font>(</font>List a<font>)</font></blockquote>
-
- Òèï ìîíàäè÷åñêàÿ ôóíêöèé äëÿ íåãî âûãëÿäåë áû ñîîòâåòñòâåííî:
-
- <blockquote>f <font color="#66cc66"><b>::</b></font> a <font color="#339933">-></font> List b</blockquote>
-
- Íî ìû áóäåì âñå-òàêè ïðèäåðæèâàòüñÿ ñòàíäàðòíîãî ñèíòàêñèñà.
-
- ×åì ÿâëÿþòñÿ ôóíêöèè ïîäîáíîãî ñîðòà? Îáû÷íî èõ ïîíèìàþò êàê ôóíêöèè, êîòîðûå áåðóò âõîäíîå çíà÷åíèå òèïà <font color=blue>a</font> è ïðîèçâîäÿò êó÷ó çíà÷åíèé òèïà <font color=blue>b</font>, ñîáðàííûõ â îäèí óäîáíûé êîíòåéíåð (ñïèñîê). (È îïÿòü ó íàñ ìîíàäà, êîòîðàÿ âûãëÿäèò êàê êîíòåéíåð.) Äðóãîé ñïîñîá äóìàòü î íèõ êàê î ôóíêöèÿõ, âîçâðàùàþùèõ ìíîæåñòâî çíà÷åíèé, òî åñòü, òàêèå ôóíêöèè âîçâðàùàþò êó÷ó ðàçíûõ çíà÷åíèé "â îäíîì". (ß íå èìåþ â âèäó "ïàðàëëåëüíî", ïîòîìó ÷òî ýòî ïîäðàçóìåâàåò ïàðàëëåëüíóþ îáðàáîòêó, ÷åãî çäåñü íåò.) Ìíîæåñòâåííûå âûõîäíûå çíà÷åíèÿ - ýòî ïðîñòî ýëåìåíòû ñïèñêà. Ïðè èñïîëüçîâàíèè ôóíêöèé íàïîäîáèå ñëåäóþùèõ îòêðûâàþòñÿ ïîëåçíûå ïåðñïåêòèâû:
-
- <blockquote>f <font color="#66cc66"><b>::</b></font> <font color=green><a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:Int">Int</a></font> <font color="#339933">-></font> <font>[</font><font color=green><a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:Int">Int</a></font><font>]</font><br/>
- g <font color="#66cc66"><b>::</b></font> <font color=green><a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:Int">Int</a></font> <font color="#339933">-></font> <font>[</font><font color=green><a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:Int">Int</a></font><font>]</font></blockquote>
-
- Çäåñü è <font color=blue>f</font>, è <font color=blue>g</font> ïðèíèìàþò îäíî <font color=blue>Int</font>-çíà÷åíèå è âîçâðàùàþò ìíîãî <font color=blue>Int</font>-çíà÷åíèé. À ÷òî åñëè ìû õîòèì âçÿòü êàæäûé ðåçóëüòàò ôóíêöèè <font color=blue>f</font> è ïðèìåíèòü åãî ê êàæäîìó ðåçóëüòàòó ôóíêöèè <font color=blue>g</font>, êîëëåêöèîíèðóÿ ðåçóëüòàòû ïðèìåíåíèÿ? Áûëî áû çäîðîâî, åñëè áû ýòî ìîæíî áûëî ñäåëàòü íåïîñðåäñòâåííî, áåç ðàñïàêîâêè êàæäîãî ýëåìåíòà èç ñïèñêîâ-ðåçóëüòàòîâ ôóíêöèé <font color=blue>g</font> è <font color=blue>f</font>. È ýòî ìîæíî ñäåëàòü ñ ïîìîùüþ ìîíàäû ñïèñêà.
-
- Äàâàéòå ïåðåéäåì ê áîëåå ìàòåðèàëüíûì ïðèìåðàì ýòèõ ôóíêöèé:
-
- <blockquote>f <font color="#66cc66"><b>::</b></font> <font color=green><a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:Int">Int</a></font> <font color="#339933">-></font> <font>[</font><font color=green><a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:Int">Int</a></font><font>]</font><br/>
- f x <font color="#66cc66"><b>=</b></font> <font>[</font>x<font color="#339933">-</font><font color=red>1</font><font color="#339933">,</font> x<font color="#339933">,</font> x<font color="#339933">+</font><font color=red>1</font><font>]</font><br/>
- <br/>
- g <font color="#66cc66"><b>::</b></font> <font color=green><a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:Int">Int</a></font> <font color="#339933">-></font> <font>[</font><font color=green><a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:Int">Int</a></font><font>]</font><br/>
- g x <font color="#66cc66"><b>=</b></font> <font>[</font><font color="#339933">-</font>x<font color="#339933">,</font> x<font>]</font></blockquote>
-
- Êàê æå íàì "ñêîìïîíîâàòü" ýòè äâå ôóíêöèè? <font color=blue>f x</font> âîçâðàùàåò ñïèñîê, è äëÿ ïðèìåíåíèÿ <font color=blue>g</font> ê êàæäîìó ýëåìåíòó íàì íóæíà ôóíêöèÿ <font color=blue>map</font>:
-
- <blockquote>f <font color=red>10</font> <font color="#339933">--></font> <font>[</font><font color=red>9</font><font color="#339933">,</font> <font color=red>10</font><font color="#339933">,</font> <font color=red>11</font><font>]</font><br/>
- <font>map</font> g <font>(</font>f <font color=red>10</font><font>)</font> <font color="#339933">--></font> <font>[</font><font>[</font><font color="#339933">-</font><font color=red>9</font><font color="#339933">,</font> <font color=red>9</font><font>]</font><font color="#339933">,</font> <font>[</font><font color="#339933">-</font><font color=red>10</font><font color="#339933">,</font> <font color=red>10</font><font>]</font><font color="#339933">,</font> <font>[</font><font color="#339933">-</font><font color=red>11</font><font color="#339933">,</font> <font color=red>11</font><font>]</font><font>]</font></blockquote>
-
- Ýòîò íîâûé ðåçóëüòàò èíòåðåñåí, íî îí íå ìîæåò áûòü êîìïîçèöèåé <font color=blue>f</font> è <font color=blue>g</font>, ïîòîìó ÷òî ó íåãî äðóãîé òèï (ñïèñîê ñïèñêîâ <font color=blue>Int</font>, à íå ïðîñòî ñïèñîê <font color=blue>Int</font>). Ìû ìîæåì åãî ñãëàäèòü â ïðîñòîé ñïèñîê ôóíêöèåé <font color=blue>concat</font> (êîòîðàÿ ïðîñòî ñîåäèíÿåò ñïèñêè â îäèí):
-
- <blockquote><font color="#5d478b">-- Îáðàòèòå îñîáîå âíèìàíèå íà òèï concat: [[a]] -> [a]</font><br/>
- <font>concat</font> <font>(</font><font>map</font> g <font>(</font>f <font color=red>10</font><font>)</font><font>)</font> <font color="#339933">--></font> <font>[</font><font color="#339933">-</font><font color=red>9</font><font color="#339933">,</font> <font color=red>9</font><font color="#339933">,</font> <font color="#339933">-</font><font color=red>10</font><font color="#339933">,</font> <font color=red>10</font><font color="#339933">,</font> <font color="#339933">-</font><font color=red>11</font><font color="#339933">,</font> <font color=red>11</font><font>]</font></blockquote>
-
- Ìû ïîëó÷èëè íàáîð âñåõ ðåçóëüòàòîâ, ïðîèçâåäåííûõ ÷åðåç ïðèìåíåíèå <font color=blue>f</font> ê öåëîìó ÷èñëó è çàòåì ïðèìåíèâ <font color=blue>g</font> ê òîìó, ÷òî ïîëó÷èëîñü ïîñëå <font color=blue>f</font>. Åñëè âû äóìàåòå îá <font color=blue>f</font> è <font color=blue>g</font> êàê î ôóíêöèÿõ, êîòîðûå ñîçäàþò ìíîæåñòâî ðåçóëüòàòîâ "çäåñü è ñåé÷àñ", èõ âûõîäíûå çíà÷åíèÿ áóäóò ìíîæåñòâîì âñåõ âîçìîæíûõ ïðèìåíåíèé ñíà÷àëà ôóíêöèè <font color=blue>f</font>, à çàòåì ôóíêöèè <font color=blue>g</font>. Ìû ìîæåì ïðåäñòàâèòü ýòî â âèäå äèàãðàììû:
-
- <pre>
- g | -9
- | 9 ----> |
- | | 9
- |
- f | g | -10
- 10 ----> | 10 ----> |
- | | 10
- |
- | g | -11
- | 11 ----> |
- | 11</pre>
-
- Õîðîøî âèäíî, ÷òî êîìïîçèöèÿ <font color=blue>f</font> è <font color=blue>g</font> - ýòî ìíîæåñòâî âñåõ ïóòåé ìåæäó <font color=blue>f</font> è <font color=blue>g</font>.
-
- Ëþáîïûòíî, ÷òî ìû òîëüêî ÷òî îïðåäåëèëè îïåðàòîð <font color=blue>>>=</font> äëÿ ìîíàäû ñïèñêà! Îí çàäàí òàê:
-
- <blockquote><font color="#5d478b">-- mv :: [a]</font><br/>
- <font color="#5d478b">-- g :: a -> [b]</font><br/>
- mv <font color="#339933">>>=</font> g <font color="#66cc66"><b>=</b></font> <font>concat</font> <font>(</font><font>map</font> g mv<font>)</font></blockquote>
-
- ãäå <font color=blue>mv</font> - ýòî ìîíàäè÷åñêîå çíà÷åíèå â ìîíàäå ñïèñêà (êîòîðîå ïðîñòî ñïèñîê çíà÷åíèé òèïà <font color=blue>a</font>).  ïðåäûäóùåì ïðèìåðå <font color=blue>mv</font> - ýòî ðåçóëüòàò âû÷èñëåíèÿ <font color=blue>f 10</font>. Îïðåäåëåíèå ðàáîòàåò äàæå äëÿ ïóñòîãî ñïèñêà <font color=blue>[]</font>, ïîñêîëüêó îòîáðàæåíèå (mapping) ôóíêöèè íà ïóñòîé ñïèñîê äàñò ïóñòîé ñïèñîê, è <font color=blue>concat</font> äëÿ ïóñòîãî ñïèñêà òîæå âñåãäà ïóñòîé ñïèñîê. Ïîëó÷èëîñü î÷åíü ïðîñòîå îïðåäåëåíèå îïåðàòîðà <font color=blue>>>=</font>.
-
- [Çàìåòêà äëÿ ôàíàòîâ GHC: ß âåðþ, ÷òî îïåðàòîð <font color=blue>>>=</font> â êîìïèëÿòîðå GHC ðåàëèçîâàí áîëåå ýôôåêòèâíî è ïî-äðóãîìó, õîòÿ è äåëàåò òî æå ñàìîå.]
-
- Êàê çàäàòü <font color=blue>return</font> äëÿ ýòîé ìîíàäû? Äàâàéòå ïîäóìàåì î ìîíàäè÷åñêîì çíà÷åíèè-ñïèñêå êàê î "äåéñòâèè", âîçâðàùàþùåì ìíîãî çíà÷åíèé. Âñïîìíèì, ÷òî <font color=blue>return</font> äîëæåí áûòü ýêâèâàëåíòîì åäèíè÷íîé ôóíêöèè, - êàê è â äðóãèõ ìîíàäàõ. ×òî áóäåò ýêâèâàëåíòîì åäèíè÷íîé ôóíêöèè â ìîíàäå ñïèñêà? Îíà äîëæíà áðàòü çíà÷åíèå è âîçâðàùàòü "äåéñòâèå", êîòîðîå ïîñëå "âû÷èñëåíèÿ" ïðîñòî âåðíåò ýòî çíà÷åíèå. Òàê ìû ïîíÿëè, ÷òî <font color=blue>return</font> íå ìîæåò ïðîñòî âîçâðàùàòü ïóñòîé ñïèñîê. Ðàçóìíî ïðåäïîëîæèòü î <font color=blue>return</font> ÷òî-òî òàêîå:
-
- <blockquote><font>return</font> <font color="#66cc66"><b>::</b></font> a <font color="#339933">-></font> <font>[</font>b<font>]</font><br/>
- <font>return</font> x <font color="#66cc66"><b>=</b></font> <font>[</font>x<font>]</font></blockquote>
-
- Òî åñòü, <font color=blue>return</font> ýëåìåíòàðíî ñîçäàåò ñïèñîê èç îòäåëüíîãî çíà÷åíèÿ. Ïðîâåðèì, ñîáëþäàþòñÿ ëè â ýòîì ñëó÷àå ìîíàäíûå çàêîíû:
-
- <blockquote><font color="#5d478b">-- f :: a -> [b]</font><br/>
- <font color="#5d478b">-- x :: a</font><br/>
- <font>return</font> x <font color="#339933">>>=</font> f <font color="#66cc66"><b>=</b></font> <font>concat</font> <font>(</font><font>map</font> f <font>(</font><font>return</font> x<font>)</font><font>)</font> <font color="#5d478b">-- ïî îïðåäåëåíèþ >>=</font><br/>
- <font color="#66cc66"><b>=</b></font> <font>concat</font> <font>(</font><font>map</font> f <font>[</font>x<font>]</font><font>)</font> <font color="#5d478b">-- ïî îïðåäåëåíèþ return</font><br/>
- <font color="#66cc66"><b>=</b></font> <font>concat</font> <font>[</font>f x<font>]</font> <font color="#5d478b">-- ïî îïðåäåëåíèþ map</font><br/>
- <font color="#66cc66"><b>=</b></font> f x <font color="#5d478b">-- ïî îïðåäåëåíèþ concat</font><br/>
- <font color="#5d478b">-- âûïîëíåíèå ïåðâîãî ìîíàäíîãî çàêîíà</font><br/>
- <br/>
- <font color="#5d478b">-- mv :: [a]</font><br/>
- mv <font color="#339933">>>=</font> <font>return</font> <font color="#66cc66"><b>=</b></font> <font>concat</font> <font>(</font><font>map</font> <font>return</font> mv<font>)</font> <font color="#5d478b">-- ïî îïðåäåëåíèþ >>=</font><br/>
- <font color="#66cc66"><b>=</b></font> <font>concat</font> <font>(</font><font>map</font> <font>(</font>\x <font color="#339933">-></font> <font>[</font>x<font>]</font><font>)</font> mv<font>)</font> <font color="#5d478b">-- ïî îïðåäåëåíèþ return</font><br/>
- <font color="#5d478b">-- Äâà ñëó÷àÿ:</font><br/>
- <font color="#5d478b">-- Ñëó÷àé 1: mv == []</font><br/>
- <font color="#66cc66"><b>=</b></font> <font>concat</font> <font>(</font><font>map</font> <font>(</font>\x <font color="#339933">-></font> <font>[</font>x<font>]</font><font>)</font> <font>[</font><font>]</font><font>)</font> <font color="#5d478b">-- ïî îïðåäåëåíèþ mv</font><br/>
- <font color="#66cc66"><b>=</b></font> <font>concat</font> <font>[</font><font>]</font> <font color="#5d478b">-- ïî îïðåäåëåíèþ map</font><br/>
- <font color="#66cc66"><b>=</b></font> <font>[</font><font>]</font> <font color="#5d478b">-- ïî îïðåäåëåíèþ concat</font><br/>
- <font color="#66cc66"><b>=</b></font> mv <font color="#5d478b">-- ïî îïðåäåëåíèþ mv</font><br/>
- <font color="#5d478b">-- Ñëó÷àé 2: mv == [v1, v2, ...]</font><br/>
- <font color="#66cc66"><b>=</b></font> <font>concat</font> <font>(</font><font>map</font> <font>(</font>\x <font color="#339933">-></font> <font>[</font>x<font>]</font><font>)</font> <font>[</font>v1<font color="#339933">,</font> v2<font color="#339933">,</font> <font color="#339933">...</font><font>]</font><font>)</font> <font color="#5d478b">-- ïî îïðåäåëåíèþ mv</font><br/>
- <font color="#66cc66">