<?xml version="1.0" encoding="utf-8"?>
<feed
    xmlns="http://www.w3.org/2005/Atom"
    xmlns:at="http://www.sixapart.com/ns/at"
    xmlns:icbm="http://postneo.com/icbm"
    xmlns:rvw="http://purl.org/NET/RVW/0.2/"
    xml:lang="en">
    <title>Miguel</title>
    <link rel="self" type="application/atom+xml" title="Miguel (Atom)" href="http://migmit.vox.com/library/posts/page/1/atom.xml" />
    <link rel="alternate" type="text/html" title="Miguel" href="http://migmit.vox.com/library/posts/page/1/"/> 
    <link rel="service.post" type="application/atom+xml" title="Miguel" href="http://www.vox.com/services/atom/svc=post/collection_id=6a00e398c5c26f000500e398c5c9520003" /> 
    <link rel="service.subscribe" type="application/atom+xml" title="Miguel" href="http://migmit.vox.com/library/posts/atom.xml" />    
    <link rel="next" type="application/atom+xml" title="Miguel" href="http://migmit.vox.com/library/posts/page/2/atom.xml" /> 
    <link rel="last" type="application/atom+xml" title="Miguel" href="http://migmit.vox.com/library/posts/page/11/atom.xml" />  
    <generator uri="http://www.vox.com/">Vox</generator>
    <updated>2009-10-14T19:19:30Z</updated> 
    <author>
        <name>migmit</name>
        <uri>http://migmit.vox.com/?_c=feed-atom-full</uri>
    </author> 
    <id>tag:vox.com,2006:6p00e398c5c26f0005/</id>  
    
    <entry>
        <title>Мысли в кучу</title>   
        <link rel="alternate" type="text/html" title="Мысли в кучу" href="http://migmit.vox.com/library/post/%D0%BC%D1%8B%D1%81%D0%BB%D0%B8-%D0%B2-%D0%BA%D1%83%D1%87%D1%83.html?_c=feed-atom-full" />  
        <link rel="service.post" type="application/atom+xml" title="Мысли в кучу" href="http://migmit.vox.com/library/post/%D0%BC%D1%8B%D1%81%D0%BB%D0%B8-%D0%B2-%D0%BA%D1%83%D1%87%D1%83.html?_c=feed-atom-full#comments" /> 
        <link rel="service.edit" type="application/atom+xml" title="Мысли в кучу" href="http://www.vox.com/atom/svc=post/asset_id=6a00e398c5c26f000501240b68fc1d860e" />          <id>tag:vox.com,2009-10-13:asset-6a00e398c5c26f000501240b68fc1d860e</id>
        <published>2009-10-13T21:14:15Z</published>
        <updated>2009-10-14T19:19:30Z</updated>
    
        <author>
            <name>migmit</name>
            <uri>http://migmit.vox.com/?_c=feed-atom-full</uri>
        </author>
    
        
        <content type="html" xml:base="http://migmit.vox.com/?_c=feed-atom-full">
            <![CDATA[
                <div xmlns="http://www.w3.org/1999/xhtml" xmlns:at="http://www.sixapart.com/ns/at">
        <p>Смотрю новый сериал FlashForward. Сюжет пересказывать не буду, желающие узнают всё необходимое, например, <a href="http://geroneja.diary.ru">вот здесь</a>. Просто соберу в кучу некоторые вопросы и теории, а потом посмотрим - что из этого оправдается, и на что будет дан ответ.<br /><dl><dt>То, в чём я не сомневаюсь.</dt><br /><dd><ol><li>Никаких инопланетян, ангелов, чертей, вампиров (увы), господа бога или Святого Ника. Если другой разум - отличный от человеческого - появится в последней серии, то это будет совершенно дикий рояль в кустах. Если не в последней - тот факт, что именно эти гады виноваты в происшедшем, станет, к сожалению, очевидным.</li><br /><li>Никакой мистики вообще. Если бы в этом сериале была возможна мистика - она бы уже проявилась, три серии, как-никак.</li><br /><li>Не природный катаклизм. Слишком легко списать всё на стихию. Обесценивает всё проведённое расследование.</li></ol></dd><br /><dt>Теории</dt><br /><dd><ol><li>Теория темпорального эха. Пока что все персонажи считают, что, кто бы ни стоял за происшедшим, он уже всё сделал. Нажал кнопку, или что там ещё. Но, поскольку мы и так имеем дело с временной аномалией, почему не допустить, что всё произойдёт 29 марта (30-го в Европе), а имевшее место затемнение - просто эхо, откатившееся НАЗАД во времени.</li><br /><li>Теория шахматиста. Только у меня возникает ощущение, что наши ФБР-овцы не столько расследование ведут, сколько реагируют на ниточки, которые кто-то осознанно дёргает? И если да, то не может ли быть так, что цель затемнения - или одна из целей - это добиться того, чтобы главные герои сделали что-то или оказались где-то?</li></ol></dd><br /><dt>Вопросы</dt><br /><dd><ol><li>Может ли вообще наступить то будущее, которое было в видениях? Ни в жисть не поверю, что не найдётся человек, достаточно упрямый, чтобы просто назло судьбе сделать наоборот. В конце концов, для этого не много нужно. Один из ФБР-овцев говорил, если не вру, что в его видении он смотрел новости по телевизору. Что ему будет стоить выключить телевизор в соответствующее время, тем более, что оно хорошо известно. С другой стороны, некоторые, по-видимому, должны к этому времени умереть. Возможно, события подгадают таким образом, чтобы именно эти упрямцы и умерли?</li><br /><li>Дима Но. С одной стороны, похоже, он умрёт. С другой стороны, слишком уж активно нас подталкивают к тому, что именно это и должно случиться. И именно это, в свою очередь, напоминает о теории шахматиста - сначала Димке подсунули шерифшу, которая тут же и умерла, потом последовал звонок фиг знает откуда. Ему как бы не говорят прямым текстом (звонок по телефону не есть прямой текст, ибо его таинственность внушает сомнения), а подводят к такому убеждению. Возможно, шахматист хочет, чтобы Димка верил, что умрёт - как, скажем, в Drive профессор верил в свою обречённость, и в результате действовал так, как никогда бы не подумал действовать, будь его здоровье в порядке.</li><br /><li>Нулевой. Поведение этого товарища очень странно. Если он не знал о затемнении - то почему вёл себя так спокойно? Не паниковал, даже не торопился найти какое-нибудь укрытие (то, что сделал бы я). Спокойно прошёл по трибуне и удалился. Может быть, он душевнобольной? Интересно, аутисты посещают спортивные мероприятия, или им до фени? Если он знал - почему он вообще оказался на этом стадионе? Почему не отсиделся дома? Если он хотел понаблюдать за толпой - кто мешал ему выбрать местечко на крыше небоскрёба и смотреть на какую-нибудь оживлённую улицу? Может, он хотел запечатлеться на камеру? Согласуется с теорией шахматиста, но что-то в этом направлении никакого продвижения пока не видно. Может быть, он не ЗНАЛ о затемнении, но быстро всё понял? Скажем, если это талантливый физик, который зарание просчитал, что что-то подобное может быть результатом, например, включения Большого Гудронного Уклайдера? Кстати, это согласуется с теорией темпорального эха. А по телефону он тогда разговаривал со своим приятелем, который тоже был в курсе этой теории - Алё, Вовка? У тебя там такой же бардак, как и здесь? А что я тебе говорил? Вот-вот, и не зря мы те таблетки принимали, а то тоже валялись бы по земле.</li><br /><li>Ди Гиббонс. Разговор по телефону с Нулевым согласуется с гипотезой, что они хотели быть обнаруженными (трудно было бы представить, что ФБР не узнает рано или поздно, что во время затемнения случился разговор по телефону) - и с теорией шахматиста. С другой стороны, как сказано в предыдущем пункте, может согласовываться и с теорией темпорального эха. Что о нём знает Чарли и почему она называет Гиббонса &quot;Ди&quot;? Не &quot;Дэвид Гиббонс&quot;, не &quot;мистер Гиббонс&quot;, а именно &quot;Ди&quot;? Может быть, имя Гиббонса было где-нибудь написано? Умеет ли Чарли в её возрасте читать? Вероятно, да. Не является ли &quot;Ди Гиббонс&quot; кивком в сторону Дейва Гиббонса, соавтора &quot;Вотчменов&quot;? Последнее уже к загадкам сериала не относится.</li><br /><li>Герр Гейер. Уж больно аккуратно он их развёл. Кто знает, может быть, его освобождение было одной из целей шахматиста (буде таковой существует)?</li><br /><li>Сам феномен бодрствования во время затемнения. Поведение Нулевого может быть объяснено разными причинами, а вот его телефонный разговор с другим бодрствующим практически доказывает, что они сохранили сознание не случайно. Они что-то делали для этого. С другой стороны, мальчик в сомалийском флэшбеке точно был никак не связан с организаторами безобразия. У него шрам на лице - может быть, это как-то связано с его бодрствованием? Согласуется с гипотезой о психическом заболевании. Возможно, Нулевой и Ди Гиббонс страдают одним и тем же заболеванием? Может быть, они подружились на сеансе групповой терапии и когда началось затемнении, один просто рефлекторно позвонил своему единственному другу? Согласуется с тем, что поведение Гиббонса во время попытки ареста было, скажем так, неадекватным. Однако неужели подобное - явно редкое - заболевание оставит после себя лишь небольшой шрам на лбу, причём в стране, где доктор Хаус не живёт?</li><br /><li>Что это за фаллический символ стоял в Сомали и что за белая субстанция из него выплеснулась? Да, я осознаю, что вопрос пошлый.<br /><br /></li><li>Те спецназовцы в видении Марка. Они шли за ним? Или за Стэном? Если бы Стэн находился у себя, то он был бы поблизости - Марк его, помнится, даже спрашивал, не видел ли он чего-нибудь. Он в это время сидел в сортире, но киллеры могли этого не знать.<br /></li></ol></dd></dl><br /> </p>   <p style="clear:both;"> 
    <a href="http://migmit.vox.com/library/post/%D0%BC%D1%8B%D1%81%D0%BB%D0%B8-%D0%B2-%D0%BA%D1%83%D1%87%D1%83.html?_c=feed-atom-full#comments">Read and post comments</a>   |   
    <a href="http://www.vox.com/share/6a00e398c5c26f000501240b68fc1d860e?_c=feed-atom-full">Send to a friend</a> 
</p>

                </div>
            ]]>
        </content> 
    </entry> 
    
    <entry>
        <title>Хозяйке на заметку</title>   
        <link rel="alternate" type="text/html" title="Хозяйке на заметку" href="http://migmit.vox.com/library/post/%D1%85%D0%BE%D0%B7%D1%8F%D0%B9%D0%BA%D0%B5-%D0%BD%D0%B0-%D0%B7%D0%B0%D0%BC%D0%B5%D1%82%D0%BA%D1%83.html?_c=feed-atom-full" />  
        <link rel="service.post" type="application/atom+xml" title="Хозяйке на заметку" href="http://migmit.vox.com/library/post/%D1%85%D0%BE%D0%B7%D1%8F%D0%B9%D0%BA%D0%B5-%D0%BD%D0%B0-%D0%B7%D0%B0%D0%BC%D0%B5%D1%82%D0%BA%D1%83.html?_c=feed-atom-full#comments" /> 
        <link rel="service.edit" type="application/atom+xml" title="Хозяйке на заметку" href="http://www.vox.com/atom/svc=post/asset_id=6a00e398c5c26f00050123f168d194860f" />          <id>tag:vox.com,2009-10-06:asset-6a00e398c5c26f00050123f168d194860f</id>
        <published>2009-10-06T21:03:04Z</published>
        <updated>2009-10-07T20:25:02Z</updated>
    
        <author>
            <name>migmit</name>
            <uri>http://migmit.vox.com/?_c=feed-atom-full</uri>
        </author>
    
        
        <content type="html" xml:base="http://migmit.vox.com/?_c=feed-atom-full">
            <![CDATA[
                <div xmlns="http://www.w3.org/1999/xhtml" xmlns:at="http://www.sixapart.com/ns/at">
        <p>Текущие настройки mencoder-а для конвертации видео на айфон:</p><p>mencoder <strong><em>источник</em></strong>.avi -o <strong><em>результат</em></strong>.mp4 -vf dsize=480:320:0,scale=-8:-8,harddup -oac faac -faacopts mpeg=4:object=2:raw:br=128 -of lavf -lavfopts format=mp4 -ovc x264 -x264encopts nocabac:level_idc=30:bframes=0:global_header:threads=auto:subq=5:frameref=6:partitions=all:trellis=1:chroma_me:me=umh:bitrate=500:no8x8dct </p><p>Вот так вот.<br /> </p>   <p style="clear:both;"> 
    <a href="http://migmit.vox.com/library/post/%D1%85%D0%BE%D0%B7%D1%8F%D0%B9%D0%BA%D0%B5-%D0%BD%D0%B0-%D0%B7%D0%B0%D0%BC%D0%B5%D1%82%D0%BA%D1%83.html?_c=feed-atom-full#comments">Read and post comments</a>   |   
    <a href="http://www.vox.com/share/6a00e398c5c26f00050123f168d194860f?_c=feed-atom-full">Send to a friend</a> 
</p>

                </div>
            ]]>
        </content> 
    </entry> 
    
    <entry>
        <title>Code Jam</title>   
        <link rel="alternate" type="text/html" title="Code Jam" href="http://migmit.vox.com/library/post/code-jam.html?_c=feed-atom-full" />  
        <link rel="service.post" type="application/atom+xml" title="Code Jam" href="http://migmit.vox.com/library/post/code-jam.html?_c=feed-atom-full#comments" /> 
        <link rel="service.edit" type="application/atom+xml" title="Code Jam" href="http://www.vox.com/atom/svc=post/asset_id=6a00e398c5c26f00050123f164d649860f" />          <id>tag:vox.com,2009-09-26:asset-6a00e398c5c26f00050123f164d649860f</id>
        <published>2009-09-26T18:36:14Z</published>
        <updated>2009-09-26T18:36:14Z</updated>
    
        <author>
            <name>migmit</name>
            <uri>http://migmit.vox.com/?_c=feed-atom-full</uri>
        </author>
    
        
        <content type="html" xml:base="http://migmit.vox.com/?_c=feed-atom-full">
            <![CDATA[
                <div xmlns="http://www.w3.org/1999/xhtml" xmlns:at="http://www.sixapart.com/ns/at">
        <p>Итак, оно кончилось. 759 место, дальше не прохожу. Решил первую задачу и первую часть третьей - оно таки обломалось на large set. Вывод: с некоторыми базовыми алгоритмами у меня, всё-таки, плохо.<br /></p>   <p style="clear:both;"> 
    <a href="http://migmit.vox.com/library/post/code-jam.html?_c=feed-atom-full#comments">Read and post comments</a>   |   
    <a href="http://www.vox.com/share/6a00e398c5c26f00050123f164d649860f?_c=feed-atom-full">Send to a friend</a> 
</p>

                </div>
            ]]>
        </content> 
    </entry> 
    
    <entry>
        <title>Почувстовал себя персонажем анекдота</title>   
        <link rel="alternate" type="text/html" title="Почувстовал себя персонажем анекдота" href="http://migmit.vox.com/library/post/%D0%BF%D0%BE%D1%87%D1%83%D0%B2%D1%81%D1%82%D0%BE%D0%B2%D0%B0%D0%BB-%D1%81%D0%B5%D0%B1%D1%8F-%D0%BF%D0%B5%D1%80%D1%81%D0%BE%D0%BD%D0%B0%D0%B6%D0%B5%D0%BC-%D0%B0%D0%BD%D0%B5%D0%BA%D0%B4%D0%BE%D1%82%D0%B0.html?_c=feed-atom-full" />  
        <link rel="service.post" type="application/atom+xml" title="Почувстовал себя персонажем анекдота" href="http://migmit.vox.com/library/post/%D0%BF%D0%BE%D1%87%D1%83%D0%B2%D1%81%D1%82%D0%BE%D0%B2%D0%B0%D0%BB-%D1%81%D0%B5%D0%B1%D1%8F-%D0%BF%D0%B5%D1%80%D1%81%D0%BE%D0%BD%D0%B0%D0%B6%D0%B5%D0%BC-%D0%B0%D0%BD%D0%B5%D0%BA%D0%B4%D0%BE%D1%82%D0%B0.html?_c=feed-atom-full#comments" /> 
        <link rel="service.edit" type="application/atom+xml" title="Почувстовал себя персонажем анекдота" href="http://www.vox.com/atom/svc=post/asset_id=6a00e398c5c26f00050110164b36d4860b" />          <id>tag:vox.com,2009-09-01:asset-6a00e398c5c26f00050110164b36d4860b</id>
        <published>2009-09-01T16:49:44Z</published>
        <updated>2009-09-01T16:49:44Z</updated>
    
        <author>
            <name>migmit</name>
            <uri>http://migmit.vox.com/?_c=feed-atom-full</uri>
        </author>
    
        
        <content type="html" xml:base="http://migmit.vox.com/?_c=feed-atom-full">
            <![CDATA[
                <div xmlns="http://www.w3.org/1999/xhtml" xmlns:at="http://www.sixapart.com/ns/at">
        <p>когда набрал в терминале &quot;which watch&quot;. </p>   <p style="clear:both;"> 
    <a href="http://migmit.vox.com/library/post/%D0%BF%D0%BE%D1%87%D1%83%D0%B2%D1%81%D1%82%D0%BE%D0%B2%D0%B0%D0%BB-%D1%81%D0%B5%D0%B1%D1%8F-%D0%BF%D0%B5%D1%80%D1%81%D0%BE%D0%BD%D0%B0%D0%B6%D0%B5%D0%BC-%D0%B0%D0%BD%D0%B5%D0%BA%D0%B4%D0%BE%D1%82%D0%B0.html?_c=feed-atom-full#comments">Read and post comments</a>   |   
    <a href="http://www.vox.com/share/6a00e398c5c26f00050110164b36d4860b?_c=feed-atom-full">Send to a friend</a> 
</p>

                </div>
            ]]>
        </content> 
    </entry> 
    
    <entry>
        <title>Первый аплоад на Hackage</title>   
        <link rel="alternate" type="text/html" title="Первый аплоад на Hackage" href="http://migmit.vox.com/library/post/%D0%BF%D0%B5%D1%80%D0%B2%D1%8B%D0%B9-%D0%B0%D0%BF%D0%BB%D0%BE%D0%B0%D0%B4-%D0%BD%D0%B0-hackage.html?_c=feed-atom-full" />  
        <link rel="service.post" type="application/atom+xml" title="Первый аплоад на Hackage" href="http://migmit.vox.com/library/post/%D0%BF%D0%B5%D1%80%D0%B2%D1%8B%D0%B9-%D0%B0%D0%BF%D0%BB%D0%BE%D0%B0%D0%B4-%D0%BD%D0%B0-hackage.html?_c=feed-atom-full#comments" /> 
        <link rel="service.edit" type="application/atom+xml" title="Первый аплоад на Hackage" href="http://www.vox.com/atom/svc=post/asset_id=6a00e398c5c26f000501101643ebbe860b" />          <id>tag:vox.com,2009-08-17:asset-6a00e398c5c26f000501101643ebbe860b</id>
        <published>2009-08-17T05:25:58Z</published>
        <updated>2009-08-20T17:13:43Z</updated>
    
        <author>
            <name>migmit</name>
            <uri>http://migmit.vox.com/?_c=feed-atom-full</uri>
        </author>
    
        
        <content type="html" xml:base="http://migmit.vox.com/?_c=feed-atom-full">
            <![CDATA[
                <div xmlns="http://www.w3.org/1999/xhtml" xmlns:at="http://www.sixapart.com/ns/at">
        <p>compose-trans-0.0</p><p>Сделан по мотивам вот <a href="http://migmit.vox.com/library/post/%D0%BA%D0%BB%D0%B0%D1%81%D1%81%D1%8B-%D0%BA%D0%B0%D0%BA-%D1%82%D0%B8%D0%BF%D1%8B.html">этого</a> поста. Очень сильно отрефакторено и упрощено. </p>   <p style="clear:both;"> 
    <a href="http://migmit.vox.com/library/post/%D0%BF%D0%B5%D1%80%D0%B2%D1%8B%D0%B9-%D0%B0%D0%BF%D0%BB%D0%BE%D0%B0%D0%B4-%D0%BD%D0%B0-hackage.html?_c=feed-atom-full#comments">Read and post comments</a>   |   
    <a href="http://www.vox.com/share/6a00e398c5c26f000501101643ebbe860b?_c=feed-atom-full">Send to a friend</a> 
</p>

                </div>
            ]]>
        </content> 
    </entry> 
    
    <entry>
        <title>Какой австралопитек</title>   
        <link rel="alternate" type="text/html" title="Какой австралопитек" href="http://migmit.vox.com/library/post/%D0%BA%D0%B0%D0%BA%D0%BE%D0%B9-%D0%B0%D0%B2%D1%81%D1%82%D1%80%D0%B0%D0%BB%D0%BE%D0%BF%D0%B8%D1%82%D0%B5%D0%BA.html?_c=feed-atom-full" />  
        <link rel="service.post" type="application/atom+xml" title="Какой австралопитек" href="http://migmit.vox.com/library/post/%D0%BA%D0%B0%D0%BA%D0%BE%D0%B9-%D0%B0%D0%B2%D1%81%D1%82%D1%80%D0%B0%D0%BB%D0%BE%D0%BF%D0%B8%D1%82%D0%B5%D0%BA.html?_c=feed-atom-full#comments" /> 
        <link rel="service.edit" type="application/atom+xml" title="Какой австралопитек" href="http://www.vox.com/atom/svc=post/asset_id=6a00e398c5c26f0005011016854ff3860c" />          <id>tag:vox.com,2009-08-10:asset-6a00e398c5c26f0005011016854ff3860c</id>
        <published>2009-08-10T09:07:44Z</published>
        <updated>2009-08-10T09:07:44Z</updated>
    
        <author>
            <name>migmit</name>
            <uri>http://migmit.vox.com/?_c=feed-atom-full</uri>
        </author>
    
        
        <content type="html" xml:base="http://migmit.vox.com/?_c=feed-atom-full">
            <![CDATA[
                <div xmlns="http://www.w3.org/1999/xhtml" xmlns:at="http://www.sixapart.com/ns/at">
        <p>делал функцию &quot;Родительский контроль&quot; в винде? Неужели он не мог посмотреть хотя бы на макось? Как вообще в его микроскопический мозг пришла мысль, что родитель должен задавать не общее время, которое чадо проводит за компом, а конкретные часы? Не &quot;два часа в день&quot;, а &quot;с 17:30 до 19:30&quot;? Или эта хуйня разрабатывалась изначально для использования в пенитенциарных учреждениях?</p><p>Почему, интересно, в макоси, да и в любом другом юниксе, никого не ебёт, какие программы юзер установит для себя лично, главное, чтобы не пытался лезть в чужие данные - а в этой куче дерьма под названием Vista по умолчанию установка софта запрещена всем не-админам? Это надо понимать как признание, что ихний выкидыш представляет собой глюк на глюке, который упадёт от первого залетевшего дятла? Какого хрена? Раньше я думал, что под админом работают только идиоты. Похоже, что в винде другого варианта вообще нет.</p><p>Ощущение такое, что виста - это не ОС, а демка. А винда Home Basic, которая шла вместе с компом - демка от демки. Повбывав бы. Уроды. Все.<br /> </p>   <p style="clear:both;"> 
    <a href="http://migmit.vox.com/library/post/%D0%BA%D0%B0%D0%BA%D0%BE%D0%B9-%D0%B0%D0%B2%D1%81%D1%82%D1%80%D0%B0%D0%BB%D0%BE%D0%BF%D0%B8%D1%82%D0%B5%D0%BA.html?_c=feed-atom-full#comments">Read and post comments</a>   |   
    <a href="http://www.vox.com/share/6a00e398c5c26f0005011016854ff3860c?_c=feed-atom-full">Send to a friend</a> 
</p>

                </div>
            ]]>
        </content> 
    </entry> 
    
    <entry>
        <title>Просто забавно</title>   
        <link rel="alternate" type="text/html" title="Просто забавно" href="http://migmit.vox.com/library/post/%D0%BF%D1%80%D0%BE%D1%81%D1%82%D0%BE-%D0%B7%D0%B0%D0%B1%D0%B0%D0%B2%D0%BD%D0%BE.html?_c=feed-atom-full" />  
        <link rel="service.post" type="application/atom+xml" title="Просто забавно" href="http://migmit.vox.com/library/post/%D0%BF%D1%80%D0%BE%D1%81%D1%82%D0%BE-%D0%B7%D0%B0%D0%B1%D0%B0%D0%B2%D0%BD%D0%BE.html?_c=feed-atom-full#comments" /> 
        <link rel="service.edit" type="application/atom+xml" title="Просто забавно" href="http://www.vox.com/atom/svc=post/asset_id=6a00e398c5c26f000501101625bcd3860b" />            <id>tag:vox.com,2009-06-30:asset-6a00e398c5c26f000501101625bcd3860b</id>
        <published>2009-06-30T18:27:24Z</published>
        <updated>2009-06-30T18:27:24Z</updated>
    
        <author>
            <name>migmit</name>
            <uri>http://migmit.vox.com/?_c=feed-atom-full</uri>
        </author>
    
        
        <content type="html" xml:base="http://migmit.vox.com/?_c=feed-atom-full">
            <![CDATA[
                <div xmlns="http://www.w3.org/1999/xhtml" xmlns:at="http://www.sixapart.com/ns/at">
        <p>Вчера всем, конечно, было не до того. Но сегодня должны были уже отойти, так что:<br />
    
    
    

    
    
    
<div at:enclosure="asset" at:xid="6a00e398c5c26f00050110166a9dd1860c" at:format="extra-large" at:align="center"
    class="enclosure enclosure-center enclosure-extra-large photo-enclosure" 
     style="text-align: center;">
<div class="enclosure-inner"
    
        style="padding: 9px; border: 1px solid; width: px; margin: 10px auto;"
    >
    <div class="enclosure-list">
        <div class="enclosure-item photo-asset last">
    
            <div class="enclosure-image">
        
                <a href="http://migmit.vox.com/library/photo/6a00e398c5c26f00050110166a9dd1860c.html"><img src="http://a1.vox.com/6a00e398c5c26f00050110166a9dd1860c-500pi" alt="Picture 1" title="Picture 1" /></a>
        
            </div>
            <div class="enclosure-meta">
                <div class="enclosure-asset-name"><a href="http://migmit.vox.com/library/photo/6a00e398c5c26f00050110166a9dd1860c.html" title="Picture 1">Picture 1</a></div>
            </div>
    
        </div>
    </div>
</div>
</div><!-- end enclosure -->

<br /> <div><br /></div></p>   <p style="clear:both;"> 
    <a href="http://migmit.vox.com/library/post/%D0%BF%D1%80%D0%BE%D1%81%D1%82%D0%BE-%D0%B7%D0%B0%D0%B1%D0%B0%D0%B2%D0%BD%D0%BE.html?_c=feed-atom-full#comments">Read and post comments</a>   |   
    <a href="http://www.vox.com/share/6a00e398c5c26f000501101625bcd3860b?_c=feed-atom-full">Send to a friend</a> 
</p>

                </div>
            ]]>
        </content> 
    </entry> 
    
    <entry>
        <title>Ну и денёк</title>   
        <link rel="alternate" type="text/html" title="Ну и денёк" href="http://migmit.vox.com/library/post/%D0%BD%D1%83-%D0%B8-%D0%B4%D0%B5%D0%BD%D1%91%D0%BA.html?_c=feed-atom-full" />  
        <link rel="service.post" type="application/atom+xml" title="Ну и денёк" href="http://migmit.vox.com/library/post/%D0%BD%D1%83-%D0%B8-%D0%B4%D0%B5%D0%BD%D1%91%D0%BA.html?_c=feed-atom-full#comments" /> 
        <link rel="service.edit" type="application/atom+xml" title="Ну и денёк" href="http://www.vox.com/atom/svc=post/asset_id=6a00e398c5c26f000501101660a212860c" />          <id>tag:vox.com,2009-06-16:asset-6a00e398c5c26f000501101660a212860c</id>
        <published>2009-06-16T18:05:30Z</published>
        <updated>2009-06-16T18:05:30Z</updated>
    
        <author>
            <name>migmit</name>
            <uri>http://migmit.vox.com/?_c=feed-atom-full</uri>
        </author>
    
        
        <content type="html" xml:base="http://migmit.vox.com/?_c=feed-atom-full">
            <![CDATA[
                <div xmlns="http://www.w3.org/1999/xhtml" xmlns:at="http://www.sixapart.com/ns/at">
        <p>Началось, как обычно, с мелочи. Дизайнеры сделали новую модель игрока, заменив устрашающий солдафонский костюм на футболку и джинсы, не менее устрашающие. В какой-то момент игрок посмотрел в небо, слегка отклонившись при этом назад. С другой позиции сразу стало видно, как автомат, висевший у игрока за спиной, прошёл у него между ногами и нагло торчит дулом аккурат из ширинки. Особо впечатлительные крестились и украдкой прикасались к томику Фрейда.<br />А потом пришла дверь. Обыкновенная дверь, которая просто не открывалась. До тех пор, пока её не переключали из режима физики в режим анимации, в котором она медленно открывалась, быстро захлопывалась и делала goto :begin. И надо же было именно на ней тестировать новый режим - когда работает и физика, и анимация сразу. Дверь начала исполнять танец пьяного ёжика вокруг косяка, вылетая далеко за запланированные пределы её перемещений. Испуганный девелопер выключил анимацию. Дверь пришла в себя, снялась с петель и, издевательски вращаясь вокруг вертикальной оси, улетела за горизонт.<br />Под конец сисадмин попросил зашедшего к нему по какой-то надобности директора налить ему чаю, потому как он сам, видите ли, до сих пор не сумел разобраться в управлении чайником.<br />Что-то будет завтра...<br /> </p>   <p style="clear:both;"> 
    <a href="http://migmit.vox.com/library/post/%D0%BD%D1%83-%D0%B8-%D0%B4%D0%B5%D0%BD%D1%91%D0%BA.html?_c=feed-atom-full#comments">Read and post comments</a>   |   
    <a href="http://www.vox.com/share/6a00e398c5c26f000501101660a212860c?_c=feed-atom-full">Send to a friend</a> 
</p>

                </div>
            ]]>
        </content> 
    </entry> 
    
    <entry>
        <title>TWIMC</title>   
        <link rel="alternate" type="text/html" title="TWIMC" href="http://migmit.vox.com/library/post/twimc.html?_c=feed-atom-full" />  
        <link rel="service.post" type="application/atom+xml" title="TWIMC" href="http://migmit.vox.com/library/post/twimc.html?_c=feed-atom-full#comments" /> 
        <link rel="service.edit" type="application/atom+xml" title="TWIMC" href="http://www.vox.com/atom/svc=post/asset_id=6a00e398c5c26f000501101607b6e9860b" />          <id>tag:vox.com,2009-05-19:asset-6a00e398c5c26f000501101607b6e9860b</id>
        <published>2009-05-19T19:20:54Z</published>
        <updated>2009-05-19T19:20:54Z</updated>
    
        <author>
            <name>migmit</name>
            <uri>http://migmit.vox.com/?_c=feed-atom-full</uri>
        </author>
    
        
        <content type="html" xml:base="http://migmit.vox.com/?_c=feed-atom-full">
            <![CDATA[
                <div xmlns="http://www.w3.org/1999/xhtml" xmlns:at="http://www.sixapart.com/ns/at">
        <p>Если кому интересно, то начистить мне чайник можно здесь: <span>http://migmit.mybrute.com</span> </p>   <p style="clear:both;"> 
    <a href="http://migmit.vox.com/library/post/twimc.html?_c=feed-atom-full#comments">Read and post comments</a>   |   
    <a href="http://www.vox.com/share/6a00e398c5c26f000501101607b6e9860b?_c=feed-atom-full">Send to a friend</a> 
</p>

                </div>
            ]]>
        </content> 
    </entry> 
    
    <entry>
        <title>Классы как типы</title>   
        <link rel="alternate" type="text/html" title="Классы как типы" href="http://migmit.vox.com/library/post/%D0%BA%D0%BB%D0%B0%D1%81%D1%81%D1%8B-%D0%BA%D0%B0%D0%BA-%D1%82%D0%B8%D0%BF%D1%8B.html?_c=feed-atom-full" />  
        <link rel="service.post" type="application/atom+xml" title="Классы как типы" href="http://migmit.vox.com/library/post/%D0%BA%D0%BB%D0%B0%D1%81%D1%81%D1%8B-%D0%BA%D0%B0%D0%BA-%D1%82%D0%B8%D0%BF%D1%8B.html?_c=feed-atom-full#comments" /> 
        <link rel="service.edit" type="application/atom+xml" title="Классы как типы" href="http://www.vox.com/atom/svc=post/asset_id=6a00e398c5c26f00050110182463d8860f" />          <id>tag:vox.com,2009-05-15:asset-6a00e398c5c26f00050110182463d8860f</id>
        <published>2009-05-15T19:42:06Z</published>
        <updated>2009-05-15T19:55:44Z</updated>
    
        <author>
            <name>migmit</name>
            <uri>http://migmit.vox.com/?_c=feed-atom-full</uri>
        </author>
    
        
        <content type="html" xml:base="http://migmit.vox.com/?_c=feed-atom-full">
            <![CDATA[
                <div xmlns="http://www.w3.org/1999/xhtml" xmlns:at="http://www.sixapart.com/ns/at">
        <p>А мне всего-то хотелось сделать композицию трансформеров...<pre style="white-space:pre-wrap; white-space:-moz-pre-wrap"><span style="color: #b8850a">&gt;</span> <span style="color: #b12121">{-</span><span style="color: #b12121"># LANGUAGE GeneralizedNewtypeDeriving, RankNTypes, TypeOperators #-}</span><br /><span style="color: #b8850a">&gt;</span> <span style="color: #7f007f">module</span> <span style="color: #218a21">MonadM</span> <span style="color: #7f007f">where</span><br /><span style="color: #b8850a">&gt;</span> <span style="color: #7f007f">import</span> <span style="color: #218a21">Control.Monad</span></pre>Допустим, мы хотим применить к некоторой монаде несколько трансформеров. Причём, мы заранее не знаем, к какой именно монаде - но знаем, какие трансформеры. Ну, например, пусть это будут<pre style="white-space:pre-wrap; white-space:-moz-pre-wrap"><span style="color: #b8850a">&gt;</span> <span style="color: #7f007f">newtype</span> <span style="color: #218a21">StateT</span> s m x <span style="color: #b8850a">=</span> <span style="color: #218a21">StateT</span> {runStateT <span style="color: #b8850a">::</span> s <span style="color: #b8850a">-&gt;</span> m (s, x)}<br /><span style="color: #b8850a">&gt;</span> <span style="color: #7f007f">instance</span> <span style="color: #218a21">Monad</span> m <span style="color: #b8850a">=&gt;</span> <span style="color: #218a21">Monad</span> (<span style="color: #218a21">StateT</span> s m) <span style="color: #7f007f">where</span><br /><span style="color: #b8850a">&gt;</span>&#160;&#160;&#160;&#160; return x <span style="color: #b8850a">=</span> <span style="color: #218a21">StateT</span> <span style="color: #b8850a">$</span> <span style="color: #b8850a">\</span>s <span style="color: #b8850a">-&gt;</span> return (s, x)<br /><span style="color: #b8850a">&gt;</span>&#160;&#160;&#160;&#160; st <span style="color: #b8850a">&gt;&gt;=</span> f <span style="color: #b8850a">=</span> <span style="color: #218a21">StateT</span> <span style="color: #b8850a">$</span> <span style="color: #b8850a">\</span>s <span style="color: #b8850a">-&gt;</span> runStateT st s <span style="color: #b8850a">&gt;&gt;=</span> <span style="color: #b8850a">\</span>(s&#39;, x) <span style="color: #b8850a">-&gt;</span> runStateT (f x) s&#39;</pre>и<pre style="white-space:pre-wrap; white-space:-moz-pre-wrap"><span style="color: #b8850a">&gt;</span> <span style="color: #7f007f">newtype</span> <span style="color: #218a21">ReaderT</span> r m x <span style="color: #b8850a">=</span> <span style="color: #218a21">ReaderT</span> {runReaderT <span style="color: #b8850a">::</span> r <span style="color: #b8850a">-&gt;</span> m x}<br /><span style="color: #b8850a">&gt;</span> <span style="color: #7f007f">instance</span> <span style="color: #218a21">Monad</span> m <span style="color: #b8850a">=&gt;</span> <span style="color: #218a21">Monad</span> (<span style="color: #218a21">ReaderT</span> r m) <span style="color: #7f007f">where</span><br /><span style="color: #b8850a">&gt;</span>&#160;&#160;&#160;&#160; return x <span style="color: #b8850a">=</span> <span style="color: #218a21">ReaderT</span> <span style="color: #b8850a">$</span> <span style="color: #b8850a">\</span>r <span style="color: #b8850a">-&gt;</span> return x<br /><span style="color: #b8850a">&gt;</span>&#160;&#160;&#160;&#160; rt <span style="color: #b8850a">&gt;&gt;=</span> f <span style="color: #b8850a">=</span> <span style="color: #218a21">ReaderT</span> <span style="color: #b8850a">$</span> <span style="color: #b8850a">\</span>r <span style="color: #b8850a">-&gt;</span> runReaderT rt r <span style="color: #b8850a">&gt;&gt;=</span> <span style="color: #b8850a">\</span>x <span style="color: #b8850a">-&gt;</span> runReaderT (f x) r</pre>Конечно, нет никакой проблемы написать трансформер-композицию.<pre style="white-space:pre-wrap; white-space:-moz-pre-wrap"><span style="color: #7f007f">newtype</span> <span style="color: #218a21">SRT</span> s r m x <span style="color: #b8850a">=</span> <span style="color: #218a21">SRT</span> (<span style="color: #218a21">ReaderT</span> r (<span style="color: #218a21">StateT</span> s m) x)</pre>Далее, можно точно также объявить<pre style="white-space:pre-wrap; white-space:-moz-pre-wrap"><span style="color: #7f007f">instance</span> <span style="color: #218a21">Monad</span> m <span style="color: #b8850a">=&gt;</span> <span style="color: #218a21">Monad</span> (<span style="color: #218a21">SRT</span> s r m)</pre>и жить припеваючи.</p><p>Но очень хотелось бы сделать это единообразно, написать единый оператор композиции трансформеров. А то вдруг, скажем, мы решим поменять порядок этих трансформеров - что же тогда, инстанс переделывать?</p><p>Попробуем это сделать. Для начала, всё-таки, объявим класс для трансформеров, чтобы не всухомятку обсуждать:<pre style="white-space:pre-wrap; white-space:-moz-pre-wrap"><span style="color: #7f007f">class</span> <span style="color: #218a21">Trans</span> t <span style="color: #7f007f">where</span><br />&#160;&#160;&#160; lift <span style="color: #b8850a">::</span> m x <span style="color: #b8850a">-&gt;</span> t m x</pre>И сделаем простенькую композицию:<pre style="white-space:pre-wrap; white-space:-moz-pre-wrap"><span style="color: #7f007f">newtype</span> (<span style="color: #218a21">Trans</span> t1, <span style="color: #218a21">Trans</span> t2) <span style="color: #b8850a">=&gt;</span> (t2 <span style="color: #218a21">:.</span> t1) m x <span style="color: #b8850a">=</span> <span style="color: #218a21">Compose</span> {runCompose <span style="color: #b8850a">::</span> t2 (t1 m) x} <span style="color: #7f007f">deriving</span> <span style="color: #218a21">Monad</span></pre>Контекст здесь нужен, на самом деле, только для того, чтобы все kind-ы были правильными. Позднее мы его несколько ослабим.</p><p>Далее, нужно, чтобы это был снова трансформер:<pre style="white-space:pre-wrap; white-space:-moz-pre-wrap"><span style="color: #7f007f">instance</span> (<span style="color: #218a21">Trans</span> t1, <span style="color: #218a21">Trans</span> t2) <span style="color: #b8850a">=&gt;</span> <span style="color: #218a21">Trans</span> (t2 <span style="color: #218a21">:.</span> t1) <span style="color: #7f007f">where</span><br />&#160;&#160;&#160; lift <span style="color: #b8850a">=</span> <span style="color: #218a21">Compose</span> <span style="color: #b8850a">.</span> lift <span style="color: #b8850a">.</span> lift</pre>Пока что, всё работает прекрасно. Давайте же сделаем два наших трансформера инстансами соответствующего класса, зарелизим библиотеку на Hackage и пойдём пить кофе с бубликами.<pre style="white-space:pre-wrap; white-space:-moz-pre-wrap"><span style="color: #7f007f">instance</span> <span style="color: #218a21">Trans</span> (<span style="color: #218a21">StateT</span> s) <span style="color: #7f007f">where</span><br />&#160;&#160;&#160; lift mx <span style="color: #b8850a">=</span> <span style="color: #218a21">StateT</span> smx<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style="color: #7f007f">where</span> smx s <span style="color: #b8850a">=</span><br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style="color: #7f007f">do</span> x <span style="color: #b8850a">&lt;-</span> mx<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; return (s, x)</pre>Упс. Получили ругань:<pre style="white-space:pre-wrap; white-space:-moz-pre-wrap"><br /><span style="color: #ff0000"><strong><u>MonadM.lhs</u></strong></span><u>:</u><span style="color: #b8860b"><u>54</u></span><u>:</u><span style="color: #228b22"><u>23</u></span><u>:<br />&#160;&#160;&#160; </u>Could not deduce (Monad m) from the context ()<br />&#160;&#160;&#160;&#160;&#160; arising from a do statement<br /><u>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; at </u><span style="color: #00cd00"><strong><u>MonadM.lhs</u></strong></span><u>:</u><span style="color: #b8860b"><u>54</u></span><u>:</u><span style="color: #228b22"><u>23</u></span><u>-</u><span style="color: #228b22"><u>29</u></span><br />&#160;&#160;&#160; Possible fix:<br />&#160;&#160;&#160;&#160;&#160; add (Monad m) to the context of the type signature for `lift&#39;<br />&#160;&#160;&#160; In a stmt of a &#39;do&#39; expression: x &lt;- mx<br />&#160;&#160;&#160; In the expression:<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; do x &lt;- mx<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; return (s, x)<br />&#160;&#160;&#160; In the definition of `smx&#39;:<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; smx s = do x &lt;- mx<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; return (s, x)<br />Failed, modules loaded: none.<br /></pre>Фикус в том, что для того, чтобы написать нашу функцию <code>lift</code>, нам нужно использовать, что аргумент засунут именно в монаду, а не во что-то ещё. Действительно нужно, это не фантазия какая-то.</p><p>Попробуем пофиксить, изменив сигнатуру <code>lift</code>.<pre style="white-space:pre-wrap; white-space:-moz-pre-wrap"><span style="color: #7f007f">class</span> <span style="color: #218a21">Trans</span> t <span style="color: #7f007f">where</span><br />&#160;&#160;&#160; lift <span style="color: #b8850a">::</span> <span style="color: #218a21">Monad</span> m <span style="color: #b8850a">=&gt;</span> m x <span style="color: #b8850a">-&gt;</span> t m x</pre>Опять облом.<pre style="white-space:pre-wrap; white-space:-moz-pre-wrap"><br /><span style="color: #ff0000"><strong><u>MonadM.lhs</u></strong></span><u>:</u><span style="color: #b8860b"><u>49</u></span><u>:</u><span style="color: #228b22"><u>23</u></span><u>:<br />&#160;&#160;&#160; </u>Could not deduce (Monad (t1 m)) from the context (Monad m)<br />&#160;&#160;&#160;&#160;&#160; arising from a use of `lift&#39;<br /><u>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; at </u><span style="color: #00cd00"><strong><u>MonadM.lhs</u></strong></span><u>:</u><span style="color: #b8860b"><u>49</u></span><u>:</u><span style="color: #228b22"><u>23</u></span><u>-</u><span style="color: #228b22"><u>26</u></span><br />&#160;&#160;&#160; Possible fix:<br />&#160;&#160;&#160;&#160;&#160; add (Monad (t1 m)) to the context of the type signature for `lift&#39;<br />&#160;&#160;&#160;&#160;&#160; or add an instance declaration for (Monad (t1 m))<br />&#160;&#160;&#160; In the first argument of `(.)&#39;, namely `lift&#39;<br />&#160;&#160;&#160; In the second argument of `(.)&#39;, namely `lift . lift&#39;<br />&#160;&#160;&#160; In the expression: Compose . lift . lift<br />Failed, modules loaded: none.<br /></pre>Теперь проблема в том, что из <code><span style="color: #7f007f">instance</span> <span style="color: #218a21">Monad</span> m</code> и <code><span style="color: #7f007f">instance</span> <span style="color: #218a21">Trans</span> t</code> не следует <code><span style="color: #7f007f">instance</span> <span style="color: #218a21">Monad</span> (t m)</code>. Практически это всегда так - по крайней мере, это так для двух трансформеров, которые мы определили в самом начале. Но у нас нет способа убедить компилятор, что это и будет всегда так.</p><p>Подход, принятый в шаблонах C++ заключается в том, чтобы забить на контекст вообще и ругаться, если он не выполняется в каждом конкретном случае. Думаю, в языке, принимающем статическую типизацию близко к сердцу, подобный вариант не имеет права на существование.</p><p>В Языке Моей Мечты(tm) я бы написал так:<pre style="white-space:pre-wrap; white-space:-moz-pre-wrap"><span style="color: #7f007f">class</span> <span style="color: #218a21">Trans</span> t <span style="color: #7f007f">where</span><br />&#160;&#160;&#160; lift <span style="color: #b8850a">::</span> <span style="color: #218a21">Monad</span> m <span style="color: #b8850a">=&gt;</span> m x <span style="color: #b8850a">-&gt;</span> t m x<br />&#160;&#160;&#160; <span style="color: #7f007f">instance</span> <span style="color: #218a21">Monad</span> m <span style="color: #b8850a">=&gt;</span> <span style="color: #218a21">Monad</span> (t m)</pre>После чего я перенёс бы <code><span style="color: #7f007f">instance</span> <span style="color: #218a21">Monad</span> m <span style="color: #b8850a">=&gt;</span> <span style="color: #218a21">Monad</span> (<span style="color: #218a21">StateT</span> s m)</code> внутрь <code><span style="color: #7f007f">instance</span> <span style="color: #218a21">Trans</span> (<span style="color: #218a21">StateT</span> s)</code> и всё заработало бы. Увы, Язык Моей Мечты(tm) пока лишён важной утилиты, а именно, компилятора. Нет, интерпретатора тоже нет. Так что, этот способ тоже не сработает.</p><p>Попробуем иначе. Что нам нужно, так это добавить в класс <code><span style="color: #218a21">Trans</span></code> какую-то функцию, которая сообщит компилятору, что происходит именно преобразование <strong>монад</strong>, а не чего-то ещё. Иначе говоря, нам нужно работать с классом <code><span style="color: #218a21">Monad</span></code> как с типом данных.</p><p>Попробуем это сделать.</p><p>Что вообще означает, что некоторый тип <code><span style="color: #218a21">T</span></code> является монадой? Это означает, что для данного типа определены несколько операций. Как учит нас теория категорий, где есть алгебраические операции (или похожие на них), стоит искать... монаду. Да-да, монаду. Правда, так как наши типы имеют не тот kind, эта монада также будет монадой на другой категории. Следовательно, имеет смысл для начала определить эту категорию:<pre style="white-space:pre-wrap; white-space:-moz-pre-wrap"><span style="color: #b8850a">&gt;</span> <span style="color: #7f007f">type</span> (m <span style="color: #218a21">:-&gt;</span> n) <span style="color: #b8850a">=</span> forall x<span style="color: #b8850a">.</span> m x <span style="color: #b8850a">-&gt;</span> n x</pre>Вот они - морфизмы нашей новой категории.</p><p>Далее, опять же, теория категорий учит, что новую монаду нужно определять так: объекту <code>p</code> ставится в соответствие нечто вроде &quot;множества всех выражений, составленных при помощи заданных операций из элементов <code>p</code>&quot;. То есть, в нашем случае подошло бы что-то в таком духе:<pre style="white-space:pre-wrap; white-space:-moz-pre-wrap"><span style="color: #7f007f">data</span> <span style="color: #218a21">MonadM</span> p x <span style="color: #7f007f">where</span><br />&#160;&#160;&#160; <span style="color: #218a21">Term</span> <span style="color: #b8850a">::</span> p x <span style="color: #b8850a">-&gt;</span> <span style="color: #218a21">MonadM</span> p x<br />&#160;&#160;&#160; <span style="color: #218a21">Return</span> <span style="color: #b8850a">::</span> x <span style="color: #b8850a">-&gt;</span> <span style="color: #218a21">MonadM</span> p x<br />&#160;&#160;&#160; <span style="color: #218a21">Bind</span> <span style="color: #b8850a">::</span> <span style="color: #218a21">MonadM</span> p x <span style="color: #b8850a">-&gt;</span> (x <span style="color: #b8850a">-&gt;</span> <span style="color: #218a21">MonadM</span> p y) <span style="color: #b8850a">-&gt;</span> <span style="color: #218a21">MonadM</span> p y</pre>Я, однако, предпочитаю более простой и универсальный подход. Сейчас я определю <em>тот же</em> тип, но по-другому. Вуаля:<pre style="white-space:pre-wrap; white-space:-moz-pre-wrap"><span style="color: #b8850a">&gt;</span> <span style="color: #7f007f">newtype</span> <span style="color: #218a21">MonadM</span> p x <span style="color: #b8850a">=</span> <span style="color: #218a21">MonadM</span> {bindM <span style="color: #b8850a">::</span> <span style="color: #218a21">Monad</span> m <span style="color: #b8850a">=&gt;</span> (p <span style="color: #218a21">:-&gt;</span> m) <span style="color: #b8850a">-&gt;</span> m x}</pre>Это и правда то же самое. Теперь, <code><span style="color: #218a21">MonadM</span></code> имеет kind<pre style="white-space:pre-wrap; white-space:-moz-pre-wrap"><br /><span style="color: #00008b">*MonadM&gt; </span><strong>:k MonadM</strong><br /><span style="color: #0000ff">MonadM</span> :: (* -&gt; *) -&gt; * -&gt; *<br /></pre>и, следовательно, похож на монаду <strong>на категории типов kind-a&#160; <code>(* -&gt; *)</code></strong>. Не хватает только функций <code>return</code> и <code>(<span style="color: #0000ff">&gt;&gt;=</span>)</code> для полного счастья. Сейчас мы их определим.</p><p>Начнём с <code>return</code>. Обычно, эта функция имеет типx <span style="color: #b8850a">-&gt;</span> m x (так она определена в классе <code><span style="color: #218a21">Monad</span></code>). У нас, следовательно, тип будет<pre style="white-space:pre-wrap; white-space:-moz-pre-wrap"><span style="color: #b8850a">&gt;</span> <span style="color: #0000ff">term</span> <span style="color: #b8850a">::</span> p <span style="color: #218a21">:-&gt;</span> <span style="color: #218a21">MonadM</span> p</pre>Такую функцию написать несложно, и делается это, по существу, единственным образом:<pre style="white-space:pre-wrap; white-space:-moz-pre-wrap"><span style="color: #b8850a">&gt;</span> <span style="color: #0000ff">term</span> px <span style="color: #b8850a">=</span> <span style="color: #218a21">MonadM</span> <span style="color: #b8850a">$</span> <span style="color: #b8850a">\</span>hom <span style="color: #b8850a">-&gt;</span> hom px</pre>Далее, оператор <code>(<span style="color: #0000ff">&gt;&gt;=</span>)</code>. Он у нас, по сути, уже есть. Это функция <code>bindM</code>. Её тип поначалу не кажется похожим на то, что нам нужно, но только потому, что у нас не хватает ещё одного важного элемента:<pre style="white-space:pre-wrap; white-space:-moz-pre-wrap"><span style="color: #b8850a">&gt;</span> <span style="color: #7f007f">instance</span> <span style="color: #218a21">Monad</span> (<span style="color: #218a21">MonadM</span> p) <span style="color: #7f007f">where</span><br /><span style="color: #b8850a">&gt;</span>&#160;&#160;&#160;&#160; return x <span style="color: #b8850a">=</span> <span style="color: #218a21">MonadM</span> <span style="color: #b8850a">$</span> <span style="color: #b8850a">\</span>hom <span style="color: #b8850a">-&gt;</span> return x<br /><span style="color: #b8850a">&gt;</span>&#160;&#160;&#160;&#160; mpx <span style="color: #b8850a">&gt;&gt;=</span> f <span style="color: #b8850a">=</span> <span style="color: #218a21">MonadM</span> <span style="color: #b8850a">$</span> <span style="color: #b8850a">\</span>hom <span style="color: #b8850a">-&gt;</span> bindM mpx hom <span style="color: #b8850a">&gt;&gt;=</span> <span style="color: #b8850a">\</span>x <span style="color: #b8850a">-&gt;</span> bindM (f x) hom</pre>В этом определении мы просто говорим, что правая часть, по существу, совпадает с левой, только вокруг тех штук, которые имеют тип <code><span style="color: #218a21">MonadM</span> p x</code> добавляется некий line noise в виде <code>bindM</code> и <code>hom</code>.</p><p>Теперь мы видим, что функция <code>bindM</code> имеет тип, который, во всяком случае, не хуже, чем то, что нам нужно:<pre style="white-space:pre-wrap; white-space:-moz-pre-wrap"><br /><span style="color: #00008b">*MonadM&gt; </span><strong>:set -XTypeOperators -XRankNTypes</strong><br /><span style="color: #00008b">*MonadM&gt; </span><strong>:t bindM :: MonadM p x -&gt; (p :-&gt; MonadM p) -&gt; MonadM p x</strong><br /><span style="color: #0000ff">bindM</span> :: MonadM p x -&gt; (p :-&gt; MonadM p) -&gt; MonadM p x<br />&#160; :: MonadM p x -&gt; (p :-&gt; MonadM p) -&gt; MonadM p x<br /></pre>Хорошо. Далее, то, чему не учат в Haskell-школах: конкретный объект с нужными нам операциями является ни чем иным как <strong>алгеброй</strong> над подобной монадой. В нашем случае это значит, что каждая монада является алгеброй над&#160; <code><span style="color: #218a21">MonadM</span></code>. Более конкретно, для каждой монады есть отображение<pre style="white-space:pre-wrap; white-space:-moz-pre-wrap"><span style="color: #0000ff">alg</span> <span style="color: #b8850a">::</span> <span style="color: #218a21">Monad</span> m <span style="color: #b8850a">=&gt;</span> <span style="color: #218a21">MonadM</span> m <span style="color: #218a21">:-&gt;</span> m</pre>Именно, оно пишется так:<pre style="white-space:pre-wrap; white-space:-moz-pre-wrap"><span style="color: #0000ff">alg</span> (<span style="color: #218a21">MonadM</span> h) <span style="color: #b8850a">=</span> h id</pre>В данном случае, <code>id</code> имеет тип <code>m <span style="color: #218a21">:-&gt;</span> m</code>.</p><p>Как же это поможет нам решить нашу проблему? А вот как: по сути дела, указать для некоторого типа отображение <code>alg</code> и определить для этого же типа <code><span style="color: #7f007f">instance</span> <span style="color: #218a21">Monad</span></code> - одно и то же. !. Я определю специальный тип:<pre style="white-space:pre-wrap; white-space:-moz-pre-wrap"><span style="color: #b8850a">&gt;</span> <span style="color: #7f007f">newtype</span> <span style="color: #218a21">Inst</span> m <span style="color: #b8850a">=</span> <span style="color: #218a21">Inst</span> {getInst <span style="color: #b8850a">::</span> <span style="color: #218a21">MonadM</span> m <span style="color: #218a21">:-&gt;</span> m}</pre>и навешу конструктор на <code>alg</code> следующим образом:<pre style="white-space:pre-wrap; white-space:-moz-pre-wrap"><span style="color: #b8850a">&gt;</span> <span style="color: #0000ff">alg</span> <span style="color: #b8850a">::</span> <span style="color: #218a21">Monad</span> m <span style="color: #b8850a">=&gt;</span> <span style="color: #218a21">Inst</span> m<br /><span style="color: #b8850a">&gt;</span> <span style="color: #0000ff">alg</span> <span style="color: #b8850a">=</span> <span style="color: #218a21">Inst</span> <span style="color: #b8850a">$</span> <span style="color: #b8850a">\</span>mmx <span style="color: #b8850a">-&gt;</span> bindM mmx id</pre>Далее, идеология происходящего следующая. Если нам нужно что-то сделать с типом <code>m</code>, для чего требуется <code><span style="color: #7f007f">instance</span> <span style="color: #218a21">Monad</span></code>, а у нас вместо него только значение <code><span style="color: #0000ff">inst</span> <span style="color: #b8850a">::</span> <span style="color: #218a21">Inst</span> m</code>, то мы проделываем всё необходимое, используя вместо <code>m</code> тип <code><span style="color: #218a21">MonadM</span> m</code> (который всегда является монадой - определение только что было), а потом переносим это на тип <code>m</code>, используя при этом отображения <code>term <span style="color: #b8850a">::</span> m <span style="color: #218a21">:-&gt;</span> <span style="color: #218a21">MonadM</span> m</code> и <code>getInst inst <span style="color: #b8850a">::</span> <span style="color: #218a21">MonadM</span> m <span style="color: #218a21">:-&gt;</span> m</code>.</p><p>Для того, чтобы этот перенос осуществить, нам потребуется такой класс:<pre style="white-space:pre-wrap; white-space:-moz-pre-wrap"><span style="color: #7f007f">class</span> <span style="color: #218a21">Iso</span> t <span style="color: #7f007f">where</span> iso <span style="color: #b8850a">::</span> (m <span style="color: #218a21">:-&gt;</span> n) <span style="color: #b8850a">-&gt;</span> (n <span style="color: #218a21">:-&gt;</span> m) <span style="color: #b8850a">-&gt;</span> (t m <span style="color: #218a21">:-&gt;</span> t n)</pre>На самом деле, мне неизвестны трансформеры монад, которые не были бы ковариантны по этим монадам, так что можно сократить сигнатуру:<pre style="white-space:pre-wrap; white-space:-moz-pre-wrap"><span style="color: #b8850a">&gt;</span> <span style="color: #7f007f">class</span> <span style="color: #218a21">Iso</span> t <span style="color: #7f007f">where</span> iso <span style="color: #b8850a">::</span> (m <span style="color: #218a21">:-&gt;</span> n) <span style="color: #b8850a">-&gt;</span> (t m <span style="color: #218a21">:-&gt;</span> t n)</pre> <code><span style="color: #7f007f">instance</span> <span style="color: #218a21">Iso</span></code> обычно пишется несложно и бойлерплейт получится весьма небольшой.</p><p>В частности, например, легко написать такое:<pre style="white-space:pre-wrap; white-space:-moz-pre-wrap"><span style="color: #b8850a">&gt;</span> <span style="color: #7f007f">infixl</span> 1 <span style="color: #b8850a">`bindM`</span><br /><span style="color: #b8850a">&gt;</span> <span style="color: #7f007f">instance</span> <span style="color: #218a21">Iso</span> <span style="color: #218a21">MonadM</span> <span style="color: #7f007f">where</span> iso hom mmx <span style="color: #b8850a">=</span> mmx <span style="color: #b8850a">`bindM`</span> term <span style="color: #b8850a">.</span> hom</pre>Заметьте, я здесь, фактически, воспроизвёл определение функции <code>liftM</code>:<pre style="white-space:pre-wrap; white-space:-moz-pre-wrap"><span style="color: #0000ff">liftM</span> f mx <span style="color: #b8850a">=</span> mx <span style="color: #b8850a">&gt;&gt;=</span> return <span style="color: #b8850a">.</span> f</pre>Класс трансформеров теперь определяется так:<pre style="white-space:pre-wrap; white-space:-moz-pre-wrap"><span style="color: #b8850a">&gt;</span> <span style="color: #7f007f">class</span> <span style="color: #218a21">Iso</span> t <span style="color: #b8850a">=&gt;</span> <span style="color: #218a21">Trans</span> t <span style="color: #7f007f">where</span><br /><span style="color: #b8850a">&gt;</span>&#160;&#160;&#160;&#160; lift <span style="color: #b8850a">::</span> <span style="color: #218a21">Monad</span> m <span style="color: #b8850a">=&gt;</span> m x <span style="color: #b8850a">-&gt;</span> t m x<br /><span style="color: #b8850a">&gt;</span>&#160;&#160;&#160;&#160; liftInst <span style="color: #b8850a">::</span> <span style="color: #218a21">Inst</span> m <span style="color: #b8850a">-&gt;</span> <span style="color: #218a21">Inst</span> (t m)</pre>Обратите внимание на изменившийся контекст.</p><p>В частности, теперь можно сделать трансформером композицию трансформеров.<pre style="white-space:pre-wrap; white-space:-moz-pre-wrap"><span style="color: #b8850a">&gt;</span> <span style="color: #7f007f">newtype</span> (<span style="color: #218a21">Iso</span> t1, <span style="color: #218a21">Iso</span> t2) <span style="color: #b8850a">=&gt;</span> (t2 <span style="color: #218a21">:.</span> t1) m x <span style="color: #b8850a">=</span> <span style="color: #218a21">Compose</span> {runCompose <span style="color: #b8850a">::</span> t2 (t1 m) x} <span style="color: #7f007f">deriving</span> <span style="color: #218a21">Monad</span><br /><span style="color: #b8850a">&gt;</span> <span style="color: #7f007f">infixr</span> 9 <span style="color: #218a21">:.</span></pre>Здесь я изменил контекст с <code><span style="color: #218a21">Trans</span></code> на <code><span style="color: #218a21">Iso</span></code>, чтобы следующий инстанс выглядел более вменяемо:<pre style="white-space:pre-wrap; white-space:-moz-pre-wrap"><span style="color: #b8850a">&gt;</span> <span style="color: #7f007f">instance</span> (<span style="color: #218a21">Iso</span> t1, <span style="color: #218a21">Iso</span> t2) <span style="color: #b8850a">=&gt;</span> <span style="color: #218a21">Iso</span> (t2 <span style="color: #218a21">:.</span> t1) <span style="color: #7f007f">where</span> iso hom ttmx <span style="color: #b8850a">=</span> <span style="color: #218a21">Compose</span> <span style="color: #b8850a">$</span> iso (iso hom) <span style="color: #b8850a">$</span> runCompose ttmx</pre>Ну и, как я и обещал, композиция трансформеров - трансформер:<pre style="white-space:pre-wrap; white-space:-moz-pre-wrap"><span style="color: #b8850a">&gt;</span> <span style="color: #7f007f">instance</span> (<span style="color: #218a21">Trans</span> t1, <span style="color: #218a21">Trans</span> t2) <span style="color: #b8850a">=&gt;</span> <span style="color: #218a21">Trans</span> (t2 <span style="color: #218a21">:.</span> t1) <span style="color: #7f007f">where</span></pre>Нам нужно пройти от <code>m x</code> к <code>(t2 <span style="color: #218a21">:.</span> t1) m x</code></p><p>Обычно мы пошли бы по маршруту <code>m x <span style="color: #b8850a">--&gt;</span> t1 m x <span style="color: #b8850a">--&gt;</span> t2 (t1 m) x <span style="color: #b8850a">--&gt;</span> (t2 <span style="color: #218a21">:.</span> t1) m x</code>.</p><p>Увы, если первый и последний шаги особых проблем не представляют, то второй шаг, увы, невозможен, так как <code>t1 m</code> не является монадой (по крайней мере, мы не можем убедить компилятор, что является). Однако, у нас есть значение <code>alg <span style="color: #b8850a">::</span> <span style="color: #218a21">Inst</span> m</code>, и, следовательно, также и значение <code>liftInst alg <span style="color: #b8850a">::</span> <span style="color: #218a21">Inst</span> (t1 m)</code>. В соответствии с общей идеологией, мы сделаем второй шаг несколько более длинным, а именно, пройдём по маршруту <code>t1 m x <span style="color: #b8850a">--&gt;</span> <span style="color: #218a21">MonadM</span> (t1 m) x <span style="color: #b8850a">--&gt;</span> t2 (<span style="color: #218a21">MonadM</span> (t1 m)) x <span style="color: #b8850a">--&gt;</span> t2 (t1 m) x</code>.</p><p>Делаем:<pre style="white-space:pre-wrap; white-space:-moz-pre-wrap">&#160;&#160;&#160; lift <span style="color: #b8850a">=</span> <span style="color: #218a21">Compose</span> <span style="color: #b8850a">.</span> step2 <span style="color: #b8850a">.</span> lift<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style="color: #7f007f">where</span> step2 <span style="color: #b8850a">=</span> iso (getInst <span style="color: #b8850a">$</span> liftInst alg) <span style="color: #b8850a">.</span> lift <span style="color: #b8850a">.</span> term</pre>или, коль скоро принцип ясен,<pre style="white-space:pre-wrap; white-space:-moz-pre-wrap"><span style="color: #b8850a">&gt;</span>&#160;&#160;&#160;&#160; lift <span style="color: #b8850a">=</span> <span style="color: #218a21">Compose</span> <span style="color: #b8850a">.</span> iso (getInst <span style="color: #b8850a">$</span> liftInst alg) <span style="color: #b8850a">.</span> lift <span style="color: #b8850a">.</span> term<span style="color: #b8850a">.</span> lift<br /><span style="color: #b8850a">&gt;</span>&#160;&#160;&#160;&#160; liftInst <span style="color: #b8850a">=</span> isoInst <span style="color: #b8850a">.</span> liftInst <span style="color: #b8850a">.</span> liftInst<br /><span style="color: #b8850a">&gt;</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style="color: #7f007f">where</span> isoInst <span style="color: #b8850a">::</span> (<span style="color: #218a21">Iso</span> t1, <span style="color: #218a21">Iso</span> t2) <span style="color: #b8850a">=&gt;</span> <span style="color: #218a21">Inst</span> (t2 (t1 m)) <span style="color: #b8850a">-&gt;</span> <span style="color: #218a21">Inst</span> ((t2 <span style="color: #218a21">:.</span> t1) m)<br /><span style="color: #b8850a">&gt;</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; isoInst inst <span style="color: #b8850a">=</span> <span style="color: #218a21">Inst</span> <span style="color: #b8850a">$</span> <span style="color: #b8850a">\</span>mmx <span style="color: #b8850a">-&gt;</span> <span style="color: #218a21">Compose</span> <span style="color: #b8850a">$</span> getInst inst <span style="color: #b8850a">$</span> iso runCompose mmx</pre>Пока всё не слишком (надеюсь) сложно. Но сумеем ли мы сделать наши <code><span style="color: #218a21">StateT</span></code> и <code><span style="color: #218a21">ReaderT</span></code> инстансами класса <code><span style="color: #218a21">Trans</span></code>? Ну, первая часть проблем не вызывает:<pre style="white-space:pre-wrap; white-space:-moz-pre-wrap"><span style="color: #b8850a">&gt;</span> <span style="color: #7f007f">instance</span> <span style="color: #218a21">Iso</span> (<span style="color: #218a21">StateT</span> s) <span style="color: #7f007f">where</span> iso hom smx <span style="color: #b8850a">=</span> <span style="color: #218a21">StateT</span> <span style="color: #b8850a">$</span> hom <span style="color: #b8850a">.</span> runStateT smx<br /><span style="color: #b8850a">&gt;</span> <span style="color: #7f007f">instance</span> <span style="color: #218a21">Trans</span> (<span style="color: #218a21">StateT</span> s) <span style="color: #7f007f">where</span><br /><span style="color: #b8850a">&gt;</span>&#160;&#160;&#160;&#160; lift mx <span style="color: #b8850a">=</span> <span style="color: #218a21">StateT</span> smx<br /><span style="color: #b8850a">&gt;</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style="color: #7f007f">where</span> smx s <span style="color: #b8850a">=</span><br /><span style="color: #b8850a">&gt;</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style="color: #7f007f">do</span> x <span style="color: #b8850a">&lt;-</span> mx<br /><span style="color: #b8850a">&gt;</span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; return (s, x)</pre>Здесь почти ничего не изменилось. Далее, нам нужно от <code><span style="color: #218a21">Inst</span> m</code> перейти к <code><span style="color: #218a21">Inst</span> (<span style="color: #218a21">StateT</span> s m)</code>.</p><p>Если бы <code>m</code> было монадой, то всё было бы не просто, а очень просто: достаточно было бы использовать значение <code>alg</code>, поскольку <code><span style="color: #7f007f">instance</span> <span style="color: #218a21">Monad</span> m <span style="color: #b8850a">=&gt;</span> <span style="color: #218a21">Monad</span> (<span style="color: #218a21">StateT</span> s m)</code> у нас уже есть. Увы, <code>m</code> не обязательно является монадой, однако мы начинаем со значения типа <code><span style="color: #218a21">Inst</span> m</code>! В соответствии с общей идеологией, мы пройдём по маршруту <code><span style="color: #218a21">MonadM</span> (<span style="color: #218a21">StateT</span> s m) <span style="color: #b8850a">--&gt;</span> <span style="color: #218a21">MonadM</span> (<span style="color: #218a21">StateT</span> s (<span style="color: #218a21">MonadM</span> m)) <span style="color: #b8850a">--&gt;</span> <span style="color: #218a21">StateT</span> s (<span style="color: #218a21">MonadM</span> m) <span style="color: #b8850a">--&gt;</span> <span style="color: #218a21">StateT</span> s m</code> следующим образом:<pre style="white-space:pre-wrap; white-space:-moz-pre-wrap">&#160;&#160;&#160; liftInst inst <span style="color: #b8850a">=</span> <span style="color: #218a21">Inst</span> <span style="color: #b8850a">$</span> iso (getInst inst) <span style="color: #b8850a">.</span> getInst alg <span style="color: #b8850a">.</span> iso (iso term)</pre>У меня лично сразу проситься вынести <code>alg</code> в дополнительный параметр и написать так:<pre style="white-space:pre-wrap; white-space:-moz-pre-wrap"><span style="color: #b8850a">&gt;</span>&#160;&#160;&#160;&#160; liftInst <span style="color: #b8850a">=</span> makeLiftInst alg<br /><span style="color: #b8850a">&gt;</span> <span style="color: #0000ff">makeLiftInst</span> <span style="color: #b8850a">::</span> <span style="color: #218a21">Iso</span> t <span style="color: #b8850a">=&gt;</span> <span style="color: #218a21">Inst</span> (t (<span style="color: #218a21">MonadM</span> m)) <span style="color: #b8850a">-&gt;</span> <span style="color: #218a21">Inst</span> m <span style="color: #b8850a">-&gt;</span> <span style="color: #218a21">Inst</span> (t m)<br /><span style="color: #b8850a">&gt;</span> <span style="color: #0000ff">makeLiftInst</span> alg&#39; inst <span style="color: #b8850a">=</span> <span style="color: #218a21">Inst</span> <span style="color: #b8850a">$</span> iso (getInst inst) <span style="color: #b8850a">.</span> getInst alg&#39; <span style="color: #b8850a">.</span> iso (iso term)</pre>Тип для функции <code>makeLiftInst</code>, признаюсь, написал не я, а компилятор. Ну, пусть будет.</p><p>Аналогично пишется инстанс для <code><span style="color: #218a21">ReaderT</span></code>:<pre style="white-space:pre-wrap; white-space:-moz-pre-wrap"><span style="color: #b8850a">&gt;</span> <span style="color: #7f007f">instance</span> <span style="color: #218a21">Iso</span> (<span style="color: #218a21">ReaderT</span> r) <span style="color: #7f007f">where</span> iso hom rmx <span style="color: #b8850a">=</span> <span style="color: #218a21">ReaderT</span> <span style="color: #b8850a">$</span> hom <span style="color: #b8850a">.</span> runReaderT rmx<br /><span style="color: #b8850a">&gt;</span> <span style="color: #7f007f">instance</span> <span style="color: #218a21">Trans</span> (<span style="color: #218a21">ReaderT</span> r) <span style="color: #7f007f">where</span><br /><span style="color: #b8850a">&gt;</span>&#160;&#160;&#160;&#160; lift mx <span style="color: #b8850a">=</span> <span style="color: #218a21">ReaderT</span> <span style="color: #b8850a">$</span> const mx<br /><span style="color: #b8850a">&gt;</span>&#160;&#160;&#160;&#160; liftInst <span style="color: #b8850a">=</span> makeLiftInst alg</pre>Обратите внимание, что объявление функции <code>liftInst</code> совершенно одинаковое, что для <code><span style="color: #218a21">StateT</span></code>, что для <code><span style="color: #218a21">ReaderT</span></code>. Мы можем написать ещё несколько трансформеров, но везде будет то же самое. Нельзя ли его написать, например, как дефолтную реализацию в самом классе? Попробовав, получаем<pre style="white-space:pre-wrap; white-space:-moz-pre-wrap"><br /><span style="color: #ff0000"><strong><u>MonadM.lhs</u></strong></span><u>:</u><span style="color: #b8860b"><u>392</u></span><u>:</u><span style="color: #228b22"><u>30</u></span><u>:<br />&#160;&#160;&#160; </u>Could not deduce (Monad (t (MonadM m))) from the context ()<br />&#160;&#160;&#160;&#160;&#160; arising from a use of `alg&#39;<br /><u>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; at </u><span style="color: #00cd00"><strong><u>MonadM.lhs</u></strong></span><u>:</u><span style="color: #b8860b"><u>392</u></span><u>:</u><span style="color: #228b22"><u>30</u></span><u>-</u><span style="color: #228b22"><u>32</u></span><br />&#160;&#160;&#160; Possible fix:<br />&#160;&#160;&#160;&#160;&#160; add (Monad (t (MonadM m))) to the context of<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; the type signature for `liftInst&#39;<br />&#160;&#160;&#160;&#160;&#160; or add an instance declaration for (Monad (t (MonadM m)))<br />&#160;&#160;&#160; In the first argument of `makeLiftInst&#39;, namely `alg&#39;<br />&#160;&#160;&#160; In the expression: makeLiftInst alg<br />&#160;&#160;&#160; In the definition of `liftInst&#39;: liftInst = makeLiftInst alg<br />Failed, modules loaded: none.<br /></pre>Увы, так не получится. Причина здесь в том, что мы для каждого конкретного <code><span style="color: #218a21">T</span></code> определяем <code><span style="color: #7f007f">instance</span> <span style="color: #218a21">Monad</span> m <span style="color: #b8850a">=&gt;</span> <span style="color: #218a21">Monad</span> (<span style="color: #218a21">T</span> m)</code> отдельно, и строчка <code><span style="color: #0000ff">liftInst</span> <span style="color: #b8850a">=</span> makeLiftInst alg</code> как бы является обещанием, что такой инстанс определён где-то в другом месте; компилятор же это обещание тщательно проверит.</p><p>На закуску - применение трансформера к монаде. Конечно, можно применять и так, но в некоторых случаях более общий подход может пригодиться:<pre style="white-space:pre-wrap; white-space:-moz-pre-wrap"><span style="color: #b8850a">&gt;</span> <span style="color: #7f007f">newtype</span> <span style="color: #218a21">Monad</span> m <span style="color: #b8850a">=&gt;</span> (t <span style="color: #218a21">:$</span> m) x <span style="color: #b8850a">=</span> <span style="color: #218a21">Apply</span> {runApply <span style="color: #b8850a">::</span> t m x}<br /><span style="color: #b8850a">&gt;</span> <span style="color: #7f007f">infixr</span> 0 <span style="color: #218a21">:$</span><br /><span style="color: #b8850a">&gt;</span> <span style="color: #7f007f">instance</span> (<span style="color: #218a21">Trans</span> t, <span style="color: #218a21">Monad</span> m) <span style="color: #b8850a">=&gt;</span> <span style="color: #218a21">Monad</span> (t <span style="color: #218a21">:$</span> m) <span style="color: #7f007f">where</span><br /><span style="color: #b8850a">&gt;</span>&#160;&#160;&#160;&#160; return x <span style="color: #b8850a">=</span> <span style="color: #218a21">Apply</span> <span style="color: #b8850a">$</span> getInst (liftInst alg) <span style="color: #b8850a">$</span> return x<br /><span style="color: #b8850a">&gt;</span>&#160;&#160;&#160;&#160; tmx <span style="color: #b8850a">&gt;&gt;=</span> f <span style="color: #b8850a">=</span> <span style="color: #218a21">Apply</span> <span style="color: #b8850a">$</span> getInst (liftInst alg) <span style="color: #b8850a">$</span> term (runApply tmx) <span style="color: #b8850a">&gt;&gt;=</span> <span style="color: #b8850a">\</span>x <span style="color: #b8850a">-&gt;</span> term (runApply <span style="color: #b8850a">$</span> f x)</pre>Фикус в том, что мы дописываем к значениям <code><span style="color: #0000ff">tmx</span> <span style="color: #b8850a">::</span> (t <span style="color: #218a21">:$</span> x) x</code> мусор вида <code>term (runApply tmx)</code>, а обратно приходим при помощи <code><span style="color: #218a21">Apply</span> <span style="color: #b8850a">.</span> getInst (liftInst alg)</code>. В остальном же, мы просто в правой части повторяем левую.</p><p>Теперь можно писать, например, <code>(<span style="color: #218a21">StateT</span> <span style="color: #218a21">Int</span> <span style="color: #218a21">:.</span> <span style="color: #218a21">ReaderT</span> <span style="color: #218a21">String</span> <span style="color: #218a21">:$</span> <span style="color: #218a21">Maybe</span>) <span style="color: #218a21">Char</span></code> и это будет примерно (с точностью до newtype-ов) то же самое, что и <code>(<span style="color: #218a21">StateT</span> <span style="color: #218a21">Int</span> <span style="color: #218a21">:$</span> <span style="color: #218a21">ReaderT</span> <span style="color: #218a21">String</span> <span style="color: #218a21">:$</span> <span style="color: #218a21">Maybe</span>) <span style="color: #218a21">Char</span></code> или <code><span style="color: #218a21">State</span> <span style="color: #218a21">Int</span> (<span style="color: #218a21">ReaderT</span> <span style="color: #218a21">String</span> (<span style="color: #218a21">Maybe</span> <span style="color: #218a21">Char</span>))</code>.</p><p>Если кто-то вдруг захочет написать собственный трансформер&#160; <code><span style="color: #218a21">MyCoolTransformer</span></code> - нет проблем, пусть сделает три вещи:</p><p>1)<pre style="white-space:pre-wrap; white-space:-moz-pre-wrap"><span style="color: #7f007f">instance</span> <span style="color: #218a21">Monad</span> m <span style="color: #b8850a">=&gt;</span> <span style="color: #218a21">Monad</span> (<span style="color: #218a21">MyCoolTransformer</span> m)</pre>Если этого не сделать, то непонятно, почему вообще речь идёт о трансформерах монад.</p><p>2)<pre style="white-space:pre-wrap; white-space:-moz-pre-wrap"><span style="color: #0000ff">lift</span> <span style="color: #b8850a">::</span> m x <span style="color: #b8850a">-&gt;</span> <span style="color: #218a21">MyCoolTransformer</span> m x</pre>Это - то, для чего трансформеры монад действительно нужны.</p><p>3) Заклинание <code><span style="color: #0000ff">liftInst</span> <span style="color: #b8850a">=</span> makeLiftInst alg</code>, которое пишется без участия мозга. Как видим, весь бойлерплейт сведён к одной строчке - что можно записывать как победу.</p><p>Маленькое замечание: здесь мы почти не пользовались тем, что речь идёт именно о монадах. Точно то же самое можно написать про трансформеры, например, стрелок. Понадобиться только а) изменить понятие морфизма, так как стрелки имеют другой kind, б) заменить два инстанса на полностью аналогичные, один для нашей &quot;монады&quot; (которая, если мы заменим монады на стрелки,.. останется монадой), и один для оператора применения трансформера к <del>монаде</del>стрелке.</p>   <p style="clear:both;"> 
    <a href="http://migmit.vox.com/library/post/%D0%BA%D0%BB%D0%B0%D1%81%D1%81%D1%8B-%D0%BA%D0%B0%D0%BA-%D1%82%D0%B8%D0%BF%D1%8B.html?_c=feed-atom-full#comments">Read and post comments</a>   |   
    <a href="http://www.vox.com/share/6a00e398c5c26f00050110182463d8860f?_c=feed-atom-full">Send to a friend</a> 
</p>

                </div>
            ]]>
        </content> 
    </entry> 
</feed>


