<?xml version="1.0"?>
<rss version="2.0" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:media="http://search.yahoo.com/mrss/" xmlns:yt="http://gdata.youtube.com/schemas/2007" xmlns:atom="http://www.w3.org/2005/Atom">
   <channel>
      <title>Russian Planet F#</title>
      <description>Pipes Output</description>
      <link>http://pipes.yahoo.com/pipes/pipe.info?_id=04a5919a3781aa3901bc4f8e56956a88</link>
      <atom:link rel="next" href="http://pipes.yahoo.com/pipes/pipe.run?_id=04a5919a3781aa3901bc4f8e56956a88&amp;_render=rss&amp;page=2"/>
      <pubDate>Thu, 01 Oct 2015 23:05:24 +0000</pubDate>
      <generator>http://pipes.yahoo.com/pipes/</generator>
      <item>
         <title>Обновленная Aivika for .NET</title>
         <link>http://dsorokin.blogspot.com/2015/06/aivika-for-net.html</link>
         <description>&lt;div dir=&quot;ltr&quot; style=&quot;text-align:left;&quot;&gt;&lt;div style=&quot;font-family:Helvetica;font-size:12px;&quot;&gt;Открыл по лицензии GNU дополнительные компоненты к версии своей библиотеки имитационного моделирования Айвика, написанной на языке F#. Теперь по открытой лицензии доступны не только разработка и запуск модели в Visual Studio или Xamarin Studio, но можно также сохранять результаты, строить графики и т.п. Все это удовольствие автоматизируется несколькими дополнительными строками кода.&lt;/div&gt;&lt;div style=&quot;font-family:Helvetica;font-size:12px;min-height:14px;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;font-family:Helvetica;font-size:12px;&quot;&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/dsorokin/aivika-fsharp-ce&quot;&gt;https://github.com/dsorokin/aivika-fsharp-ce&lt;/a&gt;&lt;/div&gt;&lt;div style=&quot;font-family:Helvetica;font-size:12px;min-height:14px;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;font-family:Helvetica;font-size:12px;&quot;&gt;В дополнение к существующей документации в формате PDF выложил исходники примеров, которые охватывают наиболее известные области имитационного моделирования: системная динамика, дискретно-событийное моделирование (управляемое временем, событиями и процессами), базовое агентное моделирование.&lt;/div&gt;&lt;div style=&quot;font-family:Helvetica;font-size:12px;min-height:14px;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;font-family:Helvetica;font-size:12px;&quot;&gt;Здесь замечу, что версия на Haskell по-прежнему остается более функциональной, и она имеет более чистый дизайн. В случае с F# пришлось пойти на некоторые упрощения. Зато доступна Visual Studio с IntelliSense, хотя лично я предпочитаю Aquamacs и runghc / cabal в терминале :)&lt;/div&gt;&lt;/div&gt;</description>
         <author>dsorokin</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-8641042312683198534.post-5785462257770010666</guid>
         <pubDate>Fri, 12 Jun 2015 09:28:00 +0000</pubDate>
      </item>
      <item>
         <title>Что нового в F# 3.1</title>
         <link>https://nesteruk.wordpress.com/2013/09/27/%d1%87%d1%82%d0%be-%d0%bd%d0%be%d0%b2%d0%be%d0%b3%d0%be-%d0%b2-f-3-1/</link>
         <description>Недавно в пререлиз VS2013 была залита версия F# 3.1 в которой, как ни странно, есть несколько полезняшек которые немного упрощают жизнь. В частности: Наконец-то кейсы дискриминированных объединений можно именовать. То есть если мы раньше писали то теперь можно дать имена аргументам, т.е.: Не могу сказать что это выглядит красиво, но это мне реально нужно для [&amp;#8230;]&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;https://pixel.wp.com/b.gif?host=nesteruk.wordpress.com&amp;#038;blog=373435&amp;#038;post=1148&amp;#038;subd=nesteruk&amp;#038;ref=&amp;#038;feed=1&quot; width=&quot;1&quot; height=&quot;1&quot;/&gt;</description>
         <guid isPermaLink="false">http://nesteruk.wordpress.com/?p=1148</guid>
         <pubDate>Fri, 27 Sep 2013 08:33:38 +0000</pubDate>
         <content:encoded><![CDATA[<p>Недавно в <a rel="nofollow" target="_blank" href="http://www.microsoft.com/visualstudio/eng/2013-downloads" title="http://www.microsoft.com/visualstudio/eng/2013-downloads">пререлиз VS2013</a> была залита версия F# 3.1 в которой, как ни странно, есть несколько полезняшек которые немного упрощают жизнь. В частности:</p>
<ul>
<li>Наконец-то кейсы дискриминированных объединений можно именовать. То есть если мы раньше писали
<pre>
type Stuff =
  | Pair of float * float
</pre>
<p>то теперь можно дать имена аргументам, т.е.:</p>
<pre>
type Stuff =
  | Pair of first : float * second : float
</pre>
<p>Не могу сказать что это выглядит красиво, но это мне реально нужно для <a rel="nofollow" target="_blank" href="http://activemesa.com/mathsharp" title="http://activemesa.com/mathsharp">MathSharp</a>, где разные конструкции MathML как раз и представлены таким большим объединением, и хочется помнить какой тип к чему относится. Да, и конечно же теперь есть паттерн-матчинг на все это, т.е. можно писать</p>
<pre>
match myPair with
| Pair(fisrt = 0.0f) -&gt; &#8942;
</pre>
</li>
<li>F# явно пытается стать чем-то вроде <a rel="nofollow" target="_blank" href="http://pluralsight.com/training/Courses/TableOfContents/matlab-fundamentals" title="http://pluralsight.com/training/Courses/TableOfContents/matlab-fundamentals">MATLAB</a>-а в плане работы с матрицами&nbsp;&ndash; в 3.0 они сделали так чтобы матрицы можно выпиливать кусочки например так <code>foo.[2..5,*]</code> что в MATLAB выглядело бы как <code>foo(2:5,:)</code>, а в 3.1 можно еще и брать отдельные элементы, например</li>
<pre>
foo.[2,*] // 2й ряд
bar.[*,5] // 5я колонка
</pre>
<li>Вывод типов для LINQ. <strong>Давно пора.</strong> Пока вы в уютном сишарпике писали <code>foo.Where(x =&gt; x.Bar)</code>, в F# творилось плохое приходилось навешшивать аннотации типов на параметр. Кажись пофиксили, теперь можно просто писать <code>foo.Where(fun x -&gt; x.Bar)</code>. Э-эх, если бы они еще <code>fun</code> убрали для лаконичности, хотя это наверное не реально.</li>
<li>Раньше, если вы импортировали из C# методы расширения с дженериками (например <a rel="nofollow" target="_blank" href="http://devtalk.net/csharp/chained-null-checks-and-the-maybe-monad/" title="http://devtalk.net/csharp/chained-null-checks-and-the-maybe-monad/">монаду Maybe</a>&nbsp;&mdash; хотя зачем?) то F# их не видел. Теперь в 3.1 все должно работать и, более того, можно самому делать подобные расширения. Правда F# как всегда отличился и добавил анти-ООПшного изврата в сей процесс путем не давания возможности ограничить generic-параметр (в стиле <code>where foo : Bar, new()</code>. Обещают пофиксить в будущем, а пока рекомендуют пользоваться <code>[&lt;Extension&gt;]</code>.</li>
<li>В констрантных выражениях теперь можно писать вещи вроде
<pre>
[&lt;Literal&gt;]
let foo = &quot;bar&quot; + &quot;baz&quot;
</pre>
</li>
</ul>
<p>Это что касается языка. Помимо этого, есть какие-то попытки улучшить поддержку VS, но если честно&nbsp;&mdash; улучшение тултипов и выравнивания кода не даст мне возможность лучше идентифицировать ошибки или делать рефакторинги. Более того, все мои дискуссии с F# community сводятся к тому что все с пеной у рта бегут доказывать что «ReSharper не нужен»,ну и следовательно продолжать диалог сложно.</p>
<p>Что ж, скажем спасибо что язык хотя бы не стоит на месте. Хотя хотелось бы конечно большего. Вот <a rel="nofollow" target="_blank" href="http://blogs.msdn.com/b/fsharpteam/archive/2013/06/27/announcing-a-pre-release-of-f-3-1-and-the-visual-f-tools-in-visual-studio-2013.aspx" title="http://blogs.msdn.com/b/fsharpteam/archive/2013/06/27/announcing-a-pre-release-of-f-3-1-and-the-visual-f-tools-in-visual-studio-2013.aspx">ссылка на пост</a> где помимо языковой части еще затронут инструментарий и либы&nbsp;&ndash; может будет интересно.&nbsp;■</p><br />Filed under: <a rel="nofollow" target="_blank" href='https://nesteruk.wordpress.com/category/net/f/'>f#</a> Tagged: <a rel="nofollow" target="_blank" href='https://nesteruk.wordpress.com/tag/f/'>f#</a>, <a rel="nofollow" target="_blank" href='https://nesteruk.wordpress.com/tag/vs2013/'>vs2013</a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gocomments/nesteruk.wordpress.com/1148/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/nesteruk.wordpress.com/1148/"/></a> <img alt="" border="0" src="https://pixel.wp.com/b.gif?host=nesteruk.wordpress.com&#038;blog=373435&#038;post=1148&#038;subd=nesteruk&#038;ref=&#038;feed=1" width="1" height="1"/>]]></content:encoded>
         <media:content medium="image" url="https://0.gravatar.com/avatar/f01cbd2238e2a78e4c43fa596f51d6a1?s=96&amp;amp;d=https%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&amp;amp;r=PG">
            <media:title type="html">nesteruk</media:title>
         </media:content>
      </item>
      <item>
         <title>F# на юниксе</title>
         <link>http://dsorokin.blogspot.com/2013/08/f.html</link>
         <description>&lt;div dir=&quot;ltr&quot; style=&quot;text-align:left;&quot;&gt;&lt;br /&gt;&lt;div style=&quot;font-family:Helvetica;font-size:12px;&quot;&gt;Оказывается, можно замечательно использовать F# на маке с помощью Mono и Xamarin Studio. Очень удобно, и мой проект от Visual Studio работает прекрасно. Попробовал редактировать и создавать файлы в Xamarin Studio. Мне понравилось. Даже лень было сегодня загружаться в винду, где у меня установлена Visual Studio.&amp;nbsp;&lt;/div&gt;&lt;div style=&quot;font-family:Helvetica;font-size:12px;min-height:14px;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;font-family:Helvetica;font-size:12px;&quot;&gt;Надо сказать, что ребята из Xamarin достигли заметного прогресса. Что меня больше всего потрясло, так это то, что в некоторых моих тестах Mono заметно обгоняет .NET, делая поправку на то, что гонял я тесты на одной машине, но под разными операционками, да и тесты, вероятно были несколько специфическими. Ни за что бы не поверил в возможность такого еще пару лет назад!&lt;/div&gt;&lt;/div&gt;</description>
         <author>dsorokin</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-8641042312683198534.post-4917484824134031892</guid>
         <pubDate>Sun, 25 Aug 2013 19:24:00 +0000</pubDate>
      </item>
      <item>
         <title>[Из песочницы] Жизнь Конвея на F# + OpenGL</title>
         <link>http://habrahabr.ru/post/173419/</link>
         <description>&lt;br/&gt;&lt;h4&gt;Почему F#?&lt;/h4&gt;&lt;br/&gt;
&lt;img src=&quot;http://habrastorage.org/storage2/fb6/592/43b/fb659243be50afdc64df69b34a0e349e.png&quot;/&gt;&lt;br/&gt;
Просто потому что он мне нравится. Решив пару десятков задач на &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://projecteuler.net/&quot;&gt;projecteuler&lt;/a&gt; я решил найти более практическое применение знаниям и написать нечто не сложное, но осязаемое.&lt;br/&gt;
&lt;br/&gt;
Кому интересно — добро пожаловать под кат.&lt;br/&gt;
 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://habrahabr.ru/post/173419/#habracut&quot;&gt;Читать дальше &amp;rarr;&lt;/a&gt;</description>
         <author>msmaximuss</author>
         <guid isPermaLink="false">http://habrahabr.ru/post/173419/</guid>
         <pubDate>Tue, 19 Mar 2013 11:11:42 +0000</pubDate>
      </item>
      <item>
         <title>Записи, макросы, скала, вывод типов, SQL</title>
         <link>http://metaclass.livejournal.com/782271.html</link>
         <description>В очередной раз, в связи с &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://xeno-by.livejournal.com/82242.html&quot;&gt;макросами&lt;/a&gt; подниму свой любимый вопрос:&lt;br /&gt;Можно ли поиметь в языках типа скалы строгую типизацию, не объявляя типы записей заранее?&lt;br /&gt;&lt;br /&gt;Идея в следующем: у меня в Clojure большая часть DSL основана на том, что я могу в любое место описания строк-колонок-ячеек отчета (условно говоря, Excel-like таблица фиксированной формы, заполняемая автоматом из проводок) в любой момент добавить атрибут типа :skip-in-vat true и обработать его. При этом мне нужно это изменить ровно в двух местах - описание документа (&quot;данные&quot;) и расчетный алгоритм (&quot;код&quot;). Типов тут нет, а вместо них - структуры данных, скомбинированные из словарей, массивов и атомарных данных.&lt;br /&gt;&lt;br /&gt;Но с динамически типизированными языками, а особенно с Clojure с ее destructring и прагматичным подходам к совместимости типов имеется постоянно проблема вида &quot;сунул лишние скобки, на место числа попал массив и через 100500 вызовов когда дело дошло до суммирования, оператор + сдох от попытки просуммировать ссылку на массив со стек-трейсом на три страницы&quot;. Причем если мне такие ошибки чинить достаточно легко, то менее опытным коллегам это вырывает мозг.&lt;br /&gt;&lt;br /&gt;В F# и прочих типизированных языках же мне придется сначала ползти в описание записи (если там записи вообще есть), добавлять поле или хуже того - еще один вариант для алгебраического типа, править вызовы конструкторов (если оверлоадинга нет) и прочая и прочая. &lt;br /&gt;&lt;br /&gt;Кроме того, часто хочется такого: &quot;тип записи создается в SQL запросе и далее используется в функции, обрабатывающей результат запроса&quot;. В clojure это опять же - словарь, с кейвордами в качестве ключей.&lt;br /&gt;&lt;br /&gt;Языки же кроме F#, Scala и Clojure можно не рассматривать вообще - на них аналогичные задачи или сводятся к &quot;наняли 100 ртишников по одному на объект предметной области и написали вручную&quot; или к &quot;написали самодельный лисп с хаскелем на дельфи/C#&quot; или к &quot;используем безумные ORM с еще более дикими, чем SQL языками и внешними декларативными описаниями&quot;.&lt;br /&gt;Т.е. я не говорю, что они не пригодны - но затраты ресусов на решение задачи на таких языках заметно больше.</description>
         <guid isPermaLink="false">urn:lj:livejournal.com:atom1:metaclass:782271</guid>
         <pubDate>Wed, 20 Feb 2013 14:04:36 +0000</pubDate>
      </item>
      <item>
         <title>Привет из 80х годов прошлого века</title>
         <link>http://metaclass.livejournal.com/727254.html</link>
         <description>Вспомнил один срач на тему однопроходных компиляторов, где Steve Yegge критиковал Clojure за то, что в ней объявления видны не во всем модуле, а только ниже объявления. (Ну, за исключением declare которые что-то вроде forward-объявлений).&lt;br /&gt; Сижу приделываю новую фичу к кодогенератору на F# - и таки внезапно оказывается, что это не только в Clojure, но так же и F#, и, что самое печальное, - в долбаном SQL, который я генерирую. &lt;br /&gt;Сижу вот, сортирую объекты из которых генерируется SQL по зависимостям.&lt;br /&gt;&lt;br /&gt; А как с этим дела обстоят в Scala? &lt;br /&gt; Я тут подумываю, что надо бы провести сравнение F# и Scala на моих задачах, все равно уже полная работа JVM и жаб, так может, выводилка типов в Scala для меня окажется более приемлемой, чем дикий ад в F# (теперь я понимаю, почему его &lt;span class=&quot;ljuser  i-ljuser  i-ljuser-type-P     &quot;&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://thesz.livejournal.com/profile&quot; class=&quot;i-ljuser-profile&quot;&gt;&lt;img class=&quot;i-ljuser-userhead&quot; src=&quot;http://l-stat.livejournal.net/img/userinfo.gif?v=17080?v=131.4&quot;/&gt;&lt;/a&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://thesz.livejournal.com/&quot; class=&quot;i-ljuser-username&quot;&gt;&lt;b&gt;thesz&lt;/b&gt;&lt;/a&gt;&lt;/span&gt;  критикует). Ну и макросы в скале &lt;span class=&quot;ljuser  i-ljuser  i-ljuser-type-P     &quot;&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://xeno-by.livejournal.com/profile&quot; class=&quot;i-ljuser-profile&quot;&gt;&lt;img class=&quot;i-ljuser-userhead&quot; src=&quot;http://l-stat.livejournal.net/img/userinfo.gif?v=17080?v=131.4&quot;/&gt;&lt;/a&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://xeno-by.livejournal.com/&quot; class=&quot;i-ljuser-username&quot;&gt;&lt;b&gt;xeno_by&lt;/b&gt;&lt;/a&gt;&lt;/span&gt;  прикрутил вроде уже. &lt;br /&gt; Хотя единственное, что мне приходит в голову на тему приличного использования макросов - это при их выполнении долбится в БД или модель этой БД и генерировать код.</description>
         <guid isPermaLink="false">urn:lj:livejournal.com:atom1:metaclass:727254</guid>
         <pubDate>Mon, 03 Sep 2012 18:31:39 +0000</pubDate>
      </item>
      <item>
         <title>Чернейшее вуду F# и структурных типов</title>
         <link>http://metaclass.livejournal.com/725414.html</link>
         <description>Оказывается, в F# есть что-то вроде структурных типов/констрейнты на наличие членов класса:&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href='https://gist.github.com/3523947'&gt;https://gist.github.com/3523947&lt;/a&gt;&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href='http://codebetter.com/matthewpodwysocki/2009/09/28/generically-constraining-f-part-ii/'&gt;http://codebetter.com/matthewpodwysocki/2009/09/28/generically-constraining-f-part-ii/&lt;/a&gt;&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href='http://codebetter.com/matthewpodwysocki/2009/06/11/f-duck-typing-and-structural-typing/'&gt;http://codebetter.com/matthewpodwysocki/2009/06/11/f-duck-typing-and-structural-typing/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Но: синтаксис объявления и поведение вывода типов в этом случае выглядит крайне противоестественно, особенно в том плане, что касается автогенерируемых компилятором методов.&lt;br /&gt;&lt;br /&gt;PS: Мерзость. Если inline функцию объявить в другом модуле и сослаться на приватные члены этого модуля - все это перестает тайп-чекится вообще, а без inline такое сделать невозможно - тайп-чек не проходит вообще.&lt;br /&gt;&quot;The value 'dumpNamed' was marked inline but its implementation makes use of an internal or private function which is not sufficiently accessible&quot;&lt;br /&gt;или же, без inline:&lt;br /&gt;&quot;This code is not sufficiently generic. The type variable  ^T when  ^T : (member get_Name :  ^T -&amp;gt; string) could not be generalized because it would escape its scope.&quot;</description>
         <guid isPermaLink="false">urn:lj:livejournal.com:atom1:metaclass:725414</guid>
         <pubDate>Thu, 30 Aug 2012 08:04:38 +0000</pubDate>
      </item>
      <item>
         <title>Sequential comparison in F#</title>
         <link>http://ru-fsharp.livejournal.com/4490.html</link>
         <description>&lt;i&gt;В этом постинге нет крутого матана, но надеюсь, что это кому-то будет полезным с образовательной точки зрения.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Originally posted by &lt;span class=&quot;ljuser  i-ljuser  i-ljuser-type-P     &quot;&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://bytebuster463.livejournal.com/profile&quot; class=&quot;i-ljuser-profile&quot;&gt;&lt;img class=&quot;i-ljuser-userhead&quot; src=&quot;http://l-stat.livejournal.net/img/userinfo.gif?v=17080?v=131.4&quot;/&gt;&lt;/a&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://bytebuster463.livejournal.com/&quot; class=&quot;i-ljuser-username&quot;&gt;&lt;b&gt;bytebuster463&lt;/b&gt;&lt;/a&gt;&lt;/span&gt;  at &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://bytebuster463.livejournal.com/577225.html&quot;&gt;Sequential comparison in F#&lt;/a&gt;&lt;br /&gt;&lt;p&gt;This kind of questions becomes more and more popular:&lt;/p&gt;&lt;div style=&quot;margin-left:20px;&quot;&gt;I want to simplify expression &lt;code&gt;if(x == y&amp;nbsp;&amp;amp;&amp;amp; y == z)&lt;/code&gt;.&lt;br /&gt;I wish I could write &lt;code&gt;if(x == y&amp;nbsp;and z)&lt;/code&gt; but there is no syntax for that. What can I do?&lt;/div&gt;&lt;br /&gt;&lt;p&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://stackoverflow.com/a/11552429/974789&quot;&gt;Look at this solution&lt;/a&gt;. Also, is seems to be a good example of using monads, also known as &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://msdn.microsoft.com/en-us/library/dd233182.aspx&quot;&gt;Computation Expressions&lt;/a&gt;. Surprisingly to myself, it is fairly fast.&lt;/p&gt;&lt;div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;// Generic&lt;/span&gt;&lt;br /&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;inline&lt;/span&gt;&lt;span&gt; mOp1&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;&amp;#39;&lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; op sample x &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; op sample x&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; sample&lt;br /&gt;&lt;/span&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;inline&lt;/span&gt;&lt;span&gt; mOp2&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;&amp;#39;&lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; op1 op2 &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; sample&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; x &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; op1 b &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;op2 sample x&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;span&gt; sample&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;// Implementation for (=) and (&amp;amp;&amp;amp;)&lt;/span&gt;&lt;br /&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(==)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; mOp1 &lt;/span&gt;&lt;span&gt;(=)&lt;/span&gt;&lt;br /&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(&amp;amp;=)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; mOp2 &lt;/span&gt;&lt;span&gt;(&amp;amp;&amp;amp;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(=)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span&gt;// Use&lt;/span&gt;&lt;br /&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; ret1 &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; a &lt;/span&gt;&lt;span&gt;==&lt;/span&gt;&lt;span&gt; b &lt;/span&gt;&lt;span&gt;&amp;amp;=&lt;/span&gt;&lt;span&gt; c &lt;/span&gt;&lt;span&gt;&amp;amp;=&lt;/span&gt;&lt;span&gt; d &lt;/span&gt;&lt;span&gt;&amp;amp;=&lt;/span&gt;&lt;span&gt; e &lt;/span&gt;&lt;span&gt;|&amp;gt;&lt;/span&gt;&lt;span&gt; fst&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3&gt;How it works&lt;/h3&gt;&lt;p&gt;The approach is a very simplified &lt;em&gt;State monad&lt;/em&gt;. The monadic type is a tuple of &lt;code&gt;(bool, &amp;#39;T)&lt;/code&gt;. The first component is the boolean value of ongoing calculation, and the second is the sample value to compare with.&lt;/p&gt;&lt;p&gt;&lt;code&gt;(==)&lt;/code&gt; would initialize the monad, similar to &lt;code&gt;Delay&lt;/code&gt; operator.&lt;br /&gt;&lt;code&gt;(&amp;amp;=)&lt;/code&gt; is used for all subsequent comparisons. It is similar to &lt;code&gt;Bind&lt;/code&gt; operator.&lt;br /&gt;We don&amp;#39;t need &lt;code&gt;Return&lt;/code&gt; because &lt;code&gt;fst&lt;/code&gt; would serve pretty fine.&lt;br /&gt;&lt;code&gt;mOp1&lt;/code&gt; and &lt;code&gt;mOp2&lt;/code&gt; are abstractions over the logical operations. &lt;em&gt;These allow defining your own operators&lt;/em&gt;. Here are examples of &lt;code&gt;or-equal&lt;/code&gt; and &lt;code&gt;and-greater-than&lt;/code&gt;:&lt;/p&gt;&lt;div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(|=)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; mOp2 &lt;/span&gt;&lt;span&gt;(||)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(=)&lt;/span&gt;&lt;br /&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(.&amp;gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; mOp1 &lt;/span&gt;&lt;span&gt;(&amp;gt;)&lt;/span&gt;&lt;br /&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(&amp;amp;&amp;gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; mOp2 &lt;/span&gt;&lt;span&gt;(&amp;amp;&amp;amp;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(&amp;gt;)&lt;/span&gt;&lt;br /&gt;&lt;span&gt;// Use&lt;/span&gt;&lt;br /&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; ret2 &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; a &lt;/span&gt;&lt;span&gt;==&lt;/span&gt;&lt;span&gt; b &lt;/span&gt;&lt;span&gt;|=&lt;/span&gt;&lt;span&gt; c &lt;/span&gt;&lt;span&gt;|=&lt;/span&gt;&lt;span&gt; d &lt;/span&gt;&lt;span&gt;|=&lt;/span&gt;&lt;span&gt; e &lt;/span&gt;&lt;span&gt;|&amp;gt;&lt;/span&gt;&lt;span&gt; fst &lt;/span&gt;&lt;span&gt;// if any of b,c,d,e equals to a&lt;/span&gt;&lt;br /&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; ret3 &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;.&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;amp;&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&amp;gt;&lt;/span&gt;&lt;span&gt; fst &lt;/span&gt;&lt;span&gt;// true: 5&amp;gt;3 &amp;amp;&amp;amp; 5&amp;gt;4&lt;/span&gt;&lt;br /&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; ret4 &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;.&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;amp;&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;amp;&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&amp;gt;&lt;/span&gt;&lt;span&gt; fst &lt;/span&gt;&lt;span&gt;// false&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3&gt;Performance&lt;/h3&gt;&lt;p&gt;I have looked at solutions like &lt;code&gt;&lt;span&gt;List&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;forall &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;fun&lt;/span&gt;&lt;span&gt; n &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; n &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; a&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;code&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;span&gt; b&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;span&gt; c&lt;/span&gt;&lt;span&gt;;] &lt;/span&gt;&lt;/code&gt;&lt;/span&gt;&lt;/code&gt;, but constructing &lt;code&gt;List&lt;/code&gt; is quite slow, so my primary goal was performance.&lt;br /&gt;Running a chain of 8 comparisons, 10 million times:&lt;/p&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;04972ms &lt;code&gt;a=b &amp;amp;&amp;amp; a=с &amp;amp;&amp;amp; ...&lt;/code&gt;&lt;/li&gt;&lt;li&gt;23138ms &lt;code&gt;List&lt;/code&gt;-based&lt;/li&gt;&lt;li&gt;12367ms monadic&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;a rel=&quot;nofollow&quot; name='cutid1-end'&gt;&lt;/a&gt;&lt;p&gt;P.S. If you like it, you may upvote it on StackOverflow. :)&lt;/p&gt;</description>
         <author>...Вона блює і співає</author>
         <guid isPermaLink="false">urn:lj:livejournal.com:atom1:ru_fsharp:4490</guid>
         <pubDate>Wed, 29 Aug 2012 17:38:40 +0000</pubDate>
      </item>
      <item>
         <title>Point-free function application in F#</title>
         <link>http://ru-fsharp.livejournal.com/4117.html</link>
         <description>В коммуне по-прежнему тихо, потому подумалось, что эта мини-статья будет кому-то интересна. Не все знают, как использовать duck-typing для применения не-последнего аргумента.&lt;br /&gt;Модератору: не знаю, какие метки ставить. :( И не знаю: а ссылки на SO вообще можно, да? :-)&lt;br /&gt;&lt;br /&gt;Originally posted by &lt;span class=&quot;ljuser  i-ljuser  i-ljuser-type-P     &quot;&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://bytebuster463.livejournal.com/profile&quot; class=&quot;i-ljuser-profile&quot;&gt;&lt;img class=&quot;i-ljuser-userhead&quot; src=&quot;http://l-stat.livejournal.net/img/userinfo.gif?v=17080?v=131.4&quot;/&gt;&lt;/a&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://bytebuster463.livejournal.com/&quot; class=&quot;i-ljuser-username&quot;&gt;&lt;b&gt;bytebuster463&lt;/b&gt;&lt;/a&gt;&lt;/span&gt;  at &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://bytebuster463.livejournal.com/540105.html&quot;&gt;Point-free function application in F#&lt;/a&gt;&lt;div&gt;Pointless notation in F# is a powerful mechanism for coding, allowing the source be free of burdening arguments. Combined with &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Strong_typing&quot;&gt;strong typing&lt;/a&gt; it makes F# code very expressive.&lt;br /&gt;Say you have &lt;font face=&quot;Courier New&quot;&gt;(+)&lt;/font&gt; operator which has type of &lt;font face=&quot;Courier New&quot;&gt;int -&amp;gt; int -&amp;gt; int&lt;/font&gt;.&lt;br /&gt;You may define your&amp;nbsp;custom function:&lt;br /&gt;&lt;br /&gt;&lt;font face=&quot;Courier New&quot;&gt;let add2_version1 x = x + 2&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;This function will have type of &lt;font face=&quot;Courier New&quot;&gt;int -&amp;gt; int&lt;/font&gt; which means it takes an int and returns an int.&lt;br /&gt;This syntax is equal to:&lt;br /&gt;&lt;br /&gt;&lt;font face=&quot;Courier New&quot;&gt;let add2_version2 x = (+) 2 x&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;or&lt;br /&gt;&lt;br /&gt;&lt;font face=&quot;Courier New&quot;&gt;let add2_version3 x = ((+) 2) x&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;As we see, &lt;font face=&quot;Courier New&quot;&gt;((+) 2) &lt;/font&gt;is a function itself, and &lt;font face=&quot;Courier New&quot;&gt;x&lt;/font&gt;&amp;nbsp;is applied to it. So we can simplify our function:&lt;br /&gt;&lt;br /&gt;&lt;font face=&quot;Courier New&quot;&gt;let add2_version4 = (+) 2&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;But what if our operator is not symmetric, and we need to apply the first argument? Look at &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://stackoverflow.com/q/11378402/974789&quot;&gt;this question on StackOverflow&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;p&gt;How can I create a partial function application for a non-symmetric operator such as the modulus operator with regards to the first argument without any argument names in F#? My first attempt was &lt;code&gt;let mod10 = (%) 10&lt;/code&gt; which of course translates to&amp;nbsp;&lt;code&gt;mod10(x) = 10 mod x&lt;/code&gt; instead of the desired &lt;code&gt;mod10(x) = x mod 10&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://stackoverflow.com/a/11383421/974789&quot;&gt;Certainly, this is possible&lt;/a&gt;!&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; mod10 &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(%)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(|&amp;gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span&gt;How did we get it? Simple! &lt;b&gt;The following expressions are equal&lt;/b&gt;:&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; m1 x &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; x &lt;/span&gt;&lt;span&gt;%&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; m2 x &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(%)&lt;/span&gt;&lt;span&gt; x &lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;// x (op) y = (op) x y&lt;/span&gt;&lt;br /&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; m3 x &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;((%)&lt;/span&gt;&lt;span&gt; x&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;// f x y = (f x) y&lt;/span&gt;&lt;br /&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; m4 x &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&amp;gt;&lt;/span&gt;&lt;span&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span&gt;((%)&lt;/span&gt;&lt;span&gt; x&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span&gt;// f x = x |&amp;gt; f&lt;/span&gt;&lt;br /&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; m5 x &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;((|&amp;gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span&gt;((%)&lt;/span&gt;&lt;span&gt; x&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span&gt;// x |&amp;gt; f = (|&amp;gt;) x f&lt;/span&gt;&lt;br /&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; m6 x &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;((%)&lt;/span&gt;&lt;span&gt; x&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;|&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;((|&amp;gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &amp;nbsp; &lt;/span&gt;&lt;span&gt;// f x = x |&amp;gt; f&lt;/span&gt;&lt;br /&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; m7 x &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;x &lt;/span&gt;&lt;span&gt;|&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(%))&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;((|&amp;gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &amp;nbsp; &lt;/span&gt;&lt;span&gt;// (op) x = x |&amp;gt; (op)&lt;/span&gt;&lt;br /&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; m8 x &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; x &lt;/span&gt;&lt;span&gt;|&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;((%)&lt;/span&gt;&lt;span&gt; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;((|&amp;gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;))&lt;/span&gt;&lt;span&gt; &amp;nbsp;&lt;/span&gt;&lt;span&gt;// f(x) |&amp;gt; g = x |&amp;gt; (f &amp;gt;&amp;gt; g)&lt;/span&gt;&lt;br /&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; m9 &amp;nbsp; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span&gt;(%)&lt;/span&gt;&lt;span&gt; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;((|&amp;gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &amp;nbsp; &lt;/span&gt;&lt;span&gt;// remove formal argument&lt;/span&gt;&lt;br /&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; m10 &amp;nbsp;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span&gt;(%)&lt;/span&gt;&lt;span&gt; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span&gt; &amp;nbsp;&lt;/span&gt;&lt;span&gt;(|&amp;gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;// remove unnecessary parenthesis&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;ЗЫ. Если Вам понравилась эта статья, можно лайкнуть по ссылке :-)</description>
         <author>...Вона блює і співає</author>
         <guid isPermaLink="false">urn:lj:livejournal.com:atom1:ru_fsharp:4117</guid>
         <pubDate>Sun, 08 Jul 2012 14:57:42 +0000</pubDate>
      </item>
      <item>
         <title>О хвостовой рекурсии</title>
         <link>http://dsorokin.blogspot.com/2012/05/blog-post.html</link>
         <description>&lt;div dir=&quot;ltr&quot; style=&quot;text-align:left;&quot;&gt;&lt;br /&gt;Тут вышла статья на хабре [1], где написано:&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&quot;Хвостовая рекурсия это частный случай рекурсии, когда рекурсивный вызов может быть заменен итерацией.&quot;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Я почему-то всегда считал, что хвостовая рекурсия сложнее. Применительно к F# можно взять такой контр-пример.&lt;br /&gt;&lt;br /&gt;Возьмем реализацию оператора while для F# Async. В исходниках F# это будет функция whileA. Если считать, что bindA - это монадическая связка для Async, то видим, что:&lt;br /&gt;&lt;br /&gt;1) функция whileA вызывает bindA и передает последней вызов на саму себя, т.е. whileA определяется рекурсивно;&lt;br /&gt;&lt;br /&gt;2) функции whileA и bindA используют хвостовые вызовы.&lt;br /&gt;&lt;br /&gt;Отсюда можно заключить, что имеем случай хвостовой рекурсии (я прав в терминах?). При этом очевидно, что ни о какой замене whileA итерацией не может быть и речи, как минимум, в терминах .NET. Нужна соответствующая поддержка со стороны виртуальной машины.&lt;br /&gt;&lt;br /&gt;В данном случае все хвостовые вызовы внутри whileA и bindA будут помечены в IL специальным тегом, который опознается виртуальной машиной .NET. Это ощутимо замедляет выполнение кода, но стек вызовов не увеличивается, что и требуется.&lt;br /&gt;&lt;br /&gt;Так вот, имеем случай хвостовой рекурсии, несводимой к простой итерации в рамках .NET. Может быть, виртуальная машина и использует итерации, но это уже совсем другой внешний уровень.&lt;br /&gt;&lt;br /&gt;[1]&amp;nbsp;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://habrahabr.ru/post/143690/&quot;&gt;http://habrahabr.ru/post/143690/&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;</description>
         <author>dsorokin</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-8641042312683198534.post-4138884371607530332</guid>
         <pubDate>Tue, 22 May 2012 11:01:00 +0000</pubDate>
      </item>
      <item>
         <title>F# Хвостовая рекурсия. Подводные грабли. Часть 1</title>
         <link>http://habrahabr.ru/post/143690/</link>
         <description>&lt;br/&gt;&lt;img src=&quot;http://habrastorage.org/storage2/26f/1f4/f2f/26f1f4f2f90ff9365f7449e0bb51b353.jpg&quot; align=&quot;right&quot;/&gt;&lt;br/&gt;
&lt;em&gt;Винни Пух: Ой, что это случилось с твоим хвостом?&lt;br/&gt;
Иа: А что с ним могло случится?&lt;br/&gt;
Винни Пух: Его нет.&lt;br/&gt;
Иа: Ты не ошибся?&lt;br/&gt;
Винни Пух: Хвост или есть или нет совсем! Тут нельзя ошибиться.&lt;br/&gt;
Иа: А что же тогда там есть?&lt;br/&gt;
Винни Пух: Ничего!&lt;/em&gt;&lt;br/&gt;
&lt;br/&gt;
У нас в проекте, в одном из серверных компонентов, после очередного рефакторинга начала течь память. Казалось бы .NET, F#, менеджед код, сборка мусора, все дела, но память, куда-то утекала. Ценой бессонных ночей и попорченных нервов, источник утечки был найден. Оказалось что проблема вызвана куском кода, который был, чуть ли не один к одному скопирован из учебника по F#.&lt;br/&gt;
&lt;br/&gt;
Все дело было в хвостовой рекурсии, вернее, как оказалось в ее отсутствии в неожиданных местах. &lt;br/&gt;
 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://habrahabr.ru/post/143690/#habracut&quot;&gt;Читать дальше &amp;rarr;&lt;/a&gt;</description>
         <author>temaHT</author>
         <guid isPermaLink="false">http://habrahabr.ru/post/143690/</guid>
         <pubDate>Mon, 21 May 2012 09:25:27 +0000</pubDate>
      </item>
      <item>
         <title>F*</title>
         <link>http://ru-fsharp.livejournal.com/4035.html</link>
         <description>&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://research.microsoft.com/en-us/projects/fstar/&quot;&gt;http://research.microsoft.com/en-us/projects/fstar/&lt;/a&gt;:&lt;br /&gt;«F* is a new dependently typed language for secure distributed programming. It's designed to be enable the construction and communication of proofs of program properties and of properties of a program's environment in a verifiably secure way. F* compiles to .NET bytecode in type-preserving style, and interoperates smoothly with other .NET languages, including F#, on which it is based.&lt;br /&gt;&lt;br /&gt;Self-certification of F*: We have verified the F* type checker using F* itself, using a novel bootstrapping technique called &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://research.microsoft.com/~nswamy/papers/popl2012-paper211.pdf&quot;&gt;self-certification&lt;/a&gt;.»&lt;br /&gt;&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://research.microsoft.com/apps/pubs/?id=141708&quot;&gt;http://research.microsoft.com/apps/pubs/?id=141708&lt;/a&gt;:&lt;br /&gt;«We present F*, a full-fledged design and implementation of a new dependently typed language for secure distributed programming. Unlike prior languages, F* provides arbitrary recursion while maintaining a logically consistent core; it enables modular reasoning about state and other effects using affine types; and it supports proofs of refinement properties using a mixture of cryptographic evidence and logical proof terms. The key mechanism is a new kind system that tracks several sub-languages within F* and controls their interaction. F* subsumes two previous languages, F7 and Fine. We prove type soundness (with proofs partially mechanized in Coq) and logical consistency for F*.»&lt;br /&gt;&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://nponeccop.livejournal.com/258410.html&quot;&gt;Via&lt;/a&gt; &lt;span class=&quot;ljuser  i-ljuser  i-ljuser-type-P     &quot;&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://nponeccop.livejournal.com/profile&quot; class=&quot;i-ljuser-profile&quot;&gt;&lt;img class=&quot;i-ljuser-userhead&quot; src=&quot;http://l-stat.livejournal.net/img/userinfo.gif?v=17080?v=131.4&quot;/&gt;&lt;/a&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://nponeccop.livejournal.com/&quot; class=&quot;i-ljuser-username&quot;&gt;&lt;b&gt;nponeccop&lt;/b&gt;&lt;/a&gt;&lt;/span&gt; .</description>
         <author>Qbit</author>
         <guid isPermaLink="false">urn:lj:livejournal.com:atom1:ru_fsharp:4035</guid>
         <pubDate>Fri, 30 Mar 2012 09:14:50 +0000</pubDate>
      </item>
      <item>
         <title>Вернулся из спячки</title>
         <link>http://norgblog.blogspot.com/2012/03/blog-post.html</link>
         <description>Что-то я давно ничего не писал. Буду исправляться.

За последнее время я слегка разочаровался в F# и находился в неком поиске себя и тех инструментов, которые мне было бы интересно изучить и использовать.

Наверно стоит сказать пару слов почему я отказался от F#.



Плохой компилятор. В общем то всё хорошо, но дьявол кроется в мелочах. И одна из этих мелочей -  rec. Нет, он честно раскрывается в</description>
         <author>Максим Карандашов</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-5219626453078054207.post-5722406536090747269</guid>
         <pubDate>Sat, 03 Mar 2012 15:19:00 +0000</pubDate>
      </item>
      <item>
         <title>Что-то тихо здесь</title>
         <link>http://ru-fsharp.livejournal.com/3835.html</link>
         <description>Посмотрел, что в коммуне слишком тихо, вот и попросился у уважаемого модератора права на запись. Давайте что-то обсудим, что ли. :)&lt;br /&gt;Например, вот что есть в моём скромном маленьком проекте (на вебе уже живёт, но ссылку не даю, во избежание):&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Разбор естественного человеческого языка (тайского) с помощью FParsec. Сам автор ФПарсека, Stephan Tolksdorf, сказал, что он никогда не думал, что его детищем могут парсить натуральные языки. Скоро будет также лаосский, камбоджийский, санскрит и деванагари.&lt;/li&gt;&lt;li&gt;Монадическая модель доказательства к логическому выводу, написанная с нуля (советы будут приняты с огромной радостью, ибо написано на коленке).&lt;/li&gt;&lt;/ol&gt;&lt;b&gt;Про FParsec&lt;/b&gt; всё понятно, кроме того, что он используется для нечёткого парсинга, примерно такого же, который используется для парсинга некомпилирующегося кода в проектах типа ReSharper.&lt;br /&gt;Другими словами, производится иерархический парсинг с возвратом до тех пор, пока не будет обнаружен чёткий признак, что парсинг можно прервать. Затем все получившиеся цепочки взвешиваются и выбирается самая &amp;quot;качественная&amp;quot;:&lt;br /&gt;val variants: Parser&amp;lt;&amp;#39;T seq&amp;gt; -&amp;gt; Parser&amp;lt;&amp;#39;T list list&amp;gt;&lt;br /&gt;Где на входе список правил, а на выходе список, каждый элемент в котором - упорядоченный список правил, которые могут быть применены ко входному потоку.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Про модель доказательства&lt;/b&gt; в двух словах.&lt;br /&gt;Рассматриваем каждую функцию как механизм получения логического вывода. Аргументы - это некоторые аксиомы, поданные на вход (&amp;quot;икс равен пяти&amp;quot;). Функция может обращаться к другим функциям, которые, в свою очередь, тоже делают какие-то выводы по таким же правилам. Моя цель была - провести &amp;quot;трассу&amp;quot; логических выводов сквозь все частные выводы к конечной цели.&lt;br /&gt;&lt;br /&gt;Для этого каждая функция возвращает не просто сам по себе результат, а&lt;pre&gt;&amp;#39;TResult * Tree&amp;lt;&amp;#39;TProof&amp;gt;&lt;/pre&gt;Где дерево упрощённо выглядит как&lt;br /&gt;&lt;pre&gt;Tree&amp;lt;&amp;#39;T&amp;gt; = | Empty | Leaf of &amp;#39;T | Node of &amp;#39;T * List&amp;lt;Tree&amp;lt;&amp;#39;T&amp;gt;&amp;gt; &lt;/pre&gt;&lt;br /&gt;Цепочка функций сопрягается примерно так:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;let increment a = proven &amp;quot;incremented&amp;quot; {
&amp;nbsp;&amp;nbsp;&amp;nbsp; let! _ = a &amp;lt;!?&amp;gt; &amp;quot;argument a&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp; return a+1
&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;
let mymethod x y = proven &amp;quot;mymethod&amp;quot; {
&amp;nbsp;&amp;nbsp;&amp;nbsp; let! _ = x &amp;lt;!?&amp;gt; &amp;quot;argument x&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp; let! _ = y &amp;lt;!?&amp;gt; &amp;quot;argument y&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp; let! x2 = increment x
&amp;nbsp;&amp;nbsp;&amp;nbsp; let! y2 = increment y
&amp;nbsp;&amp;nbsp;&amp;nbsp; return x2+y2
&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;
let result, resultProof = mymethod 5 20

&lt;/pre&gt;Такой вызов вернёт resultProof, который можно представить в виде:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;Goal: mymethod = 27 because
|     (1) argument x = 5
| AND (2) argument y = 20
| AND (3) incremented = 6 because
| |     (3.1) argument a = 5
| AND (4) incremented = 21 because
| |     (4.1) argument a = 20
&lt;/pre&gt;&lt;br /&gt;Оператор &amp;lt;!?&amp;gt; - это shortcut на простой метод &amp;#39;T -&amp;gt; &amp;#39;T * Leaf&amp;lt;string&amp;gt;&lt;br /&gt;&lt;br /&gt;Да, и ещё. На самом деле, дерево не просто из стрингов состоит, а из Lazy&amp;lt;string&amp;gt;. То есть, само дерево формируется сразу, а логический вывод, который не всегда нужен юзеру, да ещё и активно вызывающий sprintf (который тяжёлый), формируется только тогда, когда мы уже дерево визуализируем в текст или XML.&lt;a rel=&quot;nofollow&quot; name='cutid1-end'&gt;&lt;/a&gt;</description>
         <author>...Вона блює і співає</author>
         <guid isPermaLink="false">urn:lj:livejournal.com:atom1:ru_fsharp:3835</guid>
         <pubDate>Sun, 11 Dec 2011 16:41:39 +0000</pubDate>
      </item>
      <item>
         <title>[Перевод] Machete — скриптовая среда для .Net</title>
         <link>http://habrahabr.ru/post/125277/</link>
         <description>&lt;br/&gt;В попытке побороть моё стремление к совершенству, я решил открыть исходники моего долгосрочного проекта Machete для всеобщего просмотра. Machete — это мой собственный диалект стандарта ECMAScript 5 или, как его чаще называют, JavaScript.&lt;br/&gt;
&lt;br/&gt;
&lt;h5&gt;Основные возможности&lt;/h5&gt;&lt;br/&gt;
&lt;h6&gt;Более понятные лямбда-выражения&lt;/h6&gt;&lt;br/&gt;
&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;var succinct = &amp;#92;(x, y) x + y;
var verbose = function (x, y) { return x + y; };&lt;/code&gt;&lt;/pre&gt;&lt;br/&gt;
&lt;br/&gt;
&lt;h6&gt;Поддержка итерации с помощью цикла foreach и генераторов&lt;/h6&gt;&lt;br/&gt;
&lt;pre&gt;&lt;code class=&quot;cs&quot;&gt;var numbers = generator {
    yield 1;
    yield 2;
    yield 3;
};

foreach (var n in numbers) {
    Output.write(n);
}   

foreach (var e in [&amp;quot;Array&amp;quot;, &amp;quot; objects&amp;quot;, &amp;quot; are&amp;quot;, &amp;quot; iterable&amp;quot;, &amp;quot;!&amp;quot;]) {
    Output.write(e);
} 

foreach (var ch in &amp;quot;Strings are iterable!&amp;quot;) {
    Output.write(ch);
}
&lt;/code&gt;&lt;/pre&gt;&lt;br/&gt;
&lt;h5&gt;Реализация&lt;/h5&gt;&lt;br/&gt;
&lt;ul&gt;
&lt;li&gt;компилятор написан на языке F# с использованием библиотеки &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://bitbucket.org/fparsec/main/overview&quot;&gt;FParsec&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;исполняющая среда написана на языке C# и находится под управлением .NET&lt;/li&gt;
&lt;li&gt;в настоящее время имеется более 400 тестов, и еще множество разрабатывается&lt;/li&gt;
&lt;/ul&gt;&lt;br/&gt;
&lt;br/&gt;
Machete — это продукт нескольких лет исследований, проектирования и программирования. Я разместил его на GitHub, так что пожалуйста, заходите и форкайте проект. Я бы очень хотел увеличить количество тестов и тесты от сообщества были бы неоценимы.&lt;br/&gt;
&lt;br/&gt;
Ссылка на репозиторий: &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/ChaosPandion/Machete&quot;&gt;GitHub Repository For Machete&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://habrahabr.ru/post/125277/#habracut&quot;&gt;&lt;/a&gt;</description>
         <author>InTRUEdeR</author>
         <guid isPermaLink="false">http://habrahabr.ru/post/125277/</guid>
         <pubDate>Sat, 30 Jul 2011 11:03:27 +0000</pubDate>
      </item>
      <item>
         <title>10 «однострочников», которые произведут впечатление на ваших друзей</title>
         <link>http://habrahabr.ru/post/120665/</link>
         <description>&lt;br/&gt;За последнюю неделю появилось несколько топиков с названием «10 однострочников на &amp;lt;MY_LANGUAGE&amp;gt;, которые произведут впечатление на ваших друзей», которые содержат однострочное решение нескольких простых задач, демонстрирующее достоинства и «крутость» любимого языка программирования автора. Я решил перевести их и для сравнения собрать в одном топике. Вся волна началась (вроде как) со Scala. &lt;br/&gt;
Итак, поехали!&lt;br/&gt;
 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://habrahabr.ru/post/120665/#habracut&quot;&gt;Читать дальше &amp;rarr;&lt;/a&gt;</description>
         <author>Amper</author>
         <guid isPermaLink="false">http://habrahabr.ru/post/120665/</guid>
         <pubDate>Mon, 06 Jun 2011 07:25:35 +0000</pubDate>
      </item>
      <item>
         <title>Тестирование библиотек F# в Visual Studio</title>
         <link>http://norgblog.blogspot.com/2011/06/f-visual-studio.html</link>
         <description>Когда создаётся новый проект F# Library, то в довесок в *.fs файлу идёт Srcipt.fsx. И в этот скрипт логично бы запилить функционал теста работы библиотеки, причём хорошо бы прогонять этот тест автоматически.

Оказывается это возможно и делается довольно легко и просто.

Итак, по по пунктам:

1. ПКМ на Script.fsx -&amp;gt; Properties -&amp;gt; Copy to Output Directory выставить в Copy Always. Это необходимо для</description>
         <author>Максим Карандашов</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-5219626453078054207.post-7374714719340982829</guid>
         <pubDate>Thu, 02 Jun 2011 09:39:00 +0000</pubDate>
      </item>
      <item>
         <title>[Из песочницы] Паттерны Command и Strategy с точки зрения функционального программирования</title>
         <link>http://habrahabr.ru/post/120375/</link>
         <description>&lt;br/&gt;В результате изучения функционального программирования в моей голове появились некоторые мысли, которыми я хочу с вами поделиться.&lt;br/&gt;
&lt;br/&gt;
&lt;h4&gt;Паттерны проектирования и функциональное программирование? Как это вообще связано?&lt;/h4&gt;&lt;br/&gt;
В умах многих разработчиков, привыкших к объектно-ориентированной парадигме, возникает впечатление, что проектирование программного обеспечения, как таковое, неразрывно связано с ООП и всё остальное — суть ересь. UML, большей частью нацеленный на ООП, используется как универсальный язык для проектирования — хотя он таким, конечно, не является. И мы видим, как мир объектно-ориентированного программирования постепенно погружается в пучину преступного переинженеринга (1).&lt;br/&gt;
В силу этого зачастую даже не ставится вопрос о &lt;i&gt;выборе парадигмы программирования&lt;/i&gt;. Тем не менее, этот вопрос является весьма существенным, и зачастую правильный ответ даёт большие преимущества (3). Это, вообще говоря, выходит за рамки того, что мы привыкли называть проектированием — это вопрос из области архитектуры.&lt;br/&gt;
&lt;br/&gt;
&lt;h5&gt;Лирическое отступление: разница между архитектурой, проектированием и реализацией&lt;/h5&gt;&lt;br/&gt;
Не так давно я наткнулся на весьма интересное исследование — (2). В нём рассматривается задача формализации понятий «архитектура», «проектирование» и «реализация», которые чаще всего употребляются неформально. И авторам удаётся вывести весьма интересный критерий: критерий Intension/Locality. Я не буду углубляться в философию и просто приведу краткое описание критерия (эта часть — фактически перевод) и мои выводы из него.&lt;br/&gt;
Свойство Intension (интенсионность) означает способность некой сущности описывать бесконечное множество предметов: например, понятие простого числа. Ему противоположно свойство экстенсионности — сущность описывает конечный набор предметов: например, понятие страны — члены НАТО.&lt;br/&gt;
Свойство локальности — сущность влияет только на отдельную часть системы. Соответственно, глобальность — сущность влияет на всю систему в целом.&lt;br/&gt;
Дак вот, учитывая эти два свойства, авторы указанного исследования составляют такую таблицу:&lt;br/&gt;
&lt;img src=&quot;http://i060.radikal.ru/1105/fd/6c8f6e32d01a.jpg&quot; alt=&quot;image&quot;/&gt;&lt;br/&gt;
Пользуясь ей легко определить, что относится к уровню архитектуры, а что — к уровню проектирования. И вот мой вывод: &lt;i&gt;выбор парадигмы программирования, платформы и языка — это решение уровня архитектуры&lt;/i&gt;, т.к. этот выбор глобален (затрагивает все части системы) и интенсионен (парадигмы определяют способы решения бесконечного множества задач).&lt;br/&gt;
&lt;br/&gt;
Тем не менее, решить столь глобальную задачу (найти критерии выбора подходящей парадигмы) мне пока не по силам. Поэтому я решил выбрать два уже существующих класса задач и показать, что для них стоит использовать не привычный для многих ОО подход, а функциональный, который в последнее время приобретает (заслуженно) всё большую популярность.&lt;br/&gt;
Классы задач я выбрал необычным методом — я взял два паттерна ОО проектирования и показал, что они, по сути — ограниченная реализация понятия из области функционального программирования — функции высшего порядка (higher-order function, далее: ФВП). Гипотеза заключалась в том, что паттерны — &lt;i&gt;это устоявшиеся решения определённых проблем&lt;/i&gt;, а раз возникают проблемы и их устоявшиеся решения, видимо есть некие слабости и недостатки, которые приходиться преодолевать. Для рассмотренных паттернов это действительно так.&lt;br/&gt;
Кстати говоря, подобный подход был использован в (5) и (6). В (6) вообще было указано на возможность замены большинства паттернов, но подробный анализ каждого не проводился. В (5) было более подробное рассмотрение Command и Strategy, но немного с другой стороны. Я решил сделать что-то более практичное, чем в (6), и с другими акцентами, чем в (5). Итак, приступим.&lt;br/&gt;
&lt;br/&gt;
 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://habrahabr.ru/post/120375/#habracut&quot;&gt;Читать дальше &amp;rarr;&lt;/a&gt;</description>
         <author>Lakret</author>
         <guid isPermaLink="false">http://habrahabr.ru/post/120375/</guid>
         <pubDate>Wed, 01 Jun 2011 13:27:50 +0000</pubDate>
      </item>
      <item>
         <title>Релиз Nemerle 1.0</title>
         <link>http://ru-fsharp.livejournal.com/3563.html</link>
         <description>«12 мая 2011 года вышла в свет первая версия &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://groups.google.com/group/nemerle-en/browse_thread/thread/e347cbc22e993c32?tvc=2&quot;&gt;Nemerle 1.0&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;В состав инсталлятора входит:&lt;br /&gt;• Компилятор командной строки ncc.exe Nemerle 1.0 для .NET 2–3.5 и Mono 2.x.&lt;br /&gt;• Модуль интеграции с IDE Microsoft Visual Studio 2008.&lt;br /&gt;• Nemerle Express Edition — отдельная IDE на основе Microsoft Visual Studio Shell 2008 Isolated. Данная версия не требует наличия коммерческой версии Microsoft Visual Studio 2008. Для ее установки сначала скачайте и установите Microsoft Visual Studio Shell 2008 Isolated, а затем произведите установку Nemerle 1.0. При этом нужно выбрать вариант установки «Advanced» и убедиться, что пункт «Visual Studio Express Edition» выбран.&lt;br /&gt;• Стандартная библиотека Nemerle и стандартная библиотека макросов.&lt;br /&gt;• Набор дополнительных макробиблиотек — Nemerle Power Pack (ComputationExpressions, Nemerle.Xml, Nemerle.Peg, Nemerle.WPF, Nemerle.Aop, Nemerle.Linq).&lt;br /&gt;• Компилятор в виде .NET-компонента (Nemerle.Compiler.dll).&lt;br /&gt;• Плагин к компилятору позволяющий компилировать файлы C# 4.0.&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.rsdn.ru/Forum/nemerle/4269435.aspx&quot;&gt;»&lt;/a&gt;</description>
         <author>Qbit</author>
         <guid isPermaLink="false">urn:lj:livejournal.com:atom1:ru_fsharp:3563</guid>
         <pubDate>Tue, 17 May 2011 14:35:12 +0000</pubDate>
      </item>
      <item>
         <title>Генератор функций являющихся автоматами</title>
         <link>http://norgblog.blogspot.com/2011/04/blog-post.html</link>
         <description>Переоткрыл очередной  велосипед.
Меня всегда раздражало то, что для задания автомата приходилось  что-то примерно такого вида(mutable можно и на ref заменить, не суть  важно):

type Aut(state: 'S) =
  let mutable st = state
  
  member this.Next(x: 'A): 'B =
    ...
    st &amp;lt;- ...
    result
т.е. делать отдельный класс под каждый автомат или класс  обёртку. Мне хотелось чего-нибудь более</description>
         <author>Максим Карандашов</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-5219626453078054207.post-5375078481582647788</guid>
         <pubDate>Wed, 27 Apr 2011 11:04:00 +0000</pubDate>
      </item>
      <item>
         <title>Введение в F#, the blue pill</title>
         <link>http://habrahabr.ru/post/116904/</link>
         <description>&lt;br/&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://habrahabr.ru/blogs/net/116666/&quot;&gt;[&lt;b&gt;Предыдущий пост&lt;/b&gt;]&lt;/a&gt;&lt;br/&gt;
&lt;h4&gt;Введение&lt;/h4&gt;&lt;br/&gt;
&lt;img src=&quot;http://t1.gstatic.com/images?q=tbn:ANd9GcThZSyhC328NSTxS5_XWnDRerYBpJzxIQ3HWkZlQu0RY-dZkbUiie9Rjrg&quot; alt=&quot;image&quot;/&gt;&lt;br/&gt;
Вот и ожидаемое, или не очень, продолжение. Сегодня мы проглотим синюю пилюлю, гордо олицетворяющую FP (functional programming), и погрузимся в функциональную часть F# еще глубже. Поговорим о функциях, рекурсии, pattern matching'е и еще о нескольких интересных вещах. Интересно? Тогда глотаем таблетку и начинаем погружение.&lt;br/&gt;
&lt;br/&gt;
 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://habrahabr.ru/post/116904/#habracut&quot;&gt;Читать дальше &amp;rarr;&lt;/a&gt;</description>
         <author>kernelmode</author>
         <guid isPermaLink="false">http://habrahabr.ru/post/116904/</guid>
         <pubDate>Tue, 05 Apr 2011 17:08:12 +0000</pubDate>
      </item>
      <item>
         <title>[Из песочницы] Введение в F#, или полезное о бесполезном</title>
         <link>http://habrahabr.ru/post/116666/</link>
         <description>&lt;br/&gt;&lt;h4&gt;Вступление&lt;/h4&gt;&lt;br/&gt;
&lt;br/&gt;
&lt;h5&gt;А зачем оно мне?&lt;/h5&gt;&lt;br/&gt;
&lt;img src=&quot;http://www.vegansoapbox.com/wordpress/wp-content/uploads/2009/10/why.jpg&quot; alt=&quot;image&quot;/&gt;&lt;br/&gt;
&lt;br/&gt;
А почему бы и нет? К примеру, для общего развития, или просто для интереса, а впоследствии, может быть, для того, чтобы убедиться, что F# — не просто язык для ознакомления.&lt;br/&gt;
 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://habrahabr.ru/post/116666/#habracut&quot;&gt;Читать дальше &amp;rarr;&lt;/a&gt;</description>
         <author>kernelmode</author>
         <guid isPermaLink="false">http://habrahabr.ru/post/116666/</guid>
         <pubDate>Fri, 01 Apr 2011 11:55:34 +0000</pubDate>
      </item>
      <item>
         <title>Вдогонку Visual Studio 2010 SP1, новые инструменты для разработчиков</title>
         <link>http://habrahabr.ru/post/115901/</link>
         <description>&lt;br/&gt;&lt;img title=&quot;image&quot; alt=&quot;image&quot; src=&quot;http://microgeek.ru/upload/blog/visualstudio/3f5/3f5f58ea5964418976f3438efd6e7f63.png&quot;/&gt;&lt;br/&gt;
&lt;br/&gt;
Как вы, наверняка, знаете недавно &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://habrahabr.ru/blogs/vs/115109/&quot;&gt;был выпущен&lt;/a&gt; пакет обновления для Visual Studio 2010. Спустя некоторое время стали появляться дополнительные инструменты, про которые стоит рассказать отдельно.&lt;br/&gt;
&lt;br/&gt;
Итак, во-первых, Скотт Гатри &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://weblogs.asp.net/scottgu/archive/2011/03/15/visual-studio-2010-sp1.aspx&quot;&gt;анонсировал у себя в блоге&lt;/a&gt; доступность новой возможности быстрой подготовки рабочего стола веб-разработчика. Были выпущены два пакета инструментов &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.microsoft.com/web/gallery/install.aspx?appsxml=&amp;amp;amp;appid=VS2010SP1Pack&quot;&gt;VS 2010 SP1 WebPI Bundle&lt;/a&gt; и &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.microsoft.com/web/gallery/install.aspx?appsxml=&amp;amp;amp;appid=VWD&quot;&gt;Visual Web Developer 2010 SP1 WebPI Bundle&lt;/a&gt; доступных для автоматической установки через Web Platform Installer. Эти пакеты состоят из следующих компонентов: среда разработки VS 2010 или VWD 2010 SP1, ASP.NET MVC 3 (+ инструменты), IIS 7.5 Express, SQL Server Compact Edition 4.0 (+ инструменты) и Web Deployment 2.0. С помощью Web Platform Installer данные компоненты автоматически загружаются и устанавливаются так, что вы можете получить настроенное рабочее место веб-разработчика за несколько минут.&lt;br/&gt;
&lt;br/&gt;
Во-вторых, &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://blogs.msdn.com/b/adonet/archive/2011/03/15/ef-4-1-release-candidate-available.aspx?wa=wsignin1.0&quot;&gt;выпущена новая версия&lt;/a&gt; Entity Framework под индексом 4.1, которая является важным обновлением ORM с момента выпуска. Пока &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.microsoft.com/downloads/en/details.aspx?FamilyID=2dc5ddac-5a96-48b2-878d-b9f49d87569a&quot;&gt;доступна&lt;/a&gt; версия релиз-кандидата, но уже вскоре будет выпущена финальная версия. Entity Framework 4.1 предложит разработчикам &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://microgeek.ru/blogs/dotnet/tags/?entity+framework+4.0&quot;&gt;все те нововведения&lt;/a&gt;, которые были представлены в проекте Code First. По поводу выхода EF 4.1 были подготовлены &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://thedatafarm.com/blog/data-access/new-ef4-amp-ef4-1-content-on-msdn/&quot;&gt;специальные материалы&lt;/a&gt; для обучения на сайте MSDN.&lt;br/&gt;
&lt;br/&gt;
В-третьих, для загрузки доступен &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.microsoft.com/downloads/en/details.aspx?FamilyID=99393a68-affc-43bc-88b7-3d672d5fbc22&quot;&gt;пакет локализации&lt;/a&gt; для Visual Studio 2010 F#. Этот пакет позволяет локализовать сообщения об ошибках и некоторые другие текстовые данные интегрированных инструментов языка F# на различные языки. Такой же пакет выпущен для &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.microsoft.com/downloads/en/details.aspx?FamilyID=cc14eff2-d47b-43a5-a139-fbb01e5f2836&quot;&gt;компонентов Report Viewer 2010&lt;/a&gt;.&lt;br/&gt;
&lt;br/&gt;
В-четвертых, (&lt;strong&gt;и это самое интересное&lt;/strong&gt;) доступна новая мартовская версия комплексного пакета обучения &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.microsoft.com/downloads/en/details.aspx?FamilyID=752cb725-969b-4732-a383-ed5740f02e93&quot;&gt;Visual Studio 2010 and .NET Framework 4 Training Kit&lt;/a&gt;. С помощью этого пакета вы можете изучить весь комплекс технологий входящих .NET и Visual Studio 2010. Вот лишь некоторые примеры рассматриваемых технологий: C#, F#, WCF, ASP.NET, Silverlight, MEF и другие. В комплекте пакета обучения находится &lt;strong&gt;50&lt;/strong&gt; лабораторных работ, &lt;strong&gt;22&lt;/strong&gt; демонстрационных проектов, &lt;strong&gt;16&lt;/strong&gt; презентаций и &lt;strong&gt;12&lt;/strong&gt; видео. &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://blogs.msdn.com/b/zainnab/archive/2011/03/16/visual-studio-2010-and-net-framework-4-training-kit-march-2011-update.aspx&quot;&gt;Основное отличие&lt;/a&gt; мартовской версии – это новые лабораторные для изучения Silverilght 4 и новые материалы для Windows Azure. &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://habrahabr.ru/post/115901/#habracut&quot;&gt;&lt;/a&gt;</description>
         <author>XaocCPS</author>
         <guid isPermaLink="false">http://habrahabr.ru/post/115901/</guid>
         <pubDate>Mon, 21 Mar 2011 14:43:44 +0000</pubDate>
      </item>
      <item>
         <title>F#: Во что превращается ваш код после компиляции</title>
         <link>http://habrahabr.ru/post/115727/</link>
         <description>&lt;br/&gt;Язык F# появился в стандартной поставке VisualStudio совсем недавно, а именно с версии 2010 (на данный момент самой что ни на есть актуальной). Естественно, и все это прекрасно знают, язык функционирует на основе CLR — весь ваш код будет скомпилирован в MS IL как и любой другой язык .NET семейства.&lt;br/&gt;
&lt;br/&gt;
Давайте на примере часто используемой и полезной техники «меморизация» посмотрим во что превращает ваш код компилятор. Для наглядности я буду писать сам код на F# и декомпилировать его в C#.&lt;br/&gt;
 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://habrahabr.ru/post/115727/#habracut&quot;&gt;Читать дальше &amp;rarr;&lt;/a&gt;</description>
         <author>Lattyf</author>
         <guid isPermaLink="false">http://habrahabr.ru/post/115727/</guid>
         <pubDate>Fri, 18 Mar 2011 08:03:44 +0000</pubDate>
      </item>
      <item>
         <title>Маниловщина</title>
         <link>http://dsorokin.blogspot.com/2011/03/blog-post.html</link>
         <description>&lt;div dir=&quot;ltr&quot; style=&quot;text-align:left;&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family:Georgia, 'Times New Roman', serif;&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family:Georgia, 'Times New Roman', serif;&quot;&gt;Иногда очень хочется, чтобы F# был отделен от .NET. Чтобы программы на нем работали под юниксами и виндой без использования тяжелой виртуальной машины. Или, как минимум, все его новшества были портированы в окамл. Уж больно F# хорош!&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family:Georgia, 'Times New Roman', serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family:Georgia, 'Times New Roman', serif;&quot;&gt;Однако реализация F# иногда хромает. Например, в нем есть такие костыли как OptimizedClosures.FSharpFunc и FSharpFunc.InvokeFast. На деле это означает, что при вызове функции со многими аргументами задействуется RTTI, чтобы узнать, а есть ли прямой вызов функции, минуя каррирование. Во многом потому, что это снизу .NET. Подозреваю, что в окамле такой вызов функции сильно оптимизирован, и он не использует RTTI.&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;</description>
         <author>dsorokin</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-8641042312683198534.post-3767030852928981083</guid>
         <pubDate>Fri, 04 Mar 2011 10:58:00 +0000</pubDate>
      </item>
      <item>
         <title>Парсим HTML Zen на F#, FsLex и FsYacc</title>
         <link>https://nesteruk.wordpress.com/2011/03/03/parsing-htmlzen-fsharp-fslex-fsyacc/</link>
         <description>Все наверное так или иначе слышали про HTML Zen и про то, как он спасает при написании HTML. Но мало кому приходит в голову написать свою собственную реализацию, когда есть готовая на Python&amp;#8217;е. На самом деле, собственная реализация позволяет добавлять собственные конструкты, нужные только вам. Давайте попробуем реализовать базовые конструкты HTML Zen. Для этого мы [&amp;#8230;]&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;https://pixel.wp.com/b.gif?host=nesteruk.wordpress.com&amp;#038;blog=373435&amp;#038;post=733&amp;#038;subd=nesteruk&amp;#038;ref=&amp;#038;feed=1&quot; width=&quot;1&quot; height=&quot;1&quot;/&gt;</description>
         <guid isPermaLink="false">http://nesteruk.wordpress.com/?p=733</guid>
         <pubDate>Thu, 03 Mar 2011 12:22:51 +0000</pubDate>
         <content:encoded><![CDATA[<p>Все наверное так или иначе слышали про HTML Zen и про то, как он спасает при написании HTML. Но мало кому приходит в голову написать свою собственную реализацию, когда есть готовая на Python&rsquo;е. На самом деле, собственная реализация позволяет добавлять собственные конструкты, нужные только вам.</p>
<p>Давайте попробуем реализовать базовые конструкты HTML Zen. Для этого мы воспользуемся языком F#, библиотекой тестирования <a rel="nofollow" target="_blank" href="http://fsunit.codeplex.com/" title="http://fsunit.codeplex.com/">FSunit</a>. Будем писать программу в стиле TDD. Я пожалуй назову ее FSharpZen, так интересней.</p>
<p>Исходный код можно найти тут: <a rel="nofollow" target="_blank" href="https://bitbucket.org/nesteruk/fsharpzen">https://bitbucket.org/nesteruk/fsharpzen</a></p>
<h3>Базовые случаи</h3>
<p>Весь HTML Zen &ndash; это набор трансформаций. Например, на входе <code>a</code>, а на выходе <code>&lt;a href="|"&gt;&lt;/a&gt;</code>, где <code>|</code> обозначает финальное положение каретки. Следовательно, можно как минимум написать следующий тест:</p>
<pre>
[&lt;TestFixture&gt;]
type ``Basic transformation tests`` ()=
  [&lt;Test&gt;] member test.
    ``Empty input should yield empty output`` () =
      Zen.html &quot;&quot; |&gt; should equal &quot;|&quot;
</pre>
<p>Это счастье совсем не компилируется, поэтому нам придется как минимум предоставить хоть какую-то реализацию, например:</p>
<pre>
module FSharpZen.Zen
let html input = &quot;&quot;
</pre>
<p>В результате, конечно, получим &ldquo;красный&rdquo; тест:</p>
<pre>
Expected string length 1 but was 0. Strings differ at index 0.
Expected: &quot;|&quot;
But was:  &lt;string.Empty&gt;
-----------^
</pre>
<p>Ну а дальше мы &ldquo;жульничаем&rdquo; и наш тест проходит. Не забываем сказать спасибо Решарперу, который поддерживает F#-тесты out-of-the-box.</p>
<h3>Пустые тэги</h3>
<p>Дефолтное поведение HTML Zen такое, что при написании, скажем, буквы <code>z</code> разворачивается шаблон <code>&lt;z&gt;|&lt;/z&gt;</code>. С другой стороны, <code>hr</code> определенно превращается в <code>&lt;hr/&gt;|</code>, а <code>img</code> &ndash; в <code>&lt;img src="|"&gt;&lt;/img&gt;</code>.</p>
<pre>
[&lt;Test&gt;] member test.
  ``Simple entity should be in a closed tag`` () =
    Zen.html &quot;c&quot; |&gt; should equal &quot;&lt;c&gt;|&lt;/c&gt;&quot;
[&lt;Test&gt;] member test.
  ``Self-closing entity should yield a self-closing tag`` () =
    Zen.html &quot;br&quot; |&gt; should equal &quot;&lt;br/&gt;|&quot;
[&lt;Test&gt;] member test.
  ``Entity should have appropriate attributes generated and placeholder set accordingly`` () =
    Zen.html &quot;a&quot; |&gt; should equal &quot;&lt;a href=&#92;&quot;|&#92;&quot; title=&#92;&quot;&#92;&quot;&gt;&lt;/a&gt;&quot;
</pre>
<p>Теперь у нас есть 3 use-case&rsquo;а: просто тэги, тэги которые не нуждаются в закрывающем тэге, и тэги которые имеют сложную начинку. Второй и третий случай &ndash; специальные, поэтому мы можем попробовать их выделить&hellip;</p>
<pre>
let singularEntities = [&quot;hr&quot;; &quot;br&quot;; &quot;img&quot;]
let neededAttributes = [
                         &quot;a&quot;, [&quot;href&quot;, &quot;title&quot;];
                         &quot;img&quot;, [&quot;src&quot;, &quot;alt&quot;]
                       ]
</pre>
<p>TDD по наивности своей рекоммендует &ldquo;самое простое работающее решение&rdquo; которое в нашем случае выглядит примерно вот так:</p>
<pre>
let html input =
  if input |&gt; String.IsNullOrEmpty then &quot;|&quot;
  else
    let sb = StringBuilder()
    sb.Append (&quot;&lt;&quot; + input) |&gt; ignore
    for a in neededAttributes do
      match a with
      | i, attributes when i = input -&gt;
        let firstAtt = List.head attributes
        sb.Append(&quot; &quot; + firstAtt + &quot;=&#92;&quot;|&#92;&quot;&quot;) |&gt; ignore
        attributes |&gt; List.tail 
                   |&gt; List.iter (fun f -&gt; sb.Append(&quot; &quot; + f + &quot;=&#92;&quot;&#92;&quot;&quot;) |&gt; ignore)
      | _ -&gt; ()
    // see if this is a self-closing tag
    let isSelfClosing = List.exists (fun f -&gt; f = input) singularEntities
    let pipe = if sb.ToString().Contains(&quot;|&quot;) then &quot;&quot; else &quot;|&quot;
    sb.Append(if isSelfClosing then &quot;/&gt;&quot; + pipe else &quot;&gt;&quot; + pipe + &quot;&lt;/&quot; + input + &quot;&gt;&quot;) |&gt; ignore
    sb.ToString()
</pre>
<p>До элегантности тут как до Китая. Вывода напрашивается два:</p>
<ul>
<li>Нужны какие-то структуры для того чтобы отражать структуру тэгов, особенно когда будут вложенные, с аттрибутами, и т.д.</li>
<li>Нужно учиться лучше парсить строки. То, что мы делаем выше &ndash; &ldquo;не по паттернам&rdquo;.</li>
</ul>
<h3>FsLex и FsYacc</h3>
<p>Лучший способ парсить &ndash; это взять что-то уже готовое (хотя до меня это иногда туго доходит). Поэтому для парсинга наших магических строк мы возьмем <a rel="nofollow" target="_blank" href="http://fsharppowerpack.codeplex.com/" title="http://fsharppowerpack.codeplex.com/">F# Power Pack</a>, и скачаем через VS Extension Manager шаблон проекта под названием <a rel="nofollow" target="_blank" href="http://visualstudiogallery.msdn.microsoft.com/a075ff98-7e6f-47ce-a23c-838c1e488046/" title="http://visualstudiogallery.msdn.microsoft.com/a075ff98-7e6f-47ce-a23c-838c1e488046/">F# Parser Language Starter</a>. Это позволит нам получить пример, в котором есть три важных файла, а именно:</p>
<ul>
<li><code>Ast.fs</code> &mdash; определение синтактического дерева. В нашем случае оно достаточно простое.</li>
<li><code>Lexer.fsl</code> &mdash; определение &ldquo;лексем&rdquo;, т.е. различных кусков строки, которые формируют выражение HTML Zen.</li>
<li><code>Parser.fsy</code> &mdash; собственно парсер, который определяет то, как лексемы становятся чем-то осмысленным.</li>
</ul>
<p>В сгенерированном примере получается калькулятор<sup><a rel="nofollow" href="#Reference1" title="&#x00041a;&#x000441;&#x000442;&#x000430;&#x000442;&#x000438;, &#x00043f;&#x000440;&#x000438;&#x00043c;&#x000435;&#x000440; &#x00043a;&#x000440;&#x000438;&#x000432;&#x00043e;&#x000439; &ndash; &#x00043f;&#x00043e;&#x00043f;&#x000440;&#x00043e;&#x000431;&#x000443;&#x000439;&#x000442;&#x000435; &#x00043d;&#x000430;&#x00043f;&#x000440;&#x000438;&#x00043c;&#x000435;&#x000440; &#x000432;&#x000432;&#x000435;&#x000441;&#x000442;&#x000438; 2-2 &#x000438; &#x000443; &#x000432;&#x000430;&#x000441; &#x00043f;&#x000430;&#x000440;&#x000441;&#x000435;&#x000440; &#x00043c;&#x00043e;&#x00043c;&#x000435;&#x00043d;&#x000442;&#x000430;&#x00043b;&#x00044c;&#x00043d;&#x00043e; &#x00043d;&#x000430;&#x00043a;&#x000440;&#x00043e;&#x000435;&#x000442;&#x000441;&#x00044f; &ndash; &#x000430; &#x000432;&#x000441;&#x000435; &#x000438;&#x000437;-&#x000437;&#x000430; &#x00043f;&#x00043e;&#x00043f;&#x00044b;&#x000442;&#x00043a;&#x000438; &#x000432;&#x000437;&#x00044f;&#x000442;&#x00044c; &#x00043c;&#x000438;&#x00043d;&#x000443;&#x000441; &#x00043f;&#x000435;&#x000440;&#x000435;&#x000434; 2&#x00043a;&#x00043e;&#x000439; &#x00043a;&#x000430;&#x00043a; &#x00043f;&#x000440;&#x000435;&#x000444;&#x000438;&#x00043a;&#x000441;-&#x00043e;&#x00043f;&#x000435;&#x000440;&#x000430;&#x000442;&#x00043e;&#x000440;. :)" name="BackReference1">1</a></sup>, нам же остается только поменять его чтобы начали поддерживаться наши собственные структуры.</p>
<h3>AST</h3>
<p>Итак, для нашего магического синтаксиса нам нужно определить тот набор элементов дерева, который мы фактически готовы подерживать. Это включает в себя как минимум следующие конструкции<sup><a rel="nofollow" href="#Reference2" title="&#x000422;&#x000443;&#x000442; &#x00044f; &#x00043d;&#x000435;&#x00043c;&#x00043d;&#x00043e;&#x000433;&#x00043e; &#x00043e;&#x000442;&#x00043a;&#x00043b;&#x00043e;&#x00043d;&#x000438;&#x00043b;&#x000441;&#x00044f; &#x00043e;&#x000442; &ldquo;&#x00043a;&#x00043e;&#x000448;&#x000435;&#x000440;&#x00043d;&#x00043e;&#x000433;&#x00043e;&rdquo; HTML Zen &#x00043a;&#x00043e;&#x000442;&#x00043e;&#x000440;&#x00044b;&#x000439;, &#x00043d;&#x000430; &#x00043c;&#x00043e;&#x000439; &#x000432;&#x000437;&#x000433;&#x00043b;&#x00044f;&#x000434;, &#x000434;&#x00043e;&#x000441;&#x000442;&#x000430;&#x000442;&#x00043e;&#x000447;&#x00043d;&#x00043e; &#x000438;&#x000437;&#x000431;&#x00044b;&#x000442;&#x00043e;&#x000447;&#x000435;&#x00043d;. &#x000412; &#x000447;&#x000430;&#x000441;&#x000442;&#x00043d;&#x00043e;&#x000441;&#x000442;&#x000438;, &#x00044f; &#x000437;&#x000430;&#x00043c;&#x000435;&#x00043d;&#x000438;&#x00043b; &gt; &#x00043d;&#x000430; + &#x000430; &ldquo;&#x00043e;&#x000440;&#x000438;&#x000433;&#x000438;&#x00043d;&#x000430;&#x00043b;&#x00044c;&#x00043d;&#x00044b;&#x000439;&rdquo; + &#x00043f;&#x00043e;&#x00043f;&#x000440;&#x00043e;&#x000441;&#x000442;&#x000443; &#x00043f;&#x000440;&#x00043e;&#x000438;&#x000433;&#x00043d;&#x00043e;&#x000440;&#x000438;&#x000440;&#x00043e;&#x000432;&#x000430;&#x00043b;." name="BackReference2">2</a></sup>:</p>
<ul>
<li>Идентификаторы, такие как <code>div</code>, <code>href</code> и так далее. Они парсятся &ldquo;как есть&rdquo;.</li>
<li>Классы, т.е. при при написании <code>a.b</code> мы получаем <code>&lt;a href="|" class="b"&gt;&lt;/a&gt;</code>.</li>
<li>Идентификаторы, т.е. <code>a#b</code> ставовится <code>&lt;a id="b" href="|"&gt;&lt;/a&gt;</code>.</li>
<li>Множители, т.е. <code>hr*2</code> дает нам <code>&lt;hr/&gt;&lt;hr/&gt;</code>. Между тэгами, между прочим, фигурирует <code>&#92;n</code> &ndash; это вынужденная мера для таких ситуаций как <code>ol&gt;li*2</code>.</li>
<li>Вложенные тэги &ndash; например, <code>ol+li</code> становится <code>&lt;ol&gt;&lt;li&gt;|&lt;/li&gt;&lt;/ol&gt;</code>, с соответствующими переносами и отступами.</li>
</ul>
<p>Теперь попробуем перевисти все эти идеи на структуры F#. У меня получилось примерно следующее:</p>
<pre>
type ZenExpression =
  | ZenExpression of Expression list
and Expression =
  | Expression of Identifier * Qualifier list
and Identifier =
  | Identifier of string
and Qualifier =
  | ClassQualifier of string
  | IdentityQualifier of string
  | CardinalityQualifier of int
</pre>
<p>Строго говоря, то, что вы видите выше &ndash; уродство. С этим очень сложно работать. К тому же, нет никаких ограничений на количество идентификатов или показателей размерности (а ведь элемент может иметь только один квалификатор каждого типа). Ну да ладно, эту проблему мы разрулим позже.</p>
<h3>Лексер</h3>
<p>Лексер у нас будет простенький. Во-первых, нужно определить регулярные выражения для всех полезных конструктов:</p>
<pre>
let digit = ['0'-'9']
let letter = ['a'-'z'] | ['A'-'Z']
let letterOrDigit = letter | digit
let whitespace = [' ' '&#92;t' ]
let newline = ('&#92;n' | '&#92;r' '&#92;n')
</pre>
<p>Ну а теперь, нужно определить какие конструкты будут производится из регулярных выражений. Нам нужны:</p>
<ul>
<li>Строки (возможно с числами) для идентификаторов и квалификаторов.</li>
<li>Операторы для разделения квалификаторов (<code>.</code>, <code>#</code>, <code>+</code> и <code>*</code>)</li>
<li>Числа для квалификатора размерности</li>
</ul>
<p>Следовательно, получаем следующее определение:</p>
<pre>
rule tokenize = parse
| whitespace	   { tokenize lexbuf }
| newline        { tokenize lexbuf }
| letterOrDigit+ { STRING(lexeme lexbuf) }
| digit+         { INT32(Int32.Parse(lexeme lexbuf)) }
// Operators
| &quot;+&quot;            { PLUS }
| &quot;#&quot;            { HASH }
| &quot;*&quot;            { TIMES }
| &quot;.&quot;            { DOT }
// EOF
| eof   { EOF }
</pre>
<h3>Парсер</h3>
<p>Определив лексемы, нам нужно научиться парсить их и превращать их комбинации в элементы AST. Для этого пойдет следующее определение:</p>
<pre>
start: exprs { ZenExpression($1) }
exprs:
  | exp PLUS exprs EOF { Expression($1) :: $3 }
  | exp EOF { [Expression($1)] }
exp:
  | STRING quals { (Identifier($1), $2) }
  | STRING { (Identifier($1), []) }
quals:
  | qual quals { $1 :: $2 }
  | qual { [$1] }
qual:
  | DOT STRING  { ClassQualifier($2) }
  | HASH STRING { IdentityQualifier($2) }
  | TIMES INT32 { CardinalityQualifier($2) }
</pre>
<p>Помимо того, что списки чего бы то ни было создаются рекурсивно, тут нет ничего необычного.</p>
<h3>Принтер</h3>
<p>Ну а теперь самое сложное. Помните я сказал, что та структура в которую мы парсим &ndash; убогая и избыточная? Так вот, сейчас вы увидите насколько неудобно такую штуку печатать.</p>
<p>Во-первых, код забрасывается кучей вспомогательных функций для поиска квалификаторов определенного типа. Например:</p>
<pre>
let rec private getId qualifierList =
  match qualifierList with
  | IdentityQualifier(id) :: t -&gt; Some(id)
  | h :: t -&gt; getId t
  | [] -&gt; None
</pre>
<p>Потом, приходится (не знаю в какой уже раз) делать вменяемый билдер для кода:</p>
<pre>
type CodeBuilder() =
  let sb = StringBuilder()
  let mutable indent = 0;
  member this.GetIndent() =
    System.String.Empty.PadRight(indent * 2)
  member this.AppendWithIndent (text:string) = 
    sb.Append(this.GetIndent()).Append(text) |&gt; ignore
  member this.Append (text:string) = 
    sb.Append(text) |&gt; ignore
  member this.NewLine() = sb.AppendLine() |&gt; ignore
  member this.Indent() = indent &lt;- indent + 1
  member this.Unindent() = indent &lt;- indent - 1
  override this.ToString() = sb.ToString()
</pre>
<p>Потом нужен поистине гигантский кусок кода для того чтобы распарсить все кейсы &ndash; конструкция весьма громоздкая:</p>
<pre>
let rec private print expressions (builder:CodeBuilder) =
  match expressions with
  | h :: t -&gt;
    builder.AppendWithIndent &quot;&lt;&quot;
    match h with
    | Expression(name, qual) -&gt;
      builder.Append name
      // id it if has any
      match getId qual with
      | Some(id) -&gt; builder.Append(&quot; id=&#92;&quot;&quot; + id + &quot;&#92;&quot;&quot;)
      | _ -&gt; ()
      // needed attributes
      let needed = getNeededAttributes name
      needed |&gt; List.iter(fun n -&gt; builder.Append(&quot; &quot; + n + &quot;=&#92;&quot;|&#92;&quot;&quot;))
      // classes
      let classes = getClasses qual
      if classes &lt;&gt; List.empty then
        builder.Append(&quot; class=&#92;&quot;&quot;)
        builder.Append(System.String.Join(&quot; &quot;, classes))
        builder.Append(&quot;&#92;&quot;&quot;)
      // if self-closing, then close it
      let selfClosing = singularEntities |&gt; List.exists(fun f -&gt; f = name)
      if selfClosing then builder.Append &quot;/&gt;|&quot;
      else builder.Append &quot;&gt;&quot;
      // if there's more stuff in there, add it
      if t &lt;&gt; List.empty then
        builder.Indent()
        builder.NewLine()
        print t builder
        builder.NewLine()
        builder.Unindent()
        
      if not selfClosing then
        builder.Append(&quot;|&lt;/&quot; + name + &quot;&gt;&quot;)
  | _ -&gt; 
    builder.Append &quot;|&quot;
</pre>
<p>А вот собственно как все запускается:</p>
<pre>
let html input = 
  let lexbuf = LexBuffer&lt;char&gt;.FromString(input)
  let parsed = Parser.start Lexer.tokenize lexbuf
  let builder = new CodeBuilder()
  match parsed with
  | ZenExpression(items) -&gt; print items builder
  let pre = builder.ToString() |&gt; Seq.toList
  let rec clean input metBar =
    match input with
    | '|' :: t when not metBar -&gt; '|' :: clean t true
    | '|' :: t when metBar -&gt; clean t true
    | h :: t -&gt; h :: clean t metBar
    | [] -&gt; []
  let lst = clean pre false
  System.String(lst |&gt; List.toArray)
</pre>
<p>Излишние телодвижения у нас от того, что мы в принтере генерируем избыточное число кареток. Нужно удалить все кроме первой, а более элегантного способа я не знаю (хотя не исключаю что он существует).</p>
<h3>Заключение</h3>
<p>В очередной раз у меня сомнения. Количество телодвижений для того чтобы реализовать парсер примерно в 10 раз больше чем когда я все это писал &ldquo;в лоб&rdquo; на C#. FxLex и FsYacc обладают практически нулевой диагностичностью, никакого IntelliSense нет, такое впечатление что блуждаешь в потемках. Что касается принтера, опять же, структура на которую все было &ldquo;замэплено&rdquo; очень неудобна; намного быстрее было бы использовать ООП. Плюшки FP вроде паттерн-матчинга и прочего тут совсем не амортизировались.</p>
<h3>Заметки</h3>
<ol>
<li><a rel="nofollow" name="Reference1"></a><a rel="nofollow" href="#BackReference1" title="Back to text">&uarr;</a> Кстати, пример кривой &ndash; попробуйте например ввести <code>2-2</code> и у вас парсер моментально накроется &ndash; а все из-за попытки взять минус перед 2кой как префикс-оператор. :)</li>
<li><a rel="nofollow" name="Reference2"></a><a rel="nofollow" href="#BackReference2" title="Back to text">&uarr;</a> Тут я немного отклонился от &ldquo;кошерного&rdquo; HTML Zen который, на мой взгляд, достаточно избыточен. В частности, я заменил <code>&gt;</code> на <code>+</code> а &ldquo;оригинальный&rdquo; <code>+</code> попросту проигнорировал.</li>
</ol><br />Filed under: <a rel="nofollow" target="_blank" href='https://nesteruk.wordpress.com/category/net/'>.NET</a>, <a rel="nofollow" target="_blank" href='https://nesteruk.wordpress.com/category/net/f/'>f#</a> Tagged: <a rel="nofollow" target="_blank" href='https://nesteruk.wordpress.com/tag/fslex/'>fslex</a>, <a rel="nofollow" target="_blank" href='https://nesteruk.wordpress.com/tag/fsyacc/'>fsyacc</a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gocomments/nesteruk.wordpress.com/733/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/nesteruk.wordpress.com/733/"/></a> <img alt="" border="0" src="https://pixel.wp.com/b.gif?host=nesteruk.wordpress.com&#038;blog=373435&#038;post=733&#038;subd=nesteruk&#038;ref=&#038;feed=1" width="1" height="1"/>]]></content:encoded>
         <media:content medium="image" url="https://0.gravatar.com/avatar/f01cbd2238e2a78e4c43fa596f51d6a1?s=96&amp;amp;d=https%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&amp;amp;r=PG">
            <media:title type="html">nesteruk</media:title>
         </media:content>
      </item>
      <item>
         <title>[Перевод] Выпущено Mono 2.10 – F# в комплекте</title>
         <link>http://habrahabr.ru/post/114541/</link>
         <description>&lt;br/&gt;Выпущено Mono 2.10. Теперь Mono включает в себя F#, подробнее см. &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.mono-project.com/Release_Notes_Mono_2.10#Languages&quot;&gt;здесь&lt;/a&gt;.&lt;br/&gt;
&lt;br/&gt;
Основные изменения:&lt;br/&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.mono-project.com/Release_Notes_Mono_2.10#Google_Native_Client_Support&quot;&gt;Поддержка Google Native Client&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.mono-project.com/Release_Notes_Mono_2.10#New_Mono_Profiler&quot;&gt;Новый движок профайлера&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.mono-project.com/Release_Notes_Mono_2.10#Improved_Socket_and_Async_Stack&quot;&gt;Более быстрый стек сокетов&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Улучшенный Parallel Framework&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.mono-project.com/Release_Notes_Mono_2.10#SGen_Garbage_Collector&quot;&gt;Точное сканирование стека и множество улучшений производительности в SGen&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Унифицированая поддержка времени выполнения MonoTouch/Monodroid&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.mono-project.com/Release_Notes_Mono_2.10#Cecil.2FLight&quot;&gt;Cecil/Light&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.mono-project.com/Release_Notes_Mono_2.10#New_C.23_Compiler_Backend&quot;&gt;Новый бекенд компилятора C# Compiler (можно использовать собственную mscorlib)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.mono-project.com/Release_Notes_Mono_2.10#VB_Compiler&quot;&gt;Компилятор VB&lt;/a&gt; теперь может компилировать в оба профиля: 2.0 и 4.0.&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.mono-project.com/Release_Notes_Mono_2.10#ASP.NET_MVC3_Support&quot;&gt;Поддержка ASP.NET MVC3&lt;/a&gt;, Razor и новые WebPages.&lt;/li&gt;
&lt;li&gt;Новый API баз данных &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.mono-project.com/Release_Notes_Mono_2.10#WebMatrix.Data&quot;&gt;WebMatrix.Data&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.mono-project.com/Release_Notes_Mono_2.10#OSX_Updates&quot;&gt;Улучшения в Mono для OSX&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.mono-project.com/Release_Notes_Mono_2.10#Languages&quot;&gt;F# и IronRuby&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://habrahabr.ru/post/114541/#habracut&quot;&gt;&lt;/a&gt;</description>
         <author>ApeCoder</author>
         <guid isPermaLink="false">http://habrahabr.ru/post/114541/</guid>
         <pubDate>Sat, 26 Feb 2011 13:22:43 +0000</pubDate>
      </item>
      <item>
         <title>Try F#</title>
         <link>http://ru-fsharp.livejournal.com/3266.html</link>
         <description>&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://tryfsharporg.cloudapp.net/&quot;&gt;tryfsharp.org&lt;/a&gt; — это аналог &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://tryhaskell.org&quot;&gt;tryhaskell.org&lt;/a&gt;. «In just a few minutes you can begin learning F# — no registration, log-ins or forms are required.»&lt;br /&gt;&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://ctocorner.com/fsharp/book/default.aspx&quot;&gt;«The F# Survival Guide»&lt;/a&gt; — аналог &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://learnyouahaskell.com/&quot;&gt;«Learn You a Haskell for Great Good!»&lt;/a&gt;. «We wrote this book to introduce mainstream developers to the world of functional programming through the lens of F#, Microsoft's first fully-supported multi-paradigm language.»&lt;br /&gt;&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://fssnip.net&quot;&gt;fssnip.net&lt;/a&gt;. «This web site allows you to easily share F# source code snippets. It is similar to other &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Pastebin&quot;&gt;Pastebin&lt;/a&gt; services, but focuses only on F#. On the other hand, it uses the F# language service to provide colorization and also generates HTML tool tips that show results of background type checking. This makes the F# code significantly more readable.»&lt;br /&gt;&lt;br /&gt;(&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://habrahabr.ru/blogs/net/114017/&quot;&gt;Via&lt;/a&gt; Habrahabr.)</description>
         <author>Qbit</author>
         <guid isPermaLink="false">urn:lj:livejournal.com:atom1:ru_fsharp:3266</guid>
         <pubDate>Sat, 26 Feb 2011 11:54:45 +0000</pubDate>
      </item>
      <item>
         <title>Уравнения на F# проще чем на C#?</title>
         <link>https://nesteruk.wordpress.com/2011/02/05/are-fsharp-equations-easier-than-csharp/</link>
         <description>На недавней встрече, посвещенной языку F#, я показал как якобы «элегантно» можно описывать математические функции на F#. А сейчас сел и задумался &amp;#8211; так ли это на самом деле? Давайте разберемся. Квадратное уравнение Начнем с примера, приведенного мною на встрече &amp;#8211; решения квадратного уравнения. Казалось бы &amp;#8211; что может быть проще? Сразу можно сделать несколько [&amp;#8230;]&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;https://pixel.wp.com/b.gif?host=nesteruk.wordpress.com&amp;#038;blog=373435&amp;#038;post=718&amp;#038;subd=nesteruk&amp;#038;ref=&amp;#038;feed=1&quot; width=&quot;1&quot; height=&quot;1&quot;/&gt;</description>
         <guid isPermaLink="false">http://nesteruk.wordpress.com/?p=718</guid>
         <pubDate>Sat, 05 Feb 2011 07:52:32 +0000</pubDate>
         <content:encoded><![CDATA[<p>На <a rel="nofollow" target="_blank" href="http://spbalt.net/Home/Meetings/25" title="http://spbalt.net/Home/Meetings/25">недавней встрече</a>, посвещенной языку F#, я показал как якобы «элегантно» можно описывать математические функции на F#. А сейчас сел и задумался &ndash; так ли это на самом деле? Давайте разберемся.</p>
<h3>Квадратное уравнение</h3>
<p>Начнем с примера, приведенного мною на встрече &ndash; решения квадратного уравнения. Казалось бы &ndash; что может быть проще?</p>
<p align="center"><img src="https://i0.wp.com/nesteruk.org/pix/0/4d155c02-150c-48b9-a862-c6ac1cfb5d6b.png" alt="" style="border:0;" align="center" class="aligncenter"/></p>
<p>Сразу можно сделать несколько сравнений C# и F# для этого примера:</p>
<ul>
<li>Возвращаются 2 значения, а следовательно F# выигрывает за счет того что не надо писать <code>Tuple.Create</code>, а тому кто эти значения получит не надо использовать абсолютно ничего не значащие свойства <code>Item1</code> и <code>Item2</code></li>
<li>Математические binding&rsquo;и у F# намного «ближе» чем у C#, а следовательно в этом случае (да и в общем), ваш код на F# не будет испачкан явным вызовом статических функций вроде <code>Math.Sqrt</code>. Меня всегда это бесило в C# т.к. сложные вычисления становится еще сложнее читать.</li>
<li>Ни C# ни F# не умеют работать с оператором ±. Но если в C# нам придется тупо вызывать вычисления дважды, в F# мы можем просто определить функцию конечного вычисления, а потом передать в нее операторы <code>(+)</code> и <code>(-)</code>.</li>
</ul>
<p>В результате получим следующее сравнение:</p>
<p>
  <strong>C#</strong>
</p>
<pre>
public Tuple&lt;double,double&gt; SolveQuadraticEquation(double a, double b, double c)
{
  double discRoot = Math.Sqrt(b*b-4.0*a*c);
  double x1 = (-b + discRoot) / (2 * a);
  double x2 = (-b - discRoot) / (2 * a);
  return Tuple.Create(x1, x2);
}
</pre>
<p>
  <strong>F#</strong>
</p>
<pre>
let solveQuadratic a b c =
  let disc = b * b - 4.0 * a *c
  let calc op = (op (-b) (sqrt disc)) / (2.0*a)
  (calc (+), calc(-))
</pre>
<p>Пока что разница небольшая &ndash; в одну строчку, если не считать фигурных скобок. А спорим я могу сократить эту разницу практически до нуля? Вот, пожалуйста:</p>
<p>
  <strong>C#</strong>
</p>
<pre>
public Tuple&lt;double, double&gt; SolveQuadraticEquation(double a, double b, double c)
{
  double q = -0.5 * (b + Math.Sign(b) * Math.Sqrt(b * b - 4 * a * c));
  return Tuple.Create(q / a, c / q);
}
</pre>
<p>
  <strong>F#</strong>
</p>
<pre>
let solveQuadraticEquation a b c =
  let q = -0.5 * (b + (sign b |&gt; float) * sqrt(b * b - 4.0 * a * c))
  (q / a, c / q) //           ^^^^^^^^ WTF?!?
</pre>
<p>Пример на F# должен вызвать у вас возмущение &ndash; с какой это радости результат <code>(sign b)</code> должен быть приведен к типу <code>float</code>?<sup><a rel="nofollow" href="#Reference1" title="&#x00041d;&#x000430;&#x00043f;&#x00043e;&#x00043c;&#x000438;&#x00043d;&#x000430;&#x00044e;, &#x000447;&#x000442;&#x00043e; float &#x000432; F# &ndash; &#x00044d;&#x000442;&#x00043e; double &#x000432; C#. &#x000410; C#-&#x00043d;&#x00044b;&#x000439; float &#x000432; F# &#x00043d;&#x000430;&#x000437;&#x00044b;&#x000432;&#x000430;&#x000435;&#x000442;&#x000441;&#x00044f; float32." name="BackReference1">1</a></sup> А дело все в непродуманности API, согласно которому <code>sign(x)</code> &ndash; это всегда <code>int</code> (могли бы сделать тем же типом что и аргумент), а также крайне жесткой системе типов в которой <code>float + int * float</code> не воспринимается и никак не вычисляется.</p>
<p>Такое странное поведение F# унаследовано из OCaml и требуется для правильного вывода типов. Если вам действительно интересны причины &ndash; можно <a rel="nofollow" target="_blank" href="http://cs.hubfs.net/forums/thread/3391.aspx" title="http://cs.hubfs.net/forums/thread/3391.aspx">почитать тут</a>. Мне же это лишь палки в колеса. Да, и я знаю что можно было бы написать <code>sign(float b)</code> или что-то в этом роде. Тут как бы без разницы, все равно «не очень».</p>
<h3>Комплексные решения</h3>
<p>Ну да ладно, а вот вопрос &ndash; что будет если дискриминанта (&Delta;) меньше нуля? С одной стороны, и C# и F# поддерживает комплексные типы данных (см. System.Numerics). Если сделать вид что мы все будем передавать как комплексные числа (так проще?), то получим вот такой вот код:</p>
<p>
  <strong>C#</strong>
</p>
<pre>
public Tuple&lt;Complex, Complex&gt; SolveQuadraticEquation3(double a, double b, double c)
{
  double det = b * b - 4 * a * c;
  double absRoot = Math.Sqrt(Math.Abs(det));
  Complex root = det &lt; 0 ? new Complex(0, absRoot) : new Complex(absRoot, 0);
  Complex q = -0.5 * (b + Math.Sign(b) * root);
  return Tuple.Create(q / a, c / q);
}
</pre>
<p><strong>F#</strong></p>
<pre>
let solveQuadratic3 a b c =
  let complex v = Complex(v, 0.0)
  let det = b * b - 4.0 * a * c
  let absRoot = sqrt(det |&gt; abs)
  let root = if det &lt; 0.0 then Complex(0.0, absRoot)
                          else Complex(absRoot, 0.0)
  let q = -(complex 0.5) * ((complex b) + (sign b |&gt; float |&gt; complex) * root)
  (q / complex(a), complex(c) / q)
</pre>
<p>Эээ, ну что я могу сказать? F# определенно превносит массу головной боли. Проблема тут как раз в том, что в C# нам доступны операторы автоконверсии вроде <code>float</code>&rarr;<code>Complex</code>, но в F# они попросту не работают! Поэтому вы можете либо определить их как функции (благо у них есть имя <code>op_Implicit</code>), либо же просто вызвать конструктор как делаю я.<sup><a rel="nofollow" href="#Reference2" title="&#x000422;&#x000443;&#x000442; &#x000435;&#x000449;&#x000435; &#x000445;&#x00043e;&#x000447;&#x000435;&#x000442;&#x000441;&#x00044f; &#x000437;&#x000430;&#x00043c;&#x000435;&#x000442;&#x000438;&#x000442;&#x00044c; &#x000447;&#x000442;&#x00043e; if &#x00043a;&#x00043e;&#x000442;&#x00043e;&#x000440;&#x00044b;&#x000439; &#x000432;&#x00044b;&#x000431;&#x000438;&#x000440;&#x000430;&#x000435;&#x000442; &#x00043a;&#x000430;&#x00043a;&#x00043e;&#x000439; Complex &#x000441;&#x00043e;&#x000437;&#x000434;&#x000430;&#x000432;&#x000430;&#x000442;&#x00044c; &#x00043a;&#x000430;&#x00043a; &#x000431;&#x00044b; &#x00043d;&#x000435; &#x00043d;&#x000443;&#x000436;&#x00043d;&#x00043e; &mdash; &#x00043c;&#x00043e;&#x000436;&#x00043d;&#x00043e; &#x000431;&#x00044b;&#x00043b;&#x00043e; &#x000432;&#x00043c;&#x000435;&#x000441;&#x000442;&#x00043e; &#x00044d;&#x000442;&#x00043e;&#x000433;&#x00043e; &#x00043d;&#x000430;&#x00043f;&#x000438;&#x000441;&#x000430;&#x000442;&#x00044c; Complex.Sqrt(new Complex(b*b-4*a*c, 0.0)). &#x00041f;&#x000440;&#x00043e;&#x000431;&#x00043b;&#x000435;&#x00043c;&#x000430; &#x000442;&#x00043e;&#x00043b;&#x00044c;&#x00043a;&#x00043e; &#x000432; &#x000442;&#x00043e;&#x00043c; &#x000447;&#x000442;&#x00043e; &#x000432; &#x000440;&#x000435;&#x000437;&#x000443;&#x00043b;&#x00044c;&#x000442;&#x000430;&#x000442;&#x000435; &#x00044d;&#x000442;&#x00043e;&#x000433;&#x00043e; &#x000432;&#x00044b;&#x000447;&#x000438;&#x000441;&#x00043b;&#x000435;&#x00043d;&#x000438;&#x00044f; Real-&#x000437;&#x00043d;&#x000430;&#x000447;&#x000435;&#x00043d;&#x000438;&#x000435; &#x000431;&#x000443;&#x000434;&#x000435;&#x000442; &#x000447;&#x000443;&#x000442;&#x00043e;&#x000447;&#x00043a;&#x000443; &#x00043e;&#x000442;&#x00043b;&#x000438;&#x000447;&#x000430;&#x000442;&#x00044c;&#x000441;&#x00044f; &#x00043e;&#x000442; &#x00043d;&#x000443;&#x00043b;&#x00044f;. &#x00041d;&#x000430;&#x00043f;&#x000440;&#x000438;&#x00043c;&#x000435;&#x000440; sqrt(Complex(-4.0, 0.0)) &#x000440;&#x000430;&#x000432;&#x000435;&#x00043d; (1.22460635382238E-16, 2)." name="BackReference2">2</a></sup></p>
<h3>Заключение</h3>
<p>То ли я чего-то недопонимаю, то ли F# действительно неудобен для работы с математикой? Ведь если нужно каждый <code>int</code> кастовать во <code>float</code>, а каждый <code>float</code> в <code>Complex</code>, и так далее, то это же сколько лишнего, никому не нужного и мешающего восприятию кода надо написать?</p>
<p>Критика welcome! А то может я что не так написал?</p>
<h3>Заметки</h3>
<ol>
<li><a rel="nofollow" name="Reference1"></a><a rel="nofollow" href="#BackReference1" title="Back to text">&uarr;</a> Напоминаю, что <code>float</code> в F# &ndash; это <code>double</code> в C#. А C#-ный <code>float</code> в F# называется <code>float32</code>.</li>
<li><a rel="nofollow" name="Reference2"></a><a rel="nofollow" href="#BackReference2" title="Back to text">&uarr;</a> Тут еще хочется заметить что <code>if</code> который выбирает какой <code>Complex</code> создавать как бы не нужно &mdash; можно было вместо этого написать <code>Complex.Sqrt(new Complex(b*b-4*a*c, 0.0))</code>. Проблема только в том что в результате этого вычисления Real-значение будет <em><font face="Trebuchet MS">чуточку</font></em> отличаться от нуля. Например <code>sqrt(Complex(-4.0, 0.0))</code> равен <code>(1.22460635382238E-16, 2)</code>.</li>
</ol><br />Filed under: <a rel="nofollow" target="_blank" href='https://nesteruk.wordpress.com/category/net/'>.NET</a>, <a rel="nofollow" target="_blank" href='https://nesteruk.wordpress.com/category/c/'>C#</a>, <a rel="nofollow" target="_blank" href='https://nesteruk.wordpress.com/category/net/f/'>f#</a>  <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gocomments/nesteruk.wordpress.com/718/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/nesteruk.wordpress.com/718/"/></a> <img alt="" border="0" src="https://pixel.wp.com/b.gif?host=nesteruk.wordpress.com&#038;blog=373435&#038;post=718&#038;subd=nesteruk&#038;ref=&#038;feed=1" width="1" height="1"/>]]></content:encoded>
         <media:content medium="image" url="https://0.gravatar.com/avatar/f01cbd2238e2a78e4c43fa596f51d6a1?s=96&amp;amp;d=https%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&amp;amp;r=PG">
            <media:title type="html">nesteruk</media:title>
         </media:content>
         <media:content medium="image" url="http://nesteruk.org/pix/0/4d155c02-150c-48b9-a862-c6ac1cfb5d6b.png"/>
      </item>
      <item>
         <title>Коротко про WebSharper и сайтлеты</title>
         <link>https://nesteruk.wordpress.com/2011/01/19/on-websharper-and-sitelets/</link>
         <description>Этот пост &amp;#8211; про WebSharper в целом и про сайтлеты в частности. Как я уже писал, WebSharper &amp;#8211; это идея создания сайтов полностью на языке F#. У этой идеи есть несколько модельных реализаций, а точнее три &amp;#8211; через Asp.Net, Asp.Net MVC и так называемые сайтлеты &amp;#8220;sitelets&amp;#8221;. Концепция Меня во всей этой концепции интересуют именно сайтлеты. [&amp;#8230;]&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;https://pixel.wp.com/b.gif?host=nesteruk.wordpress.com&amp;#038;blog=373435&amp;#038;post=704&amp;#038;subd=nesteruk&amp;#038;ref=&amp;#038;feed=1&quot; width=&quot;1&quot; height=&quot;1&quot;/&gt;</description>
         <guid isPermaLink="false">http://nesteruk.wordpress.com/?p=704</guid>
         <pubDate>Wed, 19 Jan 2011 20:53:19 +0000</pubDate>
         <content:encoded><![CDATA[<p><img src="https://i2.wp.com/nesteruk.org/pix/0/1ac970e1-40cf-4dc7-ac88-adc39a02a8e5.png" class="alignright" alt="" style="border:0;"/>Этот пост &ndash; про <a rel="nofollow" target="_blank" href="http://websharper.com" title="http://websharper.com">WebSharper</a> в целом и про сайтлеты в частности. Как я уже писал, WebSharper &ndash; это идея создания сайтов полностью на языке F#. У этой идеи есть несколько модельных реализаций, а точнее три &ndash; через Asp.Net, Asp.Net MVC и так называемые сайтлеты &ldquo;sitelets&rdquo;.</p>
<h3>Концепция</h3>
<p>Меня во всей этой концепции интересуют именно сайтлеты. В отличии от использования Asp.Net-конструктов (пусть и на F#), сайтлеты &ndash; наиболее &ldquo;трушная&rdquo; концепция, в которой сгенерированный код будет <strong>полностью отвязан</strong> от Asp.Net и, впоследствии, от IIS.</p>
<p>Теперь о том <em><font face="Trebuchet MS">как</font></em> это делается. На самом деле, основной концепцией является конверсия F# в JavaScript/CSS/HTML на этапе компиляции. Делается это за счет аттрибута под названием <code>ReflectedDefinitionAttribute</code> который, имея alias под названием <code>JavaScriptAttribute</code>, используется перед методами, которые нужно сконвертировать в JavaScript.</p>
<p>Что этот аттрибут делает? Он заставляет компилятор F# сохранить логические конструкты метода вместо того чтобы просто его компилировать. А тут включается постпроцессинг WebSharper&rsquo;а, который берет это &ldquo;отраженное определение&rdquo; и, на его основе, формирует некий промежуточный слой JavaScript. Промежуточный слой нужен потому, что мэпить F# на JavaScript не так-то просто.</p>
<p>Простой код который вы напишете вот так</p>
<pre>
[&lt;JavaScript&gt;]
let rec Fact n =
  match n with
  | n when n &lt; 2 -&gt; 1
  | n -&gt; n * Fact1 (n - 1)
</pre>
<p>может быть в последствии вызван со страницы напрямую &ndash; ведь все остальное, что есть на странице тоже определено через F#, конвертированный в JS и HTML.</p>
<h3>Вызовы серверных методов</h3>
<p>Мне очень понравилось что механизм вызова методов очень прозрачный. Метод помеченный как <code>[&lt;JavaScript&gt;]</code> вызывается как JS прямо у клиента, в то время как метод помеченный как <code>[&lt;Rpc&gt;]</code> хостится на сервере (как это будет сделано в полноценных сайтлетах &ndash; непонятно), и соответственно его вызов со страницы дергает сервер.</p>
<p>На данный момент механизм поведения Rpc-методов такой: если метод возвращает какое-то значение, то вызов является блокирующим. Если метод возвращает <code>unit</code> &ndash; его вызов считается асинхронным и тем самым, если вы повесили на него брейкпоинт (да, это можно делать), вы можете остановиться в нем не тогда, когда ожидаете.</p>
<h3>Формирование контента</h3>
<p>ВебШарпер не отказывается от идеи шаблонов! По крайней мере сайтлеты на текущем этапе предоставляют возможность писать шаблоны в HTML, который потом компилируется&hellip; в F#! Что намного более извращенно чем то, что делает Asp.Net MVC, например. Но мы сейчас не об этом.</p>
<p>Дело в том, что сам по себе WebSharper предоставляет возможность формировать HTML путем использования HTML-подобных конструктов в F#. Механизм, с помощью которого организовано создание HTML весьма забавно. В модуле <code>IntelliFactory.Html.Tags</code> есть определения для большого количества тэгов, например <code>H1</code>. Каждый тэг &ndash; это функция, которая сама по себе берет список, состоящий из нескольких &ldquo;нодов&rdquo;, которые могут формировать как аттрибуты данного тэга, так и его начинку. Например, чтобы сделать заголовок с текстом, мы пишем следующее:</p>
<pre>
H1 [Text &quot;Title&quot;]
</pre>
<p>В примере выше, метод <code>Text</code> определяет, что его аргумент &ndash; это действительно текст. Вместо него, мы бы могли например использовать <code>Attr</code> чтобы указать что это аттрибут.</p>
<p>Теперь насчет композиции. Композиция &ndash; это <em><font face="Trebuchet MS">центральная</font></em> особенность ВебШарпера, которая очень хорошо выделяет его по сравнению с тем же Asp.Net MVC. В данном случае, для вкладывания HTML-элементов друг в друга, мы можем использовать оператор <code>-&lt;</code>. Например:</p>
<pre>
Div [Attr.Style &quot;padding: 5px;&quot;] -&lt; [
  P [Text &quot;Hello&quot;]
]
</pre>
<h3>События</h3>
<p>Обработка событий в F# делается путем еще одного полезного оператора <code>|&gt;!</code>. Этот оператор делает подписку на событие, и одновременно возвращает созданный элемент, что обязательно в условиях механики работы WebSharper. Вот небольшой пример:</p>
<pre>
let update () =
  // обработка события
 
let input = Input [Attr.Type &quot;Text&quot;]
Form [
  label &quot;First Name: &quot;
  input |&gt;! OnKeyUp (fun _ _ -&gt; update ())
]
</pre>
<p>Опять же, интересно тут то, что не важно, где располагается метод <code>update()</code> &ndash; на сервере или на клиенте.</p>
<h3>Это вам не MVC!</h3>
<p>Сейчас устраивать гонения на MVC <a rel="nofollow" target="_blank" href="http://www.gotdotnet.ru/blogs/sanchez911/9266/" title="http://www.gotdotnet.ru/blogs/sanchez911/9266/">модно</a>, многие уходят на Rails (в т.ч. всем известный <a rel="nofollow" target="_blank" href="http://www.osherove.com/blog/2011/1/2/the-journey-begins-and-why-it-starts-with-ruby.html" title="http://www.osherove.com/blog/2011/1/2/the-journey-begins-and-why-it-starts-with-ruby.html">Рой Ошеров</a>), поэтому я решил тоже подлить масла в огонь хотя, по-хорошему, ВебШарпер является частью Asp.Net инфраструктуры. Но это пока сайтлеты полностью не дописаны. Так вот, понятное дело, что в функциональной парадигме, создание сайтов выглядит несколько по-другому.</p>
<p>Для начала, давайте познакомимся с концепцией &ldquo;формлетов&rdquo;. <a rel="nofollow" target="_blank" href="http://bugsquash.blogspot.com/2011/01/simple-implementation-of-formlets-in-f.html">Формлет</a> &ndash; это возможность описания того, какие данные нужно получать в форме и как пройдет валидация. Например:</p>
<pre>
[&lt;JavaScript&gt;]
let BasicInfoForm () : Formlet&lt;BasicInfo&gt; =
  Formlet.Yield (fun name age -&gt; { Name = name; Age = age })
  &lt;*&gt; Input &quot;Name&quot; &quot;Please enter your name&quot;
  &lt;*&gt; InputInt &quot;Age&quot; &quot;Please enter a valid age&quot;
</pre>
<p>Формлеты можно &ldquo;обрамлять&rdquo; (типичный паттерн Декоратор) в различные другие конструкты, функционально добавляя им кнопки Submit/Reset, настройки, и так далее. Формлеты можно инстанциировать у себя в коде, причем с ними можно делать вещи, которые в том же MVC делать очень сложно. Например, допустим у вас сайт где можно разместить резюме, и вы хотите чтобы человек мог внести данные о всех местах где он работал. Для этого, вы делаете формлет, который инкапсулирует все данные о работе (где, когда, итп.) а потом одной строчкой кода говорите &ldquo;их может быть несколько&rdquo;. И все! Композиционная структура сделает все сама за себя.</p>
<p>Так вот, о чем мы? После того как мы сделали несколько формлетов, их можно выстроить в цепочку, так что нажав Submit на одном, мы перейдем к другому. Эта &ldquo;концепция&rdquo; именуется flowlet&rsquo;ом (или flowlet&rsquo;ами). Выражается это следующим образом.</p>
<p>Во-первых, есть некий workflow под названием <code>Flowlet.Do</code> этот вокрфлоу умеет показывать формы в тот момент, когда они учавствуют по правую сторону <code>let!</code>, и сохранять их возвращенные значения (да-да, форма это функция, а ее return value &ndash; это то, что пользователь ввел). После этого, путем <code>return!</code> происходит &ldquo;типа возврат&rdquo; из этой цепочки, то есть мы можем, например, предоставить фунцию, которая получит результаты formlet&rsquo;ов и выведет из них полезные значения на экран.</p>
<p>На самом деле, механика всего этого чуть-чуть сложнее. Во-первых, конечным результатом выражения <code>Formlet.Do</code> все равно должен быть <code>Formlet</code>, то есть создав элемент, вам придется его конвертировать. Но это не сложно! А во-вторых, весь этот computational expression должен быть передан в функцию <code>Formlet.Flowlet</code> для того чтобы оркестровать такое феерическое действие.</p>
<pre>
Formlet.Do {
  let! w = welcomeForm
  let! c = consentForm
  return! Formlet.OfElement (proc w c)
}
|&gt; Formlet.Flowlet
</pre>
<h3>Представление</h3>
<p>На данный момент презентация сего фееричного действия организована в терминах Asp.Net&rsquo;ного <code>WebControl</code>, от которого наследует ВебШарперный контрол, давая нам возможность засунуть в него целиком наш pagelet. Pagelet &ndash; это еще одна абстракция в стиле &ldquo;нечто что может фигурировать на странице&rdquo;. Логика мне не ясна, но на данный момент pagelet&rsquo;ом являются текст, <code>Element</code> (это просто элемено HTML) или <code>Flowlet</code>.</p>
<p>Понятное дело, что формирование отдельного <code>WebControl</code>-а не означает создание странички целиком. И вот тут начинаются странности.</p>
<p>Дело в том, что для сайтлетов у нас генерируются 3 проекта, а именно:</p>
<ul>
<li>Проект Asp.Net, который содержит некоторые ресурсы (например CSS), но в будущем скорее всего не будет нужен вообще. По крайней мере, сейчас для сайтлетов он служит заглушкой со ссылкой на &ldquo;настоящий сайт&rdquo;.</li>
<li>Проект сожержащий сайтлет.</li>
<li>Проект с шаблонами.</li>
</ul>
<p>Проект с шаблонами &ndash; это возможность делать, фактически, master-странички со вставками, определеными в F#. Вы уже догадались почему нужно конвертировать HTML в F#? Поясню: в основном проекте, у нас появляется возможность <em><font face="Trebuchet MS">строготипизированно</font></em> определить, что мы помещаем в различные секции шаблона. Обычно туда помещяется либо наш F#-созданный HTML, либо&hellip; наш <code>WebControl</code>, конечно же!</p>
<p>За этим всем стоит разве что само определение сайта. Там собраны все шаблоны, и еще есть некий plumbing для того чтобы все работало.</p>
<h3>Размышления</h3>
<p>Для меня, идеальным кажется сайт, который существует целиком на клиенте, а с сервером общается только через REST или более продвинутую парадигму <em><font face="Trebuchet MS">a la</font></em> NetKernel. Поэтому в случае с ВебШарпером (надеюсь мне авторы простят русификацию названия), то чего хочу видеть я &ndash; это полную отвязку от Asp.Net и IIS. Я точно не знаю когда это будет, но коллеги подсказывают мне, что релиз WebSharper 2.0 будет отвязан от Asp.Net, в то время как полноценная поддержка сайтлетов с отвязкой от IIS будет в последующем релизе. Главное, что для перехода на Linux (а это основная цель) не надо будет ничего переписывать. По крайней мере я на это надеюсь.</p>
<p>Теперь что касается <em><font face="Trebuchet MS">юзабельности</font></em> сего фреймворка. Понятное дело что вкуривать сложную DSL и писать на F# &ndash; занятие не для слабонервных, но лично меня технические трудности не очень беспокоят. Композициональность, если так можно выразиться, фреймворка впечатляет, ровно как и его возможность быстро оборачивать такие JS библиотеки как JQueryUI, YUI или даже RxJS! Это означает что в F# можно получить унифицированную, строготипизированную модель, которая будет сама подсказывать как использовать тот или иной фреймворк и упрощать работу с ним.</p>
<h3>Анонсы</h3>
<p>Коротко о главном. Во-первых, Петербургская Группа Alt.Net планирует провести 3х-часовую встречу посвещенную F#. Максим Моисеев и я будем рассказывать про все, начиная с основных понятий и заканчивая спекуляциями на тему type provider&rsquo;ов. Встреча пройдет 3го Февраля в офисах Exigen, и в ближайшее время мы вывесим анонс на сайтах Ineta и Spbalt.net.</p>
<p>Во-вторых, на выходных периодически происходят неформальные встречи участников сообщества. Встречи происходят в моем офисе (территориально 3 мин. от м. Автово), так что если вы живете в Питере и у вас есть желание убить выходной копаясь в F# (или еще какой-нть интересной фигне) с единомышленниками, напишите мне и мы обсудим. Писать лучше по скайпу &mdash; <code>dmitri.nesteruk</code>.</p>
<p>На этом все. Comments welcome!</p><br />Filed under: <a rel="nofollow" target="_blank" href='https://nesteruk.wordpress.com/category/net/'>.NET</a>, <a rel="nofollow" target="_blank" href='https://nesteruk.wordpress.com/category/net/f/'>f#</a> Tagged: <a rel="nofollow" target="_blank" href='https://nesteruk.wordpress.com/tag/sitelet/'>sitelet</a>, <a rel="nofollow" target="_blank" href='https://nesteruk.wordpress.com/tag/websharper/'>websharper</a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gocomments/nesteruk.wordpress.com/704/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/nesteruk.wordpress.com/704/"/></a> <img alt="" border="0" src="https://pixel.wp.com/b.gif?host=nesteruk.wordpress.com&#038;blog=373435&#038;post=704&#038;subd=nesteruk&#038;ref=&#038;feed=1" width="1" height="1"/>]]></content:encoded>
         <media:content medium="image" url="https://0.gravatar.com/avatar/f01cbd2238e2a78e4c43fa596f51d6a1?s=96&amp;amp;d=https%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&amp;amp;r=PG">
            <media:title type="html">nesteruk</media:title>
         </media:content>
         <media:content medium="image" url="http://nesteruk.org/pix/0/1ac970e1-40cf-4dc7-ac88-adc39a02a8e5.png"/>
      </item>
      <item>
         <title>F# Component Design Guidelines</title>
         <link>http://ru-fsharp.livejournal.com/2892.html</link>
         <description>&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/manual/fsharp-component-design-guidelines.pdf&quot;&gt;Draft F# Component Design Guidelines (August 2010)&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;«This document looks at some of the issues related to F# component design and coding. In particular, it covers:&lt;br /&gt;• Guidelines for designing “vanilla” .NET libraries for use from any .NET language.&lt;br /&gt;• Guidelines for F#-to-F# libraries and F# implementation code.&lt;br /&gt;• Suggestions on coding conventions for F# implementation code.»</description>
         <author>Qbit</author>
         <guid isPermaLink="false">urn:lj:livejournal.com:atom1:ru_fsharp:2892</guid>
         <pubDate>Tue, 11 Jan 2011 10:15:33 +0000</pubDate>
      </item>
      <item>
         <title>Технологии на моей тарелке</title>
         <link>https://nesteruk.wordpress.com/2011/01/07/tech-on-my-plate/</link>
         <description>За последние несколько месяцев, мне под руки попался ряд технологий которые я, без стороннего влияния, наверняка никогда бы и не узнал. Причина этому во-первых в том, что я слишком сильно &amp;#8220;залип&amp;#8221; в инфраструктуре .Net и языке C# чтобы отчетливо видеть что-то за ее пределами. Тем самым, &amp;#8220;отлипание&amp;#8221; для меня &amp;#8211; процесс болезненный. А целью этого [&amp;#8230;]&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;https://pixel.wp.com/b.gif?host=nesteruk.wordpress.com&amp;#038;blog=373435&amp;#038;post=694&amp;#038;subd=nesteruk&amp;#038;ref=&amp;#038;feed=1&quot; width=&quot;1&quot; height=&quot;1&quot;/&gt;</description>
         <guid isPermaLink="false">http://nesteruk.wordpress.com/?p=694</guid>
         <pubDate>Fri, 07 Jan 2011 16:44:01 +0000</pubDate>
         <content:encoded><![CDATA[<p>За последние несколько месяцев, мне под руки попался ряд технологий которые я, без стороннего влияния, наверняка никогда бы и не узнал. Причина этому во-первых в том, что я слишком сильно &ldquo;залип&rdquo; в инфраструктуре .Net и языке C# чтобы отчетливо видеть что-то за ее пределами. Тем самым, &ldquo;отлипание&rdquo; для меня &ndash; процесс болезненный. А целью этого поста является кратко осветить те технологии, с которыми я познакомился &ndash; мало ли, может кому-то еще интересно будет.</p>
<h3>F#</h3>
<p>Писать на F# демо-программки и делать на нем что-то существенное &ndash; это совершенно разные вещи. Когда начинаешь массово плодить код на F#, начинаешь понимать всю упадочность своего понимания мира. Например, я достаточно долго писал <code>member this.Something with get() = ...</code> вместо аналогичного варианта <code>member this.Something = ...</code>. Ну и тяга к скобочкам и излишним аннотациям типов (даже там где и ежу понятно что это за тип будет) &ndash; это тоже наследие использования C# где все прописывается.</p>
<p>F# поражает скудностью поддержки в студии. На одной из моих машин вылетела поддержка IntelliSense (полностью!), на другой &ndash; F# проекты по F5 только компилируются но не запускается отладчик. Очевидно что-то тут не так. Я конечно предпринимаю <a rel="nofollow" target="_blank" href="http://activemesa.com/fsharper" title="http://acivemesa.com/fsharper">усилия</a> для того чтобы работать с F# было более гуманно, но пока что нужно делать основные вещи, такие как лексер и парсер. Адаптировать их из сорцов F#-а &mdash; дело не для слабонервных.</p>
<h3>WebSharper</h3>
<p><img class="alignright" src="https://i2.wp.com/nesteruk.org/pix/0/1ac970e1-40cf-4dc7-ac88-adc39a02a8e5.png" alt="" style="border:0;" align="right"/>Я упомянул <a rel="nofollow" target="_blank" href="http://websharpercom" title="http://websharper.com">этот фреймворк</a> в моем <a rel="nofollow" target="_blank" href="http://spbaltnet.podfm.ru/solo/28/" title="http://spbaltnet.podfm.ru/solo/28/">первом сольном подкасте</a>, сказав что он позволяет делать сайты, полностью оторваные от Asp.Net и IIS. Не знаю, один ли я страдаю такой неприязнью к IIS, но на данный момент для меня нет антидота: тот релиз Вебшарпера который состоялся недавно еще не поддерживает вторую версию Sitelet&rsquo;ов, в которой как раз и должна быть поддержка создания полностью независимых сайтов. Что-то мне подсказывает, правда, что Адам Границ и компания планируют вообще сделать чуть ли не свой веб-сервер.</p>
<p>Так или иначе, я продолжаю эксперименты с Web#, а как только появятся новые сайтлеты, я начну тестировать все это дело уже на Linux. Интересно, что хоть технология и F#, нельзя сказать что она как-то связана с .Net или Microsoft.</p>
<h3>NetKernel</h3>
<p><img src="http://t2.gstatic.com/images?q=tbn:ANd9GcR4nk9TsFsbj11Nt2PHBYMH8qoedNLzedu7yvv6HuLx5gPR1k8Z" alt="" class="alignright" style="border:0;" align="right"/>Во-первых, NK &ndash; это Java-стек, но меня это не пугает т.к. ничего страшного там нет. NK &ndash; это реализация ресурсно-ориентированной парадигмы, которая сейчас будоражит умы всех кто занимается коммуникационными технологиями, например та же комманда WCF. По сути дела, RoC в представлении NK &ndash; это REST&rsquo;ообразная концепция, которая предоставляет как бы аусторсинг веб-архитектуры, позволяя разработчикам писать компоненты, которые работают через ресурсы, запросы на ресурсы, конверсию различных типов ресурсов, и так далее.</p>
<p>NK это, если хотите, эволюция REST, и является интересной технологией (более живой чем существующие .Net аналоги) которая понравится тем, кто доселе работал с такими вещами как WCF REST.</p>
<h3>Семантический Веб</h3>
<p>Про семантический веб я <a rel="nofollow" target="_blank" href="https://nesteruk.wordpress.com/2010/12/12/a-few-words-on-semantic-web/" title="https://nesteruk.wordpress.com/2010/12/12/a-few-words-on-semantic-web/">уже писал</a>, поэтому ограничусь конкретикой, а именно теми библиотеками, которые применимы к данной задаче.</p>
<p>Во-первых, это <a rel="nofollow" target="_blank" href="http://www.dotnetrdf.org/" title="http://www.dotnetrdf.org/">DotNetRdf</a> &ndash; собственно библиотека, которая позволяет работать с RDF и поддерживает различные форматы хранилищ. Кстати, недавно нашел в блоге <a rel="nofollow" target="_blank" href="http://blog.abodit.com/2011/01/a-semantic-web-ontology-triple-store-built-on-mongodb/" title="http://blog.abodit.com/2011/01/a-semantic-web-ontology-triple-store-built-on-mongodb/">попытку создания</a> semantic triple store на MongoDB.</p>
<p>Еще один аспект моих исследований связан уже с конкретикой, а именно с онтологией <a rel="nofollow" target="_blank" href="http://www.heppnetz.de/projects/goodrelations/" title="http://www.heppnetz.de/projects/goodrelations/">Good Relations</a> и ее нынешней поддержкой гуглом (их Rich Snippets). Изначально у меня была идея попробовать подобавляеть поддержку всего этого в <a rel="nofollow" target="_blank" href="http://activemesa.com/r2p" title="http://activemesa.com/r2p">R2P</a> чтобы с этим было легче работать, но потом я узнал что модели Xml и Html в моем любимом Решарпере не имеют общего корня, что означает что, по сути дела, все пришлось бы делать дважды. Возможно когда-нибудь у меня дойдут до этого руки.</p>
<p>Так вот, в попытках найти возможность создать .Net объектную модель из OWL-файла, описывающего GR, я набрел на <a rel="nofollow" target="_blank" href="http://rowlex.nc3a.nato.int/" title="http://rowlex.nc3a.nato.int/">проект ROWLEX</a>, в котором поставляется утилита именно для этого. Интересно, а можно ли как-то автоматически брать данные со страниц, записывать их в эту модель и потом заталкивать все в MongoDB без каких-либо лишних действий? Подозреваю что все несколько сложнее&hellip;</p>
<h3>MindTouch</h3>
<p><img src="http://t2.gstatic.com/images?q=tbn:ANd9GcSRdCfnPy473CyduJ48wFbv0fv5qDkZ8S2E-wY_AgMyU9kAWG3D" alt="" style="border:0;" class="alignright" align="right"/>Я занимался исследованием <a rel="nofollow" target="_blank" href="http://mindtouch.com" title="http://mindtouch.com">MindTouch</a> в двух направлениях &ndash; в попытке понять, можно ли использовать эту штуку для документирования API большого программного продукта, а также мне хотелось понять, можно ли использовать его вместо SharePoint для внутренних целей.</p>
<p>По первому вопросу у меня нет ответа. Бесплатная версия MT шикарна, и покрывает 99% того что мне лично нужно. Поэтому в личных целях я начал ее использовать. Что же касается построения на нем портала разработчиков, то тут все неоднозначно. Я не decision maker в данном вопросе, но лично меня никто не убедил отдавать за коммерческий вариант этой штуки большие деньги.</p>
<p>Я рекоммендую всем скачать MindTouch Core (бесплатную версию) и поиграть с ней. Это действительно стоит того! Это по сути дела Wiki/CMS которая хорошо подходит для документации. Чудес в этом мире не бывает, но штука красивая, и я ей доволен.</p>
<h3>TidePowerd GPU.NET</h3>
<p>Поскольку несколько лет назад я плотно занимался GPGPU и даже сам эксплуатировал pixel shader&rsquo;ы через Direct3D, наличие .Net библиотеки мне импонирует &ndash; давно пора. Тем более что трансляция IL во что-то еще &ndash; процесс весьма понятный и реализуемый без особых проблем. Библиотека <a rel="nofollow" target="_blank" href="http://www.tidepowerd.com/" title="http://www.tidepowerd.com/">GPU.Net</a> &ndash; это как раз оно и есть. Еще одна абстракция чтобы облегчить нам жизнь.</p>
<p><del>Признаюсь что я только лишь посмотрел вебинар &ndash; я не игрался еще с самой библиотекой т.к. не было времени. Все впереди :)</del><strong>Update: </strong>уже успел созвониться с директором Tidepowerd &ndash; разговор шел в основном в ключе поддержки конкретно F# в GPU.NET. Заинтересованность определенно есть, так что рано или поздно замутим совместный конференс с Саймом, Границем, и партнерами. Как что состоится &ndash; обязательно напишу.</p>
<h3>Fusion IO</h3>
<p><a rel="nofollow" target="_blank" href="http://www.fusionio.com/" title="http://www.fusionio.com/">Fusion IO</a> &ndash; компания, которая за 3 года получила 300 миллионов долларов инвестиций. Их &ldquo;фишка&rdquo; &ndash; высокоскоростные хранилища данных, и когда я говорю &ldquo;хранилище&rdquo;, подразумевается PCI-карта с SSD-устройствами на ней. Конечно, Fusion IO говорит что их устройства &ndash; это <em><font face="Candara">не</font></em> SSD, но на самом деле их отличие в качественном ПО (в плане прошивки их ASIC), а есть ли у них что-то кардинально новое &ndash; не знаю. Надо получить образец (надеюсь дадут) и самому посмотреть.</p>
<p>Хотя если по мне, так более интересной фишкой является <a rel="nofollow" target="_blank" href="http://ru.wikipedia.org/wiki/Nvidia_Tegra" title="http://ru.wikipedia.org/wiki/Nvidia_Tegra">NVidia Tegra</a> &ndash; нам уже 10 лет назад нужно было иметь нормальные <a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/System-on-a-chip" title="http://en.wikipedia.org/wiki/System-on-a-chip">SoC</a>-решения. Те же Fusion IO могли бы засунуть на свои карты контроллер и несколько FPGA которые я бы мог &ldquo;флэшить&rdquo; и им цены бы не было! Вот интересно &ndash; Intel уже начал нервничать или еще нет? Ведь по мне так самое главное это избавиться от ситуации когда я не могу иметь масштабно-инвариантную систему, а должен на каждый процессор закупать еще и материнскую плату, память, жесткий диск, и так далее. Надеюсь скоро эти телодвижения станут пережитками прошлого.</p>
<p>Кстати о Tegra&hellip; двухъядерные процессоры в мобильных телефонах это круто или как?</p><br />Filed under: <a rel="nofollow" target="_blank" href='https://nesteruk.wordpress.com/category/net/'>.NET</a>, <a rel="nofollow" target="_blank" href='https://nesteruk.wordpress.com/category/net/f/'>f#</a>, <a rel="nofollow" target="_blank" href='https://nesteruk.wordpress.com/category/gpu/'>GPU</a>, <a rel="nofollow" target="_blank" href='https://nesteruk.wordpress.com/category/hardware/'>Hardware</a> Tagged: <a rel="nofollow" target="_blank" href='https://nesteruk.wordpress.com/tag/dotnetrdf/'>dotnetrdf</a>, <a rel="nofollow" target="_blank" href='https://nesteruk.wordpress.com/tag/good-relations/'>good relations</a>, <a rel="nofollow" target="_blank" href='https://nesteruk.wordpress.com/tag/gpu-net/'>gpu.net</a>, <a rel="nofollow" target="_blank" href='https://nesteruk.wordpress.com/tag/mindtouch/'>mindtouch</a>, <a rel="nofollow" target="_blank" href='https://nesteruk.wordpress.com/tag/netkernel/'>netkernel</a> <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gocomments/nesteruk.wordpress.com/694/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/nesteruk.wordpress.com/694/"/></a> <img alt="" border="0" src="https://pixel.wp.com/b.gif?host=nesteruk.wordpress.com&#038;blog=373435&#038;post=694&#038;subd=nesteruk&#038;ref=&#038;feed=1" width="1" height="1"/>]]></content:encoded>
         <media:content medium="image" url="https://0.gravatar.com/avatar/f01cbd2238e2a78e4c43fa596f51d6a1?s=96&amp;amp;d=https%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&amp;amp;r=PG">
            <media:title type="html">nesteruk</media:title>
         </media:content>
         <media:content medium="image" url="http://nesteruk.org/pix/0/1ac970e1-40cf-4dc7-ac88-adc39a02a8e5.png"/>
         <media:content medium="image" url="http://t2.gstatic.com/images?q=tbn:ANd9GcR4nk9TsFsbj11Nt2PHBYMH8qoedNLzedu7yvv6HuLx5gPR1k8Z"/>
         <media:content medium="image" url="http://t2.gstatic.com/images?q=tbn:ANd9GcSRdCfnPy473CyduJ48wFbv0fv5qDkZ8S2E-wY_AgMyU9kAWG3D"/>
      </item>
      <item>
         <title>Композиция функций и странные баги</title>
         <link>http://norgblog.blogspot.com/2010/12/blog-post.html</link>
         <description>Начал потихоньку вникать в теорию комбинаторов и решил попробовать их реализовать на F#.

Но наткнулся на один странный баг, который не смог воспроизвести дома. А именно, есть комбинатор функций a, b:

let (|&amp;gt;&amp;gt;) a b =
    fun x -&amp;gt; a x |&amp;gt; b
Так вот, используя интерпритатор F# из плагина к VS2008 я не мог построить комбинацию скажем таких функций:

let f1 x = x + 1
let f2 x = x.ToString() </description>
         <author>Максим Карандашов</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-5219626453078054207.post-897382679926687736</guid>
         <pubDate>Tue, 28 Dec 2010 07:46:00 +0000</pubDate>
      </item>
      <item>
         <title>F# Snippets</title>
         <link>http://norgblog.blogspot.com/2010/12/f-snippets.html</link>
         <description>Бродя по интернету в поисках инфы про quotations наткнулся у Томаса Петричека на следующую ссылку: http://fssnip.net/

более чем полезный ресурс, особенно если он будет и дальше развиваться.</description>
         <author>Максим Карандашов</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-5219626453078054207.post-3941441595655514216</guid>
         <pubDate>Thu, 16 Dec 2010 10:53:00 +0000</pubDate>
      </item>
      <item>
         <title>Скорость вычислений на  F#</title>
         <link>http://norgblog.blogspot.com/2010/11/f.html</link>
         <description>Недавно задумался над скоростью вычислений в F#, а вернее о том, стоит ли заморачиваться использую lazy() и seq. Поверхностные тесты seq показывают, что seq лучше для вычислений чем list:



&amp;gt; Seq.sum (seq{ for i in 1.0 .. 50.0 -&amp;gt; 1.0/(i*i*i) });;
Real: 00:00:00.001, CPU: 00:00:00.000, GC gen0: 0, gen1: 0, gen2: 0
val it : float = 1.201860863
&amp;gt; List.sum [ for i in 1.0 .. 50.0 -&amp;gt; 1.0/(i*i*i) ];;</description>
         <author>Максим Карандашов</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-5219626453078054207.post-4333021737104091991</guid>
         <pubDate>Tue, 30 Nov 2010 11:44:00 +0000</pubDate>
      </item>
      <item>
         <title>Ну разве этот код не красив?...</title>
         <link>http://norgblog.blogspot.com/2010/11/blog-post_19.html</link>
         <description>/// L1 ⊕k L2 = {w | (w = xy, x ∈ L1, y ∈ L2, |xy| 6 k) ∨ (w = γ, xy = γβ, x ∈ L1, y ∈ L2, |γ| = k)}.
let plus k (L1 : List) (L2 : List) =
    List.fold (fun (acc : list) (x : string) -&amp;gt;
        (List.map (fun (y : string) -&amp;gt; 
                if (x.Length + y.Length) &amp;lt; k 
                    then x + y
                    else (x + y).Substring(0, k)
                ) L2 
            ) @ acc</description>
         <author>Максим Карандашов</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-5219626453078054207.post-1972878709281698935</guid>
         <pubDate>Fri, 19 Nov 2010 13:28:00 +0000</pubDate>
      </item>
      <item>
         <title>Как оперденью сломать F#?</title>
         <link>http://metaclass.livejournal.com/573846.html</link>
         <description>Элементарно. &lt;br /&gt; Экспортируем из опердени датасет с 381 записью по 40 полей в каждой в формат исходника F# и пытаемся это компилировать. Каких-то несчастных 10 тыс строк и 660 килобайт кода. Компилятор сдыхает с переполнением стека. Так же как и хаскель когда-то в такой же ситуации. &lt;br /&gt; Придется все-таки для таких целей написать адекватную сериализацию, чтобы данные лежали не в исходнике, а отдельно, а исходник содержал только метаданные и код чтения.&lt;br /&gt; &lt;br /&gt; Вообще, изначальная идея такова - часто есть необходимость произвести некое нетривиальное вуду над отчетом для проверки, и мне кажется, что экспорт отчета в виде исходника, а затем загрузка этого исходника в интерактивную консоль хаскеля или F# - это самый простой способ надругаться над данными отчета функциональщиной.&lt;br /&gt; Например, сегодня была надобность из метаданных SQL запроса генерировать более другой запрос, чтобы эти самые пресловутые 40 полей не повторять 10 раз вручную.</description>
         <guid isPermaLink="false">urn:lj:livejournal.com:atom1:metaclass:573846</guid>
         <pubDate>Sat, 13 Nov 2010 21:49:20 +0000</pubDate>
      </item>
      <item>
         <title>Кодогенераторное</title>
         <link>http://metaclass.livejournal.com/570860.html</link>
         <description>И таки несамочевидное решение &quot;сделать одноразовую опердень по-человечески, с кодогенератором, F# и тестершами&quot; показало свою полезность и адекватность в первый же день использования оной опердени.&lt;br /&gt; Пользователи по результатам уточнили требования, а внутреннее тестирование обнаружило небольшой баг, что привело к необходимости добавить одно поле в таблицу. Если бы не кодогенерация - я бы сейчас искал и менял вручную с десяток мест, где нужно добавить это поле - объект данных, его дампы, dao-классы, sql-запросы, гриды для отображения, подписи к этим гридам и прочая, и прочая.&lt;br /&gt; А так доработка даже с учетом того, что кодогенератор пока не умеет миграцию БД ни в каком виде, заняла 40 минут.</description>
         <guid isPermaLink="false">urn:lj:livejournal.com:atom1:metaclass:570860</guid>
         <pubDate>Mon, 08 Nov 2010 16:00:19 +0000</pubDate>
      </item>
      <item>
         <title>The F# Compiler Source Code Drop</title>
         <link>http://ru-fsharp.livejournal.com/2563.html</link>
         <description>Дон Сайм сообщил о публикации исходников компилятора и библиотеки под лицензией Apache 2.0: &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://blogs.msdn.com/b/dsyme/archive/2010/11/04/announcing-the-f-compiler-library-source-code-drop.aspx&quot;&gt;http://blogs.msdn.com/b/dsyme/archive/2010/11/04/announcing-the-f-compiler-library-source-code-drop.aspx&lt;/a&gt;.&lt;br /&gt;(via RSDN)</description>
         <author>Qbit</author>
         <guid isPermaLink="false">urn:lj:livejournal.com:atom1:ru_fsharp:2563</guid>
         <pubDate>Fri, 05 Nov 2010 10:56:18 +0000</pubDate>
      </item>
      <item>
         <title>Upd. Паттерн матчинг</title>
         <link>http://norgblog.blogspot.com/2010/10/upd.html</link>
         <description>В догонку к предыдущему сообщению.


let find = function
    | &quot;by&quot; :: &quot;name&quot; :: _ :: []  -&amp;gt; 3
    | &quot;by&quot; :: &quot;autor&quot; :: _ :: [] -&amp;gt; 4
    | &quot;by&quot; :: &quot;autors&quot; :: _ :: [] -&amp;gt; 5
    | _ -&amp;gt; 0и let find = function
    | &quot;by&quot; :: &quot;name&quot; :: t when t &amp;lt;&amp;gt; [] -&amp;gt; 3
    | &quot;by&quot; :: &quot;autor&quot; :: t when t &amp;lt;&amp;gt; [] -&amp;gt; 4
    | &quot;by&quot; :: &quot;autors&quot; :: t when t &amp;lt;&amp;gt; [] -&amp;gt; 5
    | _ -&amp;gt; 0Так вот, 2й вариант значительно хуже! Он</description>
         <author>Максим Карандашов</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-5219626453078054207.post-2335756791736889533</guid>
         <pubDate>Wed, 27 Oct 2010 10:29:00 +0000</pubDate>
      </item>
      <item>
         <title>Паттерн матчинг и выделение памяти</title>
         <link>http://norgblog.blogspot.com/2010/10/blog-post_27.html</link>
         <description>Есть небольшой и довольно простой код:


let replace = function
    | &quot;by&quot; :: &quot;id&quot; :: t :: [] -&amp;gt; 8
    | _ -&amp;gt; 0t :: [] - используется для того, чтобы гарантировать наличие одного свободного эл-та в списке.
И вроде бы всё хорошо, но если посмотреть в рефлекторе, то можно увидеть такую картину:

 public static int replace(FSharpList _arg1)
{
    if (_arg1.get_TailOrNull() != null)
    {</description>
         <author>Максим Карандашов</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-5219626453078054207.post-236184209393484641</guid>
         <pubDate>Wed, 27 Oct 2010 10:16:00 +0000</pubDate>
      </item>
      <item>
         <title>mutable привязки, интерпретатор и массивы</title>
         <link>http://norgblog.blogspot.com/2010/10/mutable.html</link>
         <description>Есть такой код:

let mutable x =
    [|
     1; 2; 3; 4; 5;
     2; 3; 5; 6; 3;
     |]
 
let to_null =
    for i in 0..9 do        x.[i] &amp;lt;- 0
загоняем его в интерпретатор и получаем соотв.:

val mutable x : int [] = [|0; 0; 0; 0; 0; 0; 0; 0; 0; 0|]
val to_null : unit = ()


Всё правильно, всё логично.

А теперь снова засунем в интерпретатор x:
val mutable x : int [] = [|1; 2; 3; 4; 5; 2; 3; 5; 6</description>
         <author>Максим Карандашов</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-5219626453078054207.post-1067972620516153393</guid>
         <pubDate>Tue, 26 Oct 2010 15:39:00 +0000</pubDate>
      </item>
      <item>
         <title>Динамические системы в F# - задание, динамика</title>
         <link>http://norgblog.blogspot.com/2010/10/f.html</link>
         <description>Решил начинать потихоньку писать код по ДС на F#. Оказалось это очень удобно и невообразимо просто, если знать что такое карринг;)

Итак, ДС состоит из двух элементов:

Множество состояний S;
Функция переходов(эволюции) f : S -&amp;gt; S.
очевидным образом можно примерно получить описание такого объекта на F#:Set&amp;lt;'a&amp;gt; * ('a -&amp;gt; 'a),
т.е. это кортеж из множества и функции.
Ну с множеством всё понятно - это</description>
         <author>Максим Карандашов</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-5219626453078054207.post-850158693993752640</guid>
         <pubDate>Fri, 15 Oct 2010 10:55:00 +0000</pubDate>
      </item>
      <item>
         <title>Дай дураку F# стеклянный..</title>
         <link>http://metaclass.livejournal.com/557414.html</link>
         <description>Домудрился с вложенными ленивыми секвенсами вперемежку с обращениями к БД до такой степени, что сломал компилятор F#, похоже. Во всяком случае, он у меня теперь умудряется сделать Dispose команде доступа к БД до того как начнет генерить последовательность из нее. Причем, что удивительно - не всегда, а только при определенном паттерне обращения к другим командам. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;
2010-10-13 21:43:20,944 [1] DEBUG StartupCode$ModelGen.$FirebirdReader newCmd   cmdForeignKeys 61724767 Open
2010-10-13 21:43:20,944 [1] DEBUG StartupCode$ModelGen.$FirebirdReader newCmd   cmdForeignKeyFields 18651996 Open
2010-10-13 21:43:20,944 [1] DEBUG StartupCode$ModelGen.$FirebirdReader Disposed cmdForeignKeyFields cmdForeignKeyFields 18651996
2010-10-13 21:43:20,944 [1] DEBUG StartupCode$ModelGen.$FirebirdReader Disposed cmdForeignKeys cmdForeignKeys 61724767
2010-10-13 21:43:20,944 [1] DEBUG StartupCode$ModelGen.$FirebirdReader cmdForeignKeyFields.ExecuteReader 18651996 ForeignKeyFields FK_ForeignKeys
2010-10-13 21:43:20,944 [1] FATAL CurrentDomain_UnhandledException
System.InvalidOperationException: Connection must be valid and open
&lt;/pre&gt;&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; name='cutid1-end'&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt; Однозначно, что ленивость+внешние ресурсы это не совсем то, что следует делать, да и отладке это не подлежит в принципе, ибо монады. Но как превратить это дело в fold-like алгоритм, хрен его знает, да еще с учетом того, что там внутри не просто итератор по плоским записям, а внутри этих записей еще вложенные итераторы, а из них ссылки на элементы из других итераторов, в общем, ад тот еще. &lt;br /&gt; Вот еще смех будет, если это не в F# проблема, а в ADO.NET провайдере Firebird.&lt;br /&gt;&lt;br /&gt;PS: Судя по всему, все хорошо и пень все таки я - таки ленивые вложенные итераторы можно использовать только вложенно, а не так как я - сначала пройтись по внешнему, найти нужную запись, а потом из нее читать вложенные. Адекватный вариант - сделать их неленивыми. Обычно в этом помогает Seq.cache, но тут он, похоже, тоже вызывается в неподходящий момент.&lt;br /&gt;&lt;br /&gt;PPS: Ухуху, и решение в этом случае действительно, как и советуют гуру ленивости - перевернуть все в fold-like алгоритм, передав две функции - одну для fold внешнего итератора и одну для fold внутреннего (и вроде в общем случае, еще две - одну которая будет из внешнего итератора и состояния делать начальное состояние для fold внутреннего, и вторая будет комбинировать результат от fold внутреннего итератора и состояние внешнего).&lt;br /&gt; Это получается, что для fold в случае вложенных итераторов количество передаваемых параметров-функций прилично возрастает: по одной функции на каждый итератор в иерархии и +2 на каждый случай вложенного итератора, причем у самих этих функций количество передаваемых в них параметров тоже особой радости не доставляет. &lt;br /&gt; Зато соответствующим набором таких функций, судя по всему, можно вычислить произвольную функцию от базы данных, представленной в виде набора разнообразно вложенных итераторов  :)</description>
         <guid isPermaLink="false">urn:lj:livejournal.com:atom1:metaclass:557414</guid>
         <pubDate>Wed, 13 Oct 2010 18:49:07 +0000</pubDate>
      </item>
      <item>
         <title>Еще один красивый пример</title>
         <link>http://skiminog.livejournal.com/77411.html</link>
         <description>Боянистый, правда, до ужаса, но тем не менее красивый.&lt;br /&gt;&lt;br /&gt;Взять список чисел на входе. Вернуть на выходе список списков: все перестановки заданных чисел.&lt;br /&gt;Иллюстрирует:&lt;ul&gt;&lt;li&gt;List comprehensions&lt;/li&gt;&lt;li&gt;Правую свертку&lt;/li&gt;&lt;li&gt;Композицию функций&lt;/li&gt;&lt;/ul&gt;Если бы авторы F# изгнали мочу из головы и поставили, как все нормальные люди, аргумент-список в foldBack на последнее место, то иллюстрировал бы еще и частичное применение / карринг. (Правда, для этого потребуется изгнать мочу и из компилятора, а то получим радостный Value restriction, будь он неладен.)&lt;br /&gt;Будучи дословно переведенным на Haskell, иллюстрирует ленивую генерацию списка. На F# для этого потребуется seq, который некрасиво пишется :-)&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;color:black;overflow:auto;font-family:monospace;border:1px solid black;padding:5px;background:white;&quot;&gt;&lt;pre style=&quot;background:White;margin:0em;&quot;&gt; &lt;span style=&quot;color:#0000ff;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#000000;&quot;&gt; permute xs =&lt;/pre&gt;&lt;pre style=&quot;background:White;margin:0em;&quot;&gt;     &lt;span style=&quot;color:#0000ff;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#000000;&quot;&gt; &lt;span style=&quot;color:#0000ff;&quot;&gt;rec&lt;/span&gt;&lt;span style=&quot;color:#000000;&quot;&gt; insert x = &lt;span style=&quot;color:#0000ff;&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color:#000000;&quot;&gt; &lt;/pre&gt;&lt;pre style=&quot;background:White;margin:0em;&quot;&gt;         | [] &lt;span style=&quot;color:#0000ff;&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#000000;&quot;&gt; [[x]]&lt;/pre&gt;&lt;pre style=&quot;background:White;margin:0em;&quot;&gt;         | y::ys &lt;span style=&quot;color:#0000ff;&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#000000;&quot;&gt; (x::y::ys)::[&lt;span style=&quot;color:#0000ff;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#000000;&quot;&gt; res &lt;span style=&quot;color:#0000ff;&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#000000;&quot;&gt; insert x ys &lt;span style=&quot;color:#0000ff;&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#000000;&quot;&gt; y::res]&lt;/pre&gt;&lt;pre style=&quot;background:White;margin:0em;&quot;&gt;     List.foldBack (insert &amp;gt;&amp;gt; List.collect) xs [[]]&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Работа:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&amp;gt; permute [1..4];;
val it : int list list =
  [[1; 2; 3; 4]; [2; 1; 3; 4]; [2; 3; 1; 4]; [2; 3; 4; 1]; [1; 3; 2; 4];
   [3; 1; 2; 4]; [3; 2; 1; 4]; [3; 2; 4; 1]; [1; 3; 4; 2]; [3; 1; 4; 2];
   [3; 4; 1; 2]; [3; 4; 2; 1]; [1; 2; 4; 3]; [2; 1; 4; 3]; [2; 4; 1; 3];
   [2; 4; 3; 1]; [1; 4; 2; 3]; [4; 1; 2; 3]; [4; 2; 1; 3]; [4; 2; 3; 1];
   [1; 4; 3; 2]; [4; 1; 3; 2]; [4; 3; 1; 2]; [4; 3; 2; 1]]&lt;/pre&gt;&lt;br /&gt;Хорошее упражнение: посчитать сложность работы permute ;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;</description>
         <guid isPermaLink="false">urn:lj:livejournal.com:atom1:skiminog:77411</guid>
         <pubDate>Sun, 10 Oct 2010 12:26:23 +0000</pubDate>
      </item>
      <item>
         <title>Удаление бесплодных и недостижимых символов из КС-грамматики</title>
         <link>http://norgblog.blogspot.com/2010/10/blog-post.html</link>
         <description>Не далее как сегодня утром я таки дошёл с флешкой и таки сдал эти задачки:)

Привожу тут код этих алгоритмов:

N, E - Set - мн-ва не&amp;#92;терминальных символов
P - Set&amp;gt; - мн-во правил грамматики


// функция построения Ni для DelSterileChar
    let rec del_char (N' : Set) : Set = 
        let Ni : Set = 
            Set.map (fun (a, b) -&amp;gt; 
                        if List.forall (fun e -&amp;gt; N'.Contains(</description>
         <author>Максим Карандашов</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-5219626453078054207.post-5612189584688675915</guid>
         <pubDate>Fri, 08 Oct 2010 11:33:00 +0000</pubDate>
      </item>
      <item>
         <title>Еще один однострочник</title>
         <link>http://skiminog.livejournal.com/76110.html</link>
         <description>Хозяйке на заметку: красивая проверка любой последовательности на отсортированность в одну строку. За O(N), между прочим. Ленивое, между прочим.&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;font-family:monospace;font-size:9pt;color:black;background:white;border:1px solid #d0d0d0;&quot;&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&lt;br /&gt;&lt;span style=&quot;color:blue;&quot;&gt;&amp;nbsp;&amp;nbsp;let&lt;/span&gt; sorted xs = Seq.forall id &amp;lt;| seq { &lt;span style=&quot;color:blue;&quot;&gt;for&lt;/span&gt; (a, b) &lt;span style=&quot;color:blue;&quot;&gt;in&lt;/span&gt; Seq.pairwise xs &lt;span style=&quot;color:blue;&quot;&gt;-&amp;gt;&lt;/span&gt; a &amp;lt;= b }&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;/div&gt;</description>
         <guid isPermaLink="false">urn:lj:livejournal.com:atom1:skiminog:76110</guid>
         <pubDate>Mon, 20 Sep 2010 21:11:29 +0000</pubDate>
      </item>
      <item>
         <title>CodeDom для F#</title>
         <link>http://dsorokin.blogspot.com/2010/09/codedom-f.html</link>
         <description>&lt;div&gt;Сегодня взял свою библиотеку MapSim, которая умеет создавать код через CodeDom, и заменил СSharpCodeProvider на FSharpCodeProvider из F# PowerPack. Сработало! MapSim по заданному входу сгенерировал код на F#. Только местами забавный код получился. В одном месте создаются исключения только для того, чтобы их тут же перехватить. Странно как-то. Но в целом качество кода сопоставимо с тем, что у меня создает стандартный провайдер C#.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;</description>
         <author>dsorokin</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-8641042312683198534.post-7163750447179761502</guid>
         <pubDate>Fri, 17 Sep 2010 15:34:00 +0000</pubDate>
      </item>
      <item>
         <title>Принудительная хвостовая рекурсия: жрать память вместо стека?</title>
         <link>http://metaclass.livejournal.com/537053.html</link>
         <description>Читаю про &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://lorgonblog.spaces.live.com/blog/cns!701679AD17B6D310!170.entry?_c=BlogPart&quot;&gt;катаморфизмы и FSharp&lt;/a&gt;. Вообще, изначально это я искал ответ на &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://gds.livejournal.com/52526.html?thread=176686#t176686&quot;&gt;этот вопрос&lt;/a&gt;, но зачитался и забыл.&lt;br /&gt; &lt;br /&gt; Там приводится пример, как выразить foldBack (оно же foldr) через fold(оно же foldl) с помощью continuations. И выглядит это как будто мы заменяем использование стека в случае не-tail-recursive функции таким же использованием памяти из head. Причем в случае стека выделение и удаление памяти достаточно дешевое, а вот что будет в случае обычной памяти - вопрос загадочный. Непонятно, есть ли тогда какие-нибудь преимущества у такого преобразования не-tail-recursive функции в tail-recursive?</description>
         <guid isPermaLink="false">urn:lj:livejournal.com:atom1:metaclass:537053</guid>
         <pubDate>Mon, 13 Sep 2010 17:55:26 +0000</pubDate>
      </item>
      <item>
         <title>О вычислительных выражениях</title>
         <link>http://dsorokin.blogspot.com/2010/09/blog-post.html</link>
         <description>Уже почти год пишу на F#, и мне так понравились вычислительные выражения! Удивительно простая в использовании штука. Такое выражение можно записать в императивном стиле как почти обычный код на F#, используя while, for и try, а оно потом на выходе будет преобразовано компилятором F# в выражение, состоящее из композиции функции. Императивная конструкция превращается в сугубо функциональное выражение. Замечательная идея. Сюда же легко вписываются монады и моноиды. Вот, с монадными трансформерами накладка. &lt;div&gt;&lt;br /&gt;Поддержка таких выражений – это просто непередаваемая по значимости вещь для императивных монад типа Async для асинхронных вычислений. Более того, не нужно поддерживать на уровне языка продолжения – для них можно использовать те же вычислительные выражения (но нужна поддержка TCO на уровне исполняющей среды). Продолжения не совсем императивны, но все же блоки try-with и try-finally обрабатывать в таком языке как F# надо. И здесь нет известной проблемы Common Lisp.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;Кстати, о Лиспе. Считаю, что вычислительные выражения и макросы мешают друг другу.  Эти выражения предполагают, что есть ограниченное множество конструкций языка, которые могут быть “офункционалены” (превращены в функции). Макросы это нарушают. Когда я добавлял поддержку вычислительных выражений в Немерле, то оставлял макросы как есть. Не знаю, можно ли придумать здесь что-то лучше? (интересно, а как макросы и продолжения сосуществуют в Схеме?)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;Мне теперь стало очень не хватать вычислительных выражений в Скале и Окамле. Скаловский for-comprehension смотрится как-то слабо, особенно для императивных монад, когда вычисления нужно разбавить обычным кодом. Что касается Окамла, то для него есть одно расширение, но очень хотелось бы, чтобы решение было стандартизировано и “из-коробки”. Надеюсь, что когда-нибудь добавят.&lt;br /&gt;&lt;/div&gt;</description>
         <author>dsorokin</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-8641042312683198534.post-2348427458154278646</guid>
         <pubDate>Sun, 12 Sep 2010 13:57:00 +0000</pubDate>
      </item>
      <item>
         <title>А вот и немножко грибов от использования F#</title>
         <link>http://metaclass.livejournal.com/536344.html</link>
         <description>Ради теста обновил F# с 1.9.7.8 до 2.0.0.0. Сломалось:&lt;br /&gt;1) fslex, fsyacc ставятся отдельно с FSharp PowerPack, в основную инсталляцию не входят&lt;br /&gt;2) Warning насчет имени модуля в начале файла стал полноценной ошибкой - пришлось поправить исходники парсера и опцию --module для fsyacc чтобы это имя модуля появилось в сгенерированных файлах.&lt;br /&gt;3) Самое неприятное для меня изменение - теперь optional parameters могут быть только в конце сигнатуры метода, а у меня было штук 5 конструкторов с опциональными параметрами в начале - это AST для генерируемого кода и там по логике идет что-то вроде такого:&lt;br /&gt;([опциональные атрибуты] [опциональный модификатор видимости] тип имя [опциональный код инициализации])&lt;br /&gt;В общем, это обходится досточно просто - делаем вместо одного конструктора несколько - один со всеми параметрами, и остальные - с наиболее часто встречающимися вариациями вызовов.&lt;br /&gt;&lt;br /&gt; ChangeLog для F# 2.0 я найти не в состоянии, может меня конечно гугл лично ненавидит в этом плане, не знаю. &lt;br /&gt; И вообще, F#, конечно, язык весьма удобный, но ставить его в продакшен за пределы личного использования я как-то опасаюсь - очень уж разрозненные сведения по нему в интернетах и выглядит это все, как будто он живет усилиями Дона Сайма, проталкивающего его всюду.&lt;br /&gt;&lt;br /&gt; Т.е. что я хочу сказать - пихать в продакшен что-то не мейнстримовое можно, только имея или личный контакт с девелоперами, или надмозгов на работе, которые в случае чего смогут разгрести внезапно возникший ад угара.</description>
         <guid isPermaLink="false">urn:lj:livejournal.com:atom1:metaclass:536344</guid>
         <pubDate>Sun, 12 Sep 2010 12:23:02 +0000</pubDate>
      </item>
      <item>
         <title>&quot;Кости&quot; в консоли на F#</title>
         <link>http://norgblog.blogspot.com/2010/08/f_29.html</link>
         <description>небольшая &quot;игрушка&quot; написанная на F# с применением ООП...
написанная правда фигово с точки зрения того же ООП:)

смысл - посмотреть, как юзаются классы с F#)

module BoneGame

open System
open System.Collections.Generic

#light

type UserInterface () =
    member x.Roll : bool =
        printfn &quot;Вы будете бросать кубик?&quot;
        x.QuestYN

    member x.PrintState (data : list) : unit =</description>
         <author>Максим Карандашов</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-5219626453078054207.post-543678212484521091</guid>
         <pubDate>Sun, 29 Aug 2010 06:21:00 +0000</pubDate>
      </item>
      <item>
         <title>Ревью нескольких .Net-ориентированных книг от Manning</title>
         <link>https://nesteruk.wordpress.com/2010/08/27/manning-dotnet-book-review/</link>
         <description>&lt;p&gt;&lt;img src=&quot;http://nesteruk.org/pix/0/de713ad9-ee79-44d6-83dc-af770df02bca.jpg&quot; class=&quot;alignleft&quot; alt=&quot;&quot; style=&quot;border:0;margin-right:10px;&quot;/&gt;Это еще один пост с обзором книг, но в этот раз «с изюминкой» &amp;#8211; будем обсуждать книги издательства &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.manning.com/&quot; title=&quot;http://www.manning.com/&quot;&gt;Manning&lt;/a&gt;. По сравнению с Apress (см. &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://nesteruk.wordpress.com/2010/08/22/apress-dotnet-book-review/&quot; title=&quot;https://nesteruk.wordpress.com/2010/08/22/apress-dotnet-book-review/&quot;&gt;предыдущий обзор&lt;/a&gt;), издательство Manning Publications печатают книги совсем другого уровня. У них, например, печатаются такие люди как Джон Скит или Айенде. Книги от Manning &amp;#8211; это далеко не утилитарные произведения, что с одной стороны хорошо (технический уровень намного выше) а с другой стороны не очень (книги иногда сложно читать, и многие из них недоступны для новичков).&lt;br /&gt;&lt;br /&gt;Заметьте, тут всего 4 книжки. Хочется больше, но как-то руки не доходят попросить у Manning несколько review-копий.&lt;/p&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;https://pixel.wp.com/b.gif?host=nesteruk.wordpress.com&amp;#038;blog=373435&amp;#038;post=563&amp;#038;subd=nesteruk&amp;#038;ref=&amp;#038;feed=1&quot; width=&quot;1&quot; height=&quot;1&quot;/&gt;</description>
         <guid isPermaLink="false">http://nesteruk.wordpress.com/?p=563</guid>
         <pubDate>Fri, 27 Aug 2010 11:07:56 +0000</pubDate>
         <content:encoded><![CDATA[<p><img src="https://i1.wp.com/nesteruk.org/pix/0/de713ad9-ee79-44d6-83dc-af770df02bca.jpg" class="alignleft" alt="" style="border:0;margin-right:10px;"/>Это еще один пост с обзором книг, но в этот раз «с изюминкой» &ndash; будем обсуждать книги издательства <a rel="nofollow" target="_blank" href="http://www.manning.com/" title="http://www.manning.com/">Manning</a>. По сравнению с Apress (см. <a rel="nofollow" target="_blank" href="https://nesteruk.wordpress.com/2010/08/22/apress-dotnet-book-review/" title="https://nesteruk.wordpress.com/2010/08/22/apress-dotnet-book-review/">предыдущий обзор</a>), издательство Manning Publications печатают книги совсем другого уровня. У них, например, печатаются такие люди как Джон Скит или Айенде. Книги от Manning &ndash; это далеко не утилитарные произведения, что с одной стороны хорошо (технический уровень намного выше) а с другой стороны не очень (книги иногда сложно читать, и многие из них недоступны для новичков).</p>
<p>Заметьте, тут всего 4 книжки. Хочется больше, но как-то руки не доходят попросить у Manning несколько review-копий.</p>
<hr />
<h3 style="margin-top:15px;">DSLs in BOO</h3>
<p>
<img src="https://i2.wp.com/nesteruk.org/pix/0/ed1384b6-bd51-46d8-86e2-ca04ed6e134a.jpg" class="alignright" align="right" alt=""/><br />
Собственно сам язык Boo (некоторые почему-то пишут BOO) мне интересен только одной фичей &ndash; поддержкой метапрограммирования или, другими словами, возможностью расширять компилятор. Привлекательно это потому, что научиться конкретно метапрограммированию в Boo не так сложно, хотя и приходится отказаться от таких приятностей как синтаксис C#, Visual Studio (нужно использовать SharpDevelop) и соответственно IntelliSense. Как бы там ни было, популярный блоггер <a rel="nofollow" target="_blank" href="http://www.ayende.com/" title="http://www.ayende.com/">Айенде</a> решил встать «впереди планеты всей» и написал книжку про то, как создавать доменно-специфичные языки (DSL-и) на этом питонообразном языке.
</p>
<p>Если быть откровенным, то книжка у Айенде <em><font face="Trebuchet MS">не получилась</font></em>. Совсем. Главной причиной является то, что Айенде плохо пишет &ndash; у него явно нет навыков для написания больших монографий, и с первых страниц книги читатель может ощутить тот дискомфорт который автор испытывает, пытаясь передать мысль в когерентной форме. Теперь насчет собственно структуры контента. Во-первых, Айенде плохо продает идею DSLей &ndash; а ее, как мне кажется, <em><font face="Candara">нужно</font></em> продавать. Например, показать пример BDD-фреймворка и сказать что это DSL &ndash; это как-то нечестно потому что я, например, могу привести контр-пример где мы используем, скажем, Cucumber (Ruby) чтобы написать то же самое, и для этого мне не нужен Boo. Возникает естественный вопрос: а что нам дает именно Boo, чем он лучше и полезнее?</p>
<p>Далее в книге идет описание самого языка, и интересно что на создание DSLей на этом языке выделено всего 2 главы из 13 &ndash; остальное это либо вводные части, либо примеры реализаций. Кстати насчет примеров &ndash; они все не просто короткие, они <em><font face="Candara">коротенькие</font></em> и ультра-простые. Это я к тому, что в моей практике DSLи имеет смысл использовать тогда, когда за одной строчкой DSL скрывается 5-10 обычного C#. У Айенде же в примерах соотношение примерно 1:1. Зато количество инфраструктурных обсуждений в книге очень большое &ndash; тестирование, создание UI, да просто обсуждение того как сортировать скрипты &ndash; возникает вопрос о смещении ценностей. Ведь все-таки изначальная идея была продать Boo как язык для создания DSLей, а в результате она как бы вышла на второй план.</p>
<p>В заключение скажу что на книгу я возлагал много надежд, купив ее в форме early access для подготовки к небольшому <a rel="nofollow" target="_blank" href="http://www.slideshare.net/DmitriNesteruk/metaprogramming-2349505" title="http://www.slideshare.net/DmitriNesteruk/metaprogramming-2349505">семинару по метапрограммированию</a>, но в результате разочаровался. Что ж, иногда и так бывает.</p>
<p><img src="https://i1.wp.com/nesteruk.org/pix/star.gif" style="border:0;margin:0;padding:0;" alt="1 stars"/><img src="https://i1.wp.com/nesteruk.org/pix/star-none.gif" style="border:0;margin:0;padding:0;" alt="1 stars"/><img src="https://i1.wp.com/nesteruk.org/pix/star-none.gif" style="border:0;margin:0;padding:0;" alt="1 stars"/><img src="https://i1.wp.com/nesteruk.org/pix/star-none.gif" style="border:0;margin:0;padding:0;" alt="1 stars"/><img src="https://i1.wp.com/nesteruk.org/pix/star-none.gif" style="border:0;margin:0;padding:0;" alt="1 stars"/></p>
<h3>ASP.NET MVC 2 in Action</h3>
<p><img src="https://i1.wp.com/nesteruk.org/pix/0/9218131b-e12b-4044-a725-f4e63a213ff5.jpg" class="alignright" align="right" alt=""/><br />
Иначе как «вынос мозга» эту книжку не обозвать. MVC in Action &ndash; это книга по Asp.Net MVC для тех кто уже похоже все знает но хочет проверить свои знания и заодно получить дозу зубодробильной информации от настоящих гуру в этом деле. Написало ее целых 5 авторов (все MVP), и они за словом в карман не лезут &ndash; тут у них и <a rel="nofollow" target="_blank" href="http://mvccontrib.codeplex.com/" title="http://mvccontrib.codeplex.com/">MvcContrib</a> и <a rel="nofollow" target="_blank" href="http://www.ayende.com/projects/rhino-mocks.aspx" title="http://www.ayende.com/projects/rhino-mocks.aspx">Rhino.Mocks</a> и другие прелести.
</p>
<p>На самом деле &ndash; первая часть книги это еще цветочки &ndash; ее хоть как-то можно читать новичкам. А вот начиная со 2й части уже становится значительно сложнее, т.к. без хорошего багажа знаний современный паттернов и практик во всем написанном вполне реально утонуть. Тут, кстати, фигурирут такие вещи как <a rel="nofollow" target="_blank" href="http://en.wikipedia.org/wiki/Domain-driven_design" title="http://en.wikipedia.org/wiki/Domain-driven_design">DDD</a> и такие технологии как <a rel="nofollow" target="_blank" href="http://sparkviewengine.com/" title="http://sparkviewengine.com/">Spark</a>. (Это кстате в каком-то смысле минус т.к. большинство людей сейчас скорее интересует Razor.) В трерьей части книги появляются такие вещи как AutoMapper и NHibernate (опять же, все преподнесено на хорошем, <em><font face="Candara">презентабельном</font></em> уровне). Ну и в последней главе, уже в разбивку, показаны разные многофункциональные прелести. В одной из глав, правда, приведен пример того, как написать autocomplete text-box, что немножко выбивает из ритма.</p>
<p>Если резюмировать &ndash; хорошая, компактная но полная актуальной информации «от станка» книжка. Подойдет для тех кто уже начал писать на MVC и теперь хочет сделать что-то серьезное. Рекоммендую!</p>
<p><img src="https://i1.wp.com/nesteruk.org/pix/star.gif" style="border:0;margin:0;padding:0;" alt="4 stars"/><img src="https://i1.wp.com/nesteruk.org/pix/star.gif" style="border:0;margin:0;padding:0;" alt="4 stars"/><img src="https://i1.wp.com/nesteruk.org/pix/star.gif" style="border:0;margin:0;padding:0;" alt="4 stars"/><img src="https://i1.wp.com/nesteruk.org/pix/star.gif" style="border:0;margin:0;padding:0;" alt="4 stars"/><img src="https://i2.wp.com/nesteruk.org/pix/star-half.gif" style="border:0;margin:0;padding:0;" alt="4 stars"/></p>
<h3>C# in Depth</h3>
<p><img src="https://i1.wp.com/nesteruk.org/pix/0/fae964fd-7ba0-4af9-8d13-e9dd180637a4.jpg" class="alignright" align="right" alt=""/>Несмотря на то, что у меня есть свои фавориты в плане книжек по C#, я счел своим долгом прочитать именно эту &ndash; ведь её автором является не кто-то там, а сам Джон «Чак Норрис» Скит. Для тех из вас кто живет на другой планете, мистер Скит является <a rel="nofollow" target="_blank" href="http://stackoverflow.com/users/22656/jon-skeet" title="http://stackoverflow.com/users/22656/jon-skeet">звездой портала StackOverflow</a> и одним из ведущих экспертов по C# (а также по Java, на которой он пишет в Google, хотя подозреваю что его интерес к этому языку несколько меньше по весьма понятным причинам).</p>
<p>Итак, если коротко &ndash; то C# in Depth (я читал первую версию, сейчас <a rel="nofollow" target="_blank" href="http://www.manning.com/skeet2/" title="http://www.manning.com/skeet2/">есть вторая</a>) &ndash; это <em><font face="Candara">просто конфетка</font></em>. Для человека который хочет узнать что такое C# (например, если вы пришли к нему из мира Java или C++), эта книга &ndash; манна небесная. Написана она очень хорошо &ndash; в очередной раз подтверждает что мы британцы в принципе неплохо пишем :)</p>
<p>Книга, как вы догадались, является хрестоматией C# разработки, начиная от азов и кончая такими вещами как Linq. Читается она очень легко, без WTF-моментов. Скит пишет в очень неформальной манере, завлекая читателя в интересные тонкости языка. Я читал много книг по C#, но такой дозы позитива я до этого не находил нигде. Мне кажется, что эта книга формирует неплохой «двойной удар» с книжкой C# in a Nutshell (о книгах O&rsquo;Reilly мы еще поговорим) &ndash; ведь первая объясняет что это за язык такой, а вторая описывает библиотеки классов.</p>
<p>Вообщем, впечатление осталось очень позитивное, поэтому C# in Depth получает твердую пятерку как за стиль так и за содержание.</p>
<p><img src="https://i1.wp.com/nesteruk.org/pix/star.gif" style="border:0;margin:0;padding:0;" alt="5 stars"/><img src="https://i1.wp.com/nesteruk.org/pix/star.gif" style="border:0;margin:0;padding:0;" alt="5 stars"/><img src="https://i1.wp.com/nesteruk.org/pix/star.gif" style="border:0;margin:0;padding:0;" alt="5 stars"/><img src="https://i1.wp.com/nesteruk.org/pix/star.gif" style="border:0;margin:0;padding:0;" alt="5 stars"/><img src="https://i1.wp.com/nesteruk.org/pix/star.gif" style="border:0;margin:0;padding:0;" alt="5 stars"/></p>
<h3>Real-World Functional Programming</h3>
<p><img src="https://i2.wp.com/nesteruk.org/pix/0/a1d34557-7c01-4c22-99f5-76fefd59d2d5.jpg" class="alignright" align="right" alt=""/>После того как я опубликовал отзывы по книге Expert F#, коллеги подсказали что неплохо было бы мне было посмотреть и на эту книгу, благо не всем хочется пролистывать дорогой (одна из самых дорогих книг) талмуд на тему F#. Также, стимулировали к прочтению этой книги две вещи &ndash; то что книжка покрывает не только F# но и C#, а также (drumroll please) то что и к этой книге приложил руку сам Джон Скит (хотя основной автор &ndash; Томаш Петричек). Сорри если кого-то этот мем начал раздражать &ndash; я не нарочно.</p>
<p>Итак, R-WFP &ndash; это книжка про «бытовое» функциональное программирование без высоко поднятого носа сообществ языка Haskell, Lisp или каких-то еще &ndash; это, в очередной раз, <em><font face="Candara">прагматика</font></em> и лично мне это очень нравится. (Собственно термин &lsquo;Real-World&rsquo; в названии как бы намекает&hellip;) Первое что пришло мне в голову &ndash; они украли у меня идею функциональной анимации! Я недавно на эту тему <a rel="nofollow" target="_blank" href="http://habrahabr.ru/blogs/net/57236/" title="http://habrahabr.ru/blogs/net/57236/">статью писал</a>, она даже <a rel="nofollow" target="_blank" href="http://www.codeproject.com/KB/dotnet/lambdawpf.aspx" title="http://www.codeproject.com/KB/dotnet/lambdawpf.aspx">на CP приз выиграла</a>. Впрочем, очень приятно что авторы пишут про знакомые мне идеи. Также приятно что не остались за бортом и другие языки программирования &ndash; такие как Lisp и Erlang. Понятное дело что мы тут про .Net говорим, но наше сообщество порой страдает узким мировозрением по отношению к другим платформам.</p>
<p>Книга, точно так же как и C# in Depth, делает плавную прогрессию от азов (например, от рассказов про то что такое кортежи или списки &ndash; это ведь нужно для понимания F#) и прогрессируя до таких вещей как применение функций высокого порядка. Вообще что меня поразило, так это широта задач, которые покрывает эта книга &ndash; тут и анимация, и создание DSLей (я правда и сам писал про DSLи на F#) и реактивное программирование. Правда тут есть один весьма существенный (с моей точки зрения) минус &ndash; поскольку книга была опубликована в декабре 2009, в книге не слова на тему Reactive Extensions. <em><font face="Candara">Обидно!</font></em> Ведь не знаю как вам, а лично мне очень хотелось бы иметь описание тех новых структур и опереторов, которые там фигурируют, а также четкое руководство к использованию. Хоть я и сам, в принципе, понимаю что и как.</p>
<p>Скажу честно, книга мне понравилась &ndash; в ней нашлось предостаточно моментов (особенно по F#, где мои знания на «четыре с минусом») которые меня удивили и заставили пересмотреть то как я пишу код. Другое дело что у меня очень мало F# «в продашкн», но это уже чисто мои проблемы.</p>
<p><img src="https://i1.wp.com/nesteruk.org/pix/star.gif" style="border:0;margin:0;padding:0;" alt="4 stars"/><img src="https://i1.wp.com/nesteruk.org/pix/star.gif" style="border:0;margin:0;padding:0;" alt="4 stars"/><img src="https://i1.wp.com/nesteruk.org/pix/star.gif" style="border:0;margin:0;padding:0;" alt="4 stars"/><img src="https://i1.wp.com/nesteruk.org/pix/star.gif" style="border:0;margin:0;padding:0;" alt="4 stars"/><img src="https://i1.wp.com/nesteruk.org/pix/star-none.gif" style="border:0;margin:0;padding:0;" alt="4 stars"/></p><br />Filed under: <a rel="nofollow" target="_blank" href='https://nesteruk.wordpress.com/category/net/'>.NET</a>, <a rel="nofollow" target="_blank" href='https://nesteruk.wordpress.com/category/books/'>Books</a>, <a rel="nofollow" target="_blank" href='https://nesteruk.wordpress.com/category/c/'>C#</a>, <a rel="nofollow" target="_blank" href='https://nesteruk.wordpress.com/category/net/f/'>f#</a>  <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gocomments/nesteruk.wordpress.com/563/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/nesteruk.wordpress.com/563/"/></a> <img alt="" border="0" src="https://pixel.wp.com/b.gif?host=nesteruk.wordpress.com&#038;blog=373435&#038;post=563&#038;subd=nesteruk&#038;ref=&#038;feed=1" width="1" height="1"/>]]></content:encoded>
         <media:content medium="image" url="https://0.gravatar.com/avatar/f01cbd2238e2a78e4c43fa596f51d6a1?s=96&amp;amp;d=https%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&amp;amp;r=PG">
            <media:title type="html">nesteruk</media:title>
         </media:content>
         <media:content medium="image" url="http://nesteruk.org/pix/0/de713ad9-ee79-44d6-83dc-af770df02bca.jpg"/>
         <media:content medium="image" url="http://nesteruk.org/pix/0/ed1384b6-bd51-46d8-86e2-ca04ed6e134a.jpg"/>
         <media:content medium="image" url="http://nesteruk.org/pix/star.gif">
            <media:title type="html">1 stars</media:title>
         </media:content>
         <media:content medium="image" url="http://nesteruk.org/pix/star-none.gif">
            <media:title type="html">1 stars</media:title>
         </media:content>
         <media:content medium="image" url="http://nesteruk.org/pix/star-none.gif">
            <media:title type="html">1 stars</media:title>
         </media:content>
         <media:content medium="image" url="http://nesteruk.org/pix/star-none.gif">
            <media:title type="html">1 stars</media:title>
         </media:content>
         <media:content medium="image" url="http://nesteruk.org/pix/star-none.gif">
            <media:title type="html">1 stars</media:title>
         </media:content>
         <media:content medium="image" url="http://nesteruk.org/pix/0/9218131b-e12b-4044-a725-f4e63a213ff5.jpg"/>
         <media:content medium="image" url="http://nesteruk.org/pix/star.gif">
            <media:title type="html">4 stars</media:title>
         </media:content>
         <media:content medium="image" url="http://nesteruk.org/pix/star.gif">
            <media:title type="html">4 stars</media:title>
         </media:content>
         <media:content medium="image" url="http://nesteruk.org/pix/star.gif">
            <media:title type="html">4 stars</media:title>
         </media:content>
         <media:content medium="image" url="http://nesteruk.org/pix/star.gif">
            <media:title type="html">4 stars</media:title>
         </media:content>
         <media:content medium="image" url="http://nesteruk.org/pix/star-half.gif">
            <media:title type="html">4 stars</media:title>
         </media:content>
         <media:content medium="image" url="http://nesteruk.org/pix/0/fae964fd-7ba0-4af9-8d13-e9dd180637a4.jpg"/>
         <media:content medium="image" url="http://nesteruk.org/pix/star.gif">
            <media:title type="html">5 stars</media:title>
         </media:content>
         <media:content medium="image" url="http://nesteruk.org/pix/star.gif">
            <media:title type="html">5 stars</media:title>
         </media:content>
         <media:content medium="image" url="http://nesteruk.org/pix/star.gif">
            <media:title type="html">5 stars</media:title>
         </media:content>
         <media:content medium="image" url="http://nesteruk.org/pix/star.gif">
            <media:title type="html">5 stars</media:title>
         </media:content>
         <media:content medium="image" url="http://nesteruk.org/pix/star.gif">
            <media:title type="html">5 stars</media:title>
         </media:content>
         <media:content medium="image" url="http://nesteruk.org/pix/0/a1d34557-7c01-4c22-99f5-76fefd59d2d5.jpg"/>
         <media:content medium="image" url="http://nesteruk.org/pix/star.gif">
            <media:title type="html">4 stars</media:title>
         </media:content>
         <media:content medium="image" url="http://nesteruk.org/pix/star.gif">
            <media:title type="html">4 stars</media:title>
         </media:content>
         <media:content medium="image" url="http://nesteruk.org/pix/star.gif">
            <media:title type="html">4 stars</media:title>
         </media:content>
         <media:content medium="image" url="http://nesteruk.org/pix/star.gif">
            <media:title type="html">4 stars</media:title>
         </media:content>
         <media:content medium="image" url="http://nesteruk.org/pix/star-none.gif">
            <media:title type="html">4 stars</media:title>
         </media:content>
      </item>
      <item>
         <title>Циклы на F#</title>
         <link>http://norgblog.blogspot.com/2010/08/f_27.html</link>
         <description>Сейчас попытался реализовать довольно тривиальный цикл, который на C++ выглядел бы следующим образом:

while(true)
{
    string buf = &quot;&quot;;
    cout &amp;lt;&amp;lt; &quot;write string(Y/N): &quot;;
    cin &amp;gt;&amp;gt; buf;
    if(buf == &quot;Y&quot;) return true;
    if(buf == &quot;N&quot;) return false;
}
довольно тривиальная весчь, заставляющая ввести либо Y, либо N.
но вот на F# возникли некоторые проблемы(предположительно из-за того, что</description>
         <author>Максим Карандашов</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-5219626453078054207.post-4398412398431194305</guid>
         <pubDate>Fri, 27 Aug 2010 10:16:00 +0000</pubDate>
      </item>
      <item>
         <title>Кілбасы, пальцам пханыя</title>
         <link>http://metaclass.livejournal.com/525945.html</link>
         <description>200 килобайт кода (5000 строк) на F# из модели, содержащей 81(типы)+44(таблицы)+276(поля) записей в БД генерит 1.1 мегабайта sql+xml+C# (22 тысяч строк).&lt;br /&gt;&lt;br /&gt; Что меня в моем стиле писанины на F# немного напрягает, так это постоянно получающиеся в исходниках строки по 100-150 символов, т.к. на широкоэкранном монике они не мешают, а получающиеся методы сильно читабельнее, т.к. в основном весь смысл строки где-нибудь в начале (&quot;какой ADT создаем&quot;) а дальше идут только параметры. &lt;br /&gt;&lt;br /&gt; И вот с этими параметрами такая длина и вылазит - осмысленный набор конструкторов данных для половины ADT содержит что-то вроде None, из-за чего эти None путаются между собой и стандартным  типом Option (он же - Maybe, т.е. Option.None == Nothing) и для них приходится явно указывать префиксы имени типа (ReadOnlyFieldModifier.None, CSharpVisibility.None, CSharpModifier.None). Сокращать имена типов не хочу, они осмысленные, Можно было бы добавить коротенькие префиксы прямо в имена конструкторов данных, тогда можно было бы обойтись без явного указания имени типа. &lt;br /&gt;&lt;br /&gt; Еще было бы неплохо поиметь &quot;параметры по умолчанию&quot;, типа вместо параметра пишешь _, а компилятор подставляет то, что мы указали дефолтным где-нибудь в описании функции или конструктора. При небольшом количестве параметров это лечится функциями - умными конструкторами, а при большом задолбаться перебирать комбинации.</description>
         <guid isPermaLink="false">urn:lj:livejournal.com:atom1:metaclass:525945</guid>
         <pubDate>Tue, 24 Aug 2010 07:09:16 +0000</pubDate>
      </item>
      <item>
         <title>Внимание, системы типов и базы данных - срач</title>
         <link>http://metaclass.livejournal.com/522446.html</link>
         <description>&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://109.livejournal.com/539588.html&quot;&gt;Спор про F#&lt;/a&gt; (там рекаптча если шо)&lt;br /&gt;&lt;br /&gt; Товарищ прицепился к тому, что в F# нельзя написать функцию, которая бы по индексу поля в кортеже возвращала бы значение поля.&lt;br /&gt;&lt;br /&gt; Т.е. вообще-то ее написать можно, через Reflection, но 1) это все только благодаря дотнету, но никак не системе типов; 2) это противоречит духу статической типизации и является способом стрелять себе в ногу.&lt;br /&gt;&lt;br /&gt; Никак не могу человеку объяснить разницу между статической типизацией и &lt;s&gt;натягиванием совы на глобус&lt;/s&gt; реализацией динамической типизации поверх языка со статической, чем занимаются 90% либ доступа к БД (все эти ADO.NET, ODBC, JDBC, BDE и прочая).</description>
         <guid isPermaLink="false">urn:lj:livejournal.com:atom1:metaclass:522446</guid>
         <pubDate>Fri, 20 Aug 2010 08:15:42 +0000</pubDate>
      </item>
      <item>
         <title>F#, первое знакомство</title>
         <link>http://norgblog.blogspot.com/2010/08/f.html</link>
         <description>F# - это функциональный язык разработанный в M$ под платформу .Net, близкий родственник Haskell.

Первые ощущения от языка - странно.
Оч. похоже на Haskell и Python на первый взгляд. Сразу бросается в глаза использование отступов для различения блоков кода, но это есть гуд кстати(есть и в питоне и в хаскеле).
Потом... функцию main можно определить следующим образом:
let main ( _ ) =
    ...
ну</description>
         <author>Максим Карандашов</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-5219626453078054207.post-6766124222560195369</guid>
         <pubDate>Wed, 18 Aug 2010 13:53:00 +0000</pubDate>
      </item>
      <item>
         <title>&quot;Асинхронные&quot; продолжения</title>
         <link>http://dsorokin.blogspot.com/2010/08/blog-post.html</link>
         <description>Сегодня осознал одну замечательную вещь. Оказывается, что в F# можно использовать async workflow вместо продолжений… Фактически, async состоит из трех продолжений: основной ветки вычислений, обработки ошибок и экстренной отмены вычислений. Все это разные продолжения под куполом единого значения в монаде Async.&lt;br /&gt;&lt;br /&gt;Вот, пример примитивного вычисления функции Аккермана с кешированием промежуточных результатов:&lt;br /&gt;&lt;pre style=&quot;background:#ffffff;color:#000000;&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#800000;&quot;&gt;open&lt;/span&gt; System&lt;span style=&quot;color:#008c00;&quot;&gt;.&lt;/span&gt;Collections&lt;span style=&quot;color:#008c00;&quot;&gt;.&lt;/span&gt;Generic&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight:bold;color:#800000;&quot;&gt;let&lt;/span&gt; ackermann m n &lt;span style=&quot;color:#808030;&quot;&gt;=&lt;/span&gt;&lt;br /&gt;   &lt;span style=&quot;font-weight:bold;color:#800000;&quot;&gt;let&lt;/span&gt; dict &lt;span style=&quot;color:#808030;&quot;&gt;=&lt;/span&gt; Dictionary&lt;span style=&quot;color:#808030;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#008c00;&quot;&gt;_&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;,&lt;/span&gt; &lt;span style=&quot;color:#008c00;&quot;&gt;_&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&quot;color:#808030;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;   &lt;span style=&quot;font-weight:bold;color:#800000;&quot;&gt;let&lt;/span&gt; fix m n x &lt;span style=&quot;color:#808030;&quot;&gt;=&lt;/span&gt; async &lt;span style=&quot;color:#808030;&quot;&gt;{&lt;/span&gt;&lt;br /&gt;       &lt;span style=&quot;font-weight:bold;color:#800000;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;!&lt;/span&gt; a &lt;span style=&quot;color:#808030;&quot;&gt;=&lt;/span&gt; x&lt;br /&gt;       dict&lt;span style=&quot;color:#008c00;&quot;&gt;.&lt;/span&gt;Add &lt;span style=&quot;color:#808030;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;(&lt;/span&gt;m&lt;span style=&quot;color:#808030;&quot;&gt;,&lt;/span&gt; n&lt;span style=&quot;color:#808030;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;,&lt;/span&gt; a&lt;span style=&quot;color:#808030;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;       return&lt;span style=&quot;color:#808030;&quot;&gt;!&lt;/span&gt; x&lt;br /&gt;   &lt;span style=&quot;color:#808030;&quot;&gt;}&lt;/span&gt;&lt;br /&gt;   &lt;span style=&quot;font-weight:bold;color:#800000;&quot;&gt;let&lt;/span&gt; &lt;span style=&quot;font-weight:bold;color:#800000;&quot;&gt;rec&lt;/span&gt; ack m n &lt;span style=&quot;color:#808030;&quot;&gt;=&lt;/span&gt; async &lt;span style=&quot;color:#808030;&quot;&gt;{&lt;/span&gt;&lt;br /&gt;       &lt;span style=&quot;font-weight:bold;color:#800000;&quot;&gt;if&lt;/span&gt; m &lt;span style=&quot;color:#808030;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color:#008c00;&quot;&gt;0&lt;/span&gt; &lt;span style=&quot;font-weight:bold;color:#800000;&quot;&gt;then&lt;/span&gt;&lt;br /&gt;           return n &lt;span style=&quot;color:#808030;&quot;&gt;+&lt;/span&gt; &lt;span style=&quot;color:#008c00;&quot;&gt;1&lt;/span&gt;&lt;br /&gt;       elif dict&lt;span style=&quot;color:#008c00;&quot;&gt;.&lt;/span&gt;ContainsKey &lt;span style=&quot;color:#808030;&quot;&gt;(&lt;/span&gt;m&lt;span style=&quot;color:#808030;&quot;&gt;,&lt;/span&gt; n&lt;span style=&quot;color:#808030;&quot;&gt;)&lt;/span&gt; &lt;span style=&quot;font-weight:bold;color:#800000;&quot;&gt;then&lt;/span&gt;&lt;br /&gt;           return dict.&lt;span style=&quot;color:#808030;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;(&lt;/span&gt;m&lt;span style=&quot;color:#808030;&quot;&gt;,&lt;/span&gt; n&lt;span style=&quot;color:#808030;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;]&lt;/span&gt;&lt;br /&gt;       elif n &lt;span style=&quot;color:#808030;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color:#008c00;&quot;&gt;0&lt;/span&gt; &lt;span style=&quot;font-weight:bold;color:#800000;&quot;&gt;then&lt;/span&gt;&lt;br /&gt;           return&lt;span style=&quot;color:#808030;&quot;&gt;!&lt;/span&gt; fix m n &lt;span style=&quot;color:#808030;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;|&lt;/span&gt; ack &lt;span style=&quot;color:#808030;&quot;&gt;(&lt;/span&gt;m &lt;span style=&quot;color:#808030;&quot;&gt;-&lt;/span&gt; &lt;span style=&quot;color:#008c00;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;)&lt;/span&gt; &lt;span style=&quot;color:#008c00;&quot;&gt;1&lt;/span&gt;&lt;br /&gt;       &lt;span style=&quot;font-weight:bold;color:#800000;&quot;&gt;else&lt;/span&gt;&lt;br /&gt;           &lt;span style=&quot;font-weight:bold;color:#800000;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;!&lt;/span&gt; x &lt;span style=&quot;color:#808030;&quot;&gt;=&lt;/span&gt; ack m &lt;span style=&quot;color:#808030;&quot;&gt;(&lt;/span&gt;n &lt;span style=&quot;color:#808030;&quot;&gt;-&lt;/span&gt; &lt;span style=&quot;color:#008c00;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;           return&lt;span style=&quot;color:#808030;&quot;&gt;!&lt;/span&gt; fix m n &lt;span style=&quot;color:#808030;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;|&lt;/span&gt; ack &lt;span style=&quot;color:#808030;&quot;&gt;(&lt;/span&gt;m &lt;span style=&quot;color:#808030;&quot;&gt;-&lt;/span&gt; &lt;span style=&quot;color:#008c00;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;)&lt;/span&gt; x&lt;br /&gt;   &lt;span style=&quot;color:#808030;&quot;&gt;}&lt;/span&gt;&lt;br /&gt;   ack m n&lt;br /&gt;&lt;/pre&gt;А это результат работы:&lt;br /&gt;&lt;pre style=&quot;background:#ffffff;color:#000000;&quot;&gt;&lt;span style=&quot;color:#808030;&quot;&gt;&amp;gt;&lt;/span&gt; ackermann &lt;span style=&quot;color:#008c00;&quot;&gt;3&lt;/span&gt; &lt;span style=&quot;color:#008c00;&quot;&gt;19&lt;/span&gt; &lt;span style=&quot;color:#808030;&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;&amp;gt;&lt;/span&gt; Async&lt;span style=&quot;color:#008c00;&quot;&gt;.&lt;/span&gt;RunSynchronously&lt;span style=&quot;color:#808030;&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;Real&lt;span style=&quot;color:#808030;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color:#008c00;&quot;&gt;00&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#008c00;&quot;&gt;01&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#008c00;&quot;&gt;15&lt;/span&gt;&lt;span style=&quot;color:#008c00;&quot;&gt;.849&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;,&lt;/span&gt; CPU&lt;span style=&quot;color:#808030;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color:#008c00;&quot;&gt;00&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#008c00;&quot;&gt;01&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#008c00;&quot;&gt;15&lt;/span&gt;&lt;span style=&quot;color:#008c00;&quot;&gt;.816&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;,&lt;/span&gt; GC gen0&lt;span style=&quot;color:#808030;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color:#008c00;&quot;&gt;1398&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;,&lt;/span&gt; gen1&lt;span style=&quot;color:#808030;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color:#008c00;&quot;&gt;515&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;,&lt;/span&gt; gen2&lt;span style=&quot;color:#808030;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color:#008c00;&quot;&gt;7&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-weight:bold;color:#800000;&quot;&gt;val&lt;/span&gt; it &lt;span style=&quot;color:#808030;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;font-weight:bold;color:#800000;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color:#808030;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color:#008c00;&quot;&gt;4194301&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;Без продолжений был бы явный StackOverflowException при гораздо меньших значениях n и m.</description>
         <author>dsorokin</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-8641042312683198534.post-1622464491162012714</guid>
         <pubDate>Fri, 13 Aug 2010 19:10:00 +0000</pubDate>
      </item>
      <item>
         <title>Разбор XML на F# с помощью комбинаторов</title>
         <link>http://dsorokin.blogspot.com/2010/08/xml-f.html</link>
         <description>Возникла задача разбора потока данных XML, выдаваемых стандартным дотнетовским парсером XmlReader. Раньше я много раз это проделывал на C#, но часто приходилось создавать много дополнительных методов для обработки вложенных тегов XML. Код неприлично разрастался. Теперь захотелось выразительности и декларативности, чтобы разбор сводился к заданию структуры тегов с вкраплениями кода для сбора данных. Получилась представленная ниже крошечная библиотека, идейно близкая к парсер-комбинаторам.&lt;br /&gt;&lt;br /&gt;Итак, входной поток задается объектом-значением XmlReader. Неприятность в том, что этот объект несет в себе изменяемое состояние. Это ограничивает наши возможности по разбору. Вероятно, об откатах придется забыть.&lt;br /&gt;&lt;br /&gt;Представим наш парсер в виде функции, которая по заданному объекту XmlReader возвращает прочитанные данные в случае успеха, либо сигнализирует о неудаче.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;namespace Maritegra.Xml&lt;br /&gt;&lt;br /&gt;open System.Xml&lt;br /&gt;&lt;br /&gt;type XmlReader&amp;lt;'a&amp;gt; = XmlReader -&amp;gt; 'a option&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Нужно поставить сразу условие. Если мы изменяем состояние объекта XmlReader, то тогда должны вернуть Some, т.е. успех. Наоборот, если функция парсера возвращает None, то тогда гарантируется, что состояние XmlReader не претерпело изменений. Следование этому условию делает разбор надежным, но заметно ограничивает наши возможности. Справедливый обмен.&lt;br /&gt;&lt;br /&gt;В определении полиморфного типа XmlReader&amp;lt;’a&amp;gt; использована такая особенность дотнета, которая разделяет одноименные типы по параметрам. То есть, введенный тип XmlReader&amp;lt;’a&amp;gt; и стандартный тип XmlReader из System.Xml – это два разных типа. Далее полиморфный тип XmlReader&amp;lt;’a&amp;gt; я буду называть парсером, а, говоря о стандартном типе XmlReader, буду просто использовать его название.&lt;br /&gt;&lt;br /&gt;Если сравнивать с другими парсерами, то введенный отличается тем, что аргумент функции, т.е. объект XmlReader, имеет состояние, а потому возвращать как результат его ненужно. Отсюда же возникает наложенное выше условие. В большинстве случаев мы не можем просто так прикоснуться к объекту XmlReader, не изменив его.&lt;br /&gt;&lt;br /&gt;Ближе к делу. Очевидно, что парсер XmlReader&amp;lt;’a&amp;gt; является монадой. Сильно не буду углубляться в эту тему. Лишь приведу необходимые определения.&lt;br /&gt;&lt;br /&gt;Вот, основные монадические функции, скрытые внутри отдельного модуля (новый F# обычно не позволяет определять глобальные функции вне модулей):&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;module XmlReaderImpl =&lt;br /&gt;&lt;br /&gt;    let returnXR a = fun (r: XmlReader) -&amp;gt; Some a&lt;br /&gt;    let bindXR m k = fun (r: XmlReader) -&amp;gt; match m r with | Some a -&amp;gt; (k a) r | None -&amp;gt; None&lt;br /&gt;    let delayXR k  = fun (r: XmlReader) -&amp;gt; (k ()) r&lt;br /&gt;    let zeroXR     = fun (r: XmlReader) -&amp;gt; Some ()&lt;br /&gt;    let combineXR m1 m2 = fun (r: XmlReader) -&amp;gt; match m1 r with | Some () -&amp;gt; m2 r | None -&amp;gt; None&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Теперь для монады нужен построитель, тип которого задается очень просто:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;open XmlReaderImpl&lt;br /&gt;&lt;br /&gt;type XmlReaderBuilder () =&lt;br /&gt;&lt;br /&gt;    member x.Return (a)  = returnXR a&lt;br /&gt;    member x.Bind (m, k) = bindXR m k&lt;br /&gt;    member x.Delay (k)   = delayXR (k: unit -&amp;gt; XmlReader&amp;lt;'a&amp;gt;)&lt;br /&gt;    member x.Zero ()     = zeroXR&lt;br /&gt;    member x.Combine (m1, m2) = combineXR m1 m2&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Завершающее определение построителя монады xmlreader:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;[&amp;lt;AutoOpen&amp;gt;]&lt;br /&gt;module XmlReaderWorkflow =&lt;br /&gt;&lt;br /&gt;    let xmlreader = XmlReaderBuilder ()&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Атрибут AutoOpen автоматически делает доступным определение построителя.&lt;br /&gt;&lt;br /&gt;Сейчас создадим еще один XmlReader, но уже модуль. Язык F# превосходно справляется с таким смешением имен, но для этого модуль нужно снабдить следующим длинным атрибутом CompilationRepresentation (CompilationRepresentationFlags.ModuleSuffix). Поместим в этот модуль функции запуска run и отображения map. В комментариях указана сигнатура функций. Кроме того, модуль снабдим атрибутом RequireQualifiedAccess, который указывает на обязательность имени модуля при обращении к функциям.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;[&amp;lt;RequireQualifiedAccess&amp;gt;]&lt;br /&gt;[&amp;lt;CompilationRepresentation (CompilationRepresentationFlags.ModuleSuffix)&amp;gt;]&lt;br /&gt;module XmlReader =&lt;br /&gt;&lt;br /&gt;    // val run: XmlReader -&amp;gt; XmlReader&amp;lt;'a&amp;gt; -&amp;gt; 'a&lt;br /&gt;    let run (r: XmlReader) m = &lt;br /&gt;        match m r with&lt;br /&gt;        | Some a -&amp;gt; a&lt;br /&gt;        | None -&amp;gt; failwithf &quot;Invalid input data&quot;&lt;br /&gt;&lt;br /&gt;    // val map: ('a -&amp;gt; 'b) -&amp;gt; XmlReader&amp;lt;'a&amp;gt; -&amp;gt; XmlReader&amp;lt;'b&amp;gt;&lt;br /&gt;    let map f m = fun (r: XmlReader) -&amp;gt;&lt;br /&gt;        match m r with&lt;br /&gt;        | Some a -&amp;gt; Some (f a)&lt;br /&gt;        | None -&amp;gt; None&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Все это следует из самого определения монады. До функций разбора дело пока не дошло. Они приведены ниже. Я также сделаю их частью определения модуля XmlReader. Поэтому код можно копировать с сохранением порядка и отступов.&lt;br /&gt;&lt;br /&gt;Начнем с простых комбинаторов, которые извлекают информацию об атрибутах. Они безболезненны и не меняют состояние объекта XmlReader. По заданному имени или порядковому номеру получаем значение атрибута, обернутое в монаду:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    // val attr: string -&amp;gt; XmlReader&amp;lt;string&amp;gt;&lt;br /&gt;    let attr (name: string) = fun (r: XmlReader) -&amp;gt; Some &amp;lt;| r.GetAttribute (name)&lt;br /&gt;&lt;br /&gt;    // val attri: int -&amp;gt; XmlReader&amp;lt;string&amp;gt;&lt;br /&gt;    let attri (i: int) = fun (r: XmlReader) -&amp;gt; Some &amp;lt;| r.GetAttribute (i)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Для извлечения текста можно использовать следующий простой комбинатор, который уже меняет состояние XmlReader:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    // val text: XmlReader&amp;lt;string&amp;gt;&lt;br /&gt;    let text = fun (r: XmlReader) -&amp;gt; Some &amp;lt;| r.ReadElementContentAsString ()&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Более сложный случай – это разбор элемента. Комбинатор elem разбирает элемент с заданным именем, применяя для содержимого другой парсер. Если элемент не тот, то, не меняя состояния XmlReader, сразу возвращается None, как и было оговорено в изначальном условии, накладываемом на парсер.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    // val elem: string -&amp;gt; XmlReader&amp;lt;'a&amp;gt; -&amp;gt; XmlReader&amp;lt;'a&amp;gt;&lt;br /&gt;    let elem (name: string) m = fun (r: XmlReader) -&amp;gt;&lt;br /&gt;        if r.IsStartElement (name) then m r else None&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Теперь нужны комбинаторы для разбора внутренних тегов. Таких комбинаторов два. Первый рассчитывает на императивную обработку содержимого – он является основным. Второй же больше соответствует функциональной парадигме. Устроены оба комбинатора одинаково.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    // val contents: XmlReader&amp;lt;unit&amp;gt; -&amp;gt; XmlReader&amp;lt;unit&amp;gt;&lt;br /&gt;    let contents (m: XmlReader&amp;lt;unit&amp;gt;) = fun (r: XmlReader) -&amp;gt;&lt;br /&gt;        if r.IsStartElement () then&lt;br /&gt;            if not r.IsEmptyElement then&lt;br /&gt;                let depth = r.Depth&lt;br /&gt;                while r.Read () &amp;&amp; (r.Depth &amp;gt; depth) do&lt;br /&gt;                    if (r.Depth = 1 + depth) then &lt;br /&gt;                        m r |&amp;gt; ignore&lt;br /&gt;            Some ()&lt;br /&gt;        else&lt;br /&gt;            None&lt;br /&gt;            &lt;br /&gt;    // val selectContents: XmlReader&amp;lt;'a&amp;gt; -&amp;gt; XmlReader&amp;lt;'a list&amp;gt;&lt;br /&gt;    let selectContents (m: XmlReader&amp;lt;_&amp;gt;) = fun (r: XmlReader) -&amp;gt;&lt;br /&gt;        if r.IsStartElement () then&lt;br /&gt;            [ if not r.IsEmptyElement then&lt;br /&gt;                let depth = r.Depth&lt;br /&gt;                while r.Read () &amp;&amp; (r.Depth &amp;gt; depth) do&lt;br /&gt;                if (r.Depth = 1 + depth) then&lt;br /&gt;                    match m r with&lt;br /&gt;                    | Some a -&amp;gt; yield a&lt;br /&gt;                    | None -&amp;gt; ()&lt;br /&gt;            ] |&amp;gt; Some&lt;br /&gt;        else None&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Комбинатор contents применяет заданный парсер ко всем внутренним тегам, чья глубина вложенности меньше на единицу. Второй комбинатор делает то же самое, но при этом извлекает полезную информацию.&lt;br /&gt;&lt;br /&gt;На этом определение модуля XmlReader закончено. Теперь в отдельном модуле введем вспомогательный бинарный оператор (+++), который бы объединял два заданных парсера, пытаясь сначала применить первый, а затем второй в случае неудачи.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;module Operators =&lt;br /&gt;&lt;br /&gt;    // val (+++): XmlReader&amp;lt;'a&amp;gt; -&amp;gt; XmlReader&amp;lt;'a&amp;gt; -&amp;gt; XmlReader&amp;lt;'a&amp;gt;&lt;br /&gt;    let (+++) m1 m2 = fun (r: XmlReader) -&amp;gt;&lt;br /&gt;        match m1 r with&lt;br /&gt;        | Some a as n -&amp;gt; n&lt;br /&gt;        | None -&amp;gt; m2 r&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Библиотека закончена. Она содержится в пространстве имен Maritegra.Xml. &lt;br /&gt;&lt;br /&gt;Перейдем к скриптованию и тестированию. В режиме скрипта мы уже можем определять глобальные функции и данные. В качестве исходных данных возьмем следующий кусок XML:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let document = &lt;br /&gt;    @&quot;&amp;lt;struct&amp;gt;&lt;br /&gt;        &amp;lt;items&amp;gt;&lt;br /&gt;           &amp;lt;item id='1001' x='1'&amp;gt;10&amp;lt;/item&amp;gt;&lt;br /&gt;           &amp;lt;item id='1002' x='2'&amp;gt;20&amp;lt;/item&amp;gt;&lt;br /&gt;           &amp;lt;item id='1003' x='3'&amp;gt;30&amp;lt;/item&amp;gt;&lt;br /&gt;        &amp;lt;/items&amp;gt;&lt;br /&gt;        &amp;lt;links&amp;gt;&lt;br /&gt;           &amp;lt;link source-id='1001' target-id='1003'&amp;gt;PuperLink&amp;lt;/link&amp;gt;&lt;br /&gt;           &amp;lt;link source-id='1001' target-id='1002'&amp;gt;WeakLink&amp;lt;/link&amp;gt;&lt;br /&gt;        &amp;lt;/links&amp;gt;&lt;br /&gt;      &amp;lt;/struct&amp;gt;&quot;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Задача состоит в извлечении информации из тегов item и link. Сделать это довольно просто:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;open System&lt;br /&gt;open System.Collections&lt;br /&gt;open System.Collections.Generic&lt;br /&gt;open System.IO&lt;br /&gt;open System.Xml&lt;br /&gt;&lt;br /&gt;open Maritegra.Xml&lt;br /&gt;open Maritegra.Xml.Operators&lt;br /&gt;&lt;br /&gt;type Item = Item of string * string * string&lt;br /&gt;type Link = Link of string * string * string&lt;br /&gt;&lt;br /&gt;let proc document =&lt;br /&gt;&lt;br /&gt;    use reader = new XmlTextReader (new StringReader (document))&lt;br /&gt;    &lt;br /&gt;    let items = List&amp;lt;_&amp;gt; ()&lt;br /&gt;    let links = List&amp;lt;_&amp;gt; ()&lt;br /&gt;    &lt;br /&gt;    (XmlReader.elem &quot;struct&quot; &amp;lt;|&lt;br /&gt;        (XmlReader.contents &amp;lt;|&lt;br /&gt;            (XmlReader.elem &quot;items&quot; &amp;lt;|&lt;br /&gt;                (XmlReader.contents &amp;lt;|&lt;br /&gt;                    (XmlReader.elem &quot;item&quot; &amp;lt;|&lt;br /&gt;                        xmlreader {&lt;br /&gt;                            let! id   = XmlReader.attr &quot;id&quot;&lt;br /&gt;                            let! x    = XmlReader.attr &quot;x&quot;&lt;br /&gt;                            let! text = XmlReader.text&lt;br /&gt;                            items.Add (Item (id, x, text))&lt;br /&gt;                        })))&lt;br /&gt;            +++&lt;br /&gt;            (XmlReader.elem &quot;links&quot; &amp;lt;|&lt;br /&gt;                (XmlReader.contents &amp;lt;|&lt;br /&gt;                    (XmlReader.elem &quot;link&quot; &amp;lt;|&lt;br /&gt;                        xmlreader {&lt;br /&gt;                            let! sourceId = XmlReader.attr &quot;source-id&quot;&lt;br /&gt;                            let! targetId = XmlReader.attr &quot;target-id&quot;&lt;br /&gt;                            let! text = XmlReader.text&lt;br /&gt;                            links.Add (Link (sourceId, targetId, text))&lt;br /&gt;                        })))))&lt;br /&gt;    |&amp;gt; XmlReader.run reader&lt;br /&gt;&lt;br /&gt;    (items, links)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Теперь сюда помещаем определение значения document (единственное место, где порядок приведения кода отличается от линейного). Затем производим разбор и выводим результат:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;let (items, links) = proc document&lt;br /&gt;&lt;br /&gt;let sprintItem (Item (id, x, text)) = sprintf &quot;Item (%s, %s, %s)&quot; id x text&lt;br /&gt;let sprintLink (Link (sid, tid, text)) = sprintf &quot;Link (%s, %s, %s)&quot; sid tid text&lt;br /&gt;&lt;br /&gt;items |&amp;gt; Seq.map sprintItem&lt;br /&gt;      |&amp;gt; Seq.reduce (fun s1 s2 -&amp;gt; s1 + &quot;, &quot; + s2)&lt;br /&gt;      |&amp;gt; printfn &quot;items = seq [%s]&quot;&lt;br /&gt;&lt;br /&gt;links |&amp;gt; Seq.map sprintLink&lt;br /&gt;      |&amp;gt; Seq.reduce (fun s1 s2 -&amp;gt; s1 + &quot;, &quot; + s2)&lt;br /&gt;      |&amp;gt; printfn &quot;links = seq [%s]&quot;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Итак, удалось довольно рутинный разбор XML втиснуть внутрь одной функции. На мой взгляд, получилось выразительно, хотя и несколько пестрит словом XmlReader. Используя вышеприведенный подход, можно разбирать довольно сложный XML с большой степенью вложенности, оставаясь в рамках одной функции или выражения. Конечно, метод не претендует на полноту. Например, пока не придумал, как разбирать текстовые поля, чередующиеся с тегами на одном уровне, но мне это и ненужно. Тем не менее, метод интересен тем, что XmlReader очень быстр и легковесен в отличие от того же XmlDocument. Правда стоит отметить, что для XmlDocument можно использовать такую чудесную вещь как активное сопоставление с образцом, что позволяет писать чрезвычайно наглядный и выразительный код, но там нужно предварительно полностью загрузить документ XML в промежуточное представление XmlDocument. В общем, нет в мире совершенства!</description>
         <author>dsorokin</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-8641042312683198534.post-6314740098989665577</guid>
         <pubDate>Sat, 07 Aug 2010 15:33:00 +0000</pubDate>
      </item>
      <item>
         <title>Нужно ли полиглотное программирование в стеке .Net?</title>
         <link>https://nesteruk.wordpress.com/2010/08/02/dot-net-polyglot-programming/</link>
         <description>Из комментариев к коротенькому посту на Хабре про использование Python как базового языка для Asp.Net мне понравился вот этот комментарий от centur: Ну собственно повторный вопрос &amp;#8212; зачем? Дмитрий Нестерук высказал вполне здравую мысль &amp;#8212; зачем нужна вся эта куча языков, если есть так активно развиваемый C#. В общем возможность мульти-языкастости среды это клево, но [&amp;#8230;]&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;https://pixel.wp.com/b.gif?host=nesteruk.wordpress.com&amp;#038;blog=373435&amp;#038;post=490&amp;#038;subd=nesteruk&amp;#038;ref=&amp;#038;feed=1&quot; width=&quot;1&quot; height=&quot;1&quot;/&gt;</description>
         <guid isPermaLink="false">http://nesteruk.wordpress.com/?p=490</guid>
         <pubDate>Mon, 02 Aug 2010 13:55:44 +0000</pubDate>
         <content:encoded><![CDATA[<p>Из комментариев к <a rel="nofollow" target="_blank" href="http://habrahabr.ru/blogs/python/100158/">коротенькому посту</a> на Хабре про использование Python как базового языка для Asp.Net мне понравился вот этот комментарий от <a rel="nofollow" target="_blank" href="http://centur.habrahabr.ru">centur</a>:</p>
<blockquote><p>
Ну собственно повторный вопрос &mdash; зачем?<br />
Дмитрий Нестерук высказал вполне здравую мысль &mdash; зачем нужна вся эта куча языков, если есть так активно развиваемый C#.<br />
В общем возможность мульти-языкастости среды это клево, но вот потенциальная поддержка этого &mdash; один из кругов ада =)
</p></blockquote>
<p>Мне кажется что пришло самое время досконально обсудить проблему того, что конкретно нам дают все эти языки, и насколько &ldquo;полиглотное программирование&rdquo; вообще имеет смысл.</p>
<h3>F#</h3>
<p>Давайте прокинем VB и начнем с языка №2 который уже является полноправным жителем нашей .Net экосистемы. Да, интересный, функциональный язык. А теперь внимание вопрос: в чем собственно его приемущества, какой конкретно от него business value?</p>
<p>Вот я написал несколько проектов либо полностью на F# либо частично. У меня была возможность попробовать такие &ldquo;рекламируемые&rdquo; фичи как async workflows и повсеместное отсутствие мутабельности. И вот к каким выводам я пришел:</p>
<ul>
<li>Бизнес-программирование по большому счету мутабельное, тем самым язык который вставляет вам 100 палок в каждое колесо при попытке изменить переменную для него слабо подходит. Чего стоит например вот такое определение:
<pre>
let context : Ref&lt;IVisitable option&gt; = ref None
</pre>
</li>
<li>Async workflows &ndash; это всего лишь кастомная издевка над синтаксисом. Это хак. Такой же хак есть и в .Net с использованием AsyncEnumerator (PowerThreading). Ничего &ldquo;гениального&rdquo; в этом нет, работу это не упрощает. Вот вам прямое сравнение двух подходов &ndash; выводы делайте сами:
<p>
  <strong>F#</strong>
</p>
<pre>
let private DownloadPage(url:string) =
  async {
    try
      let r = WebRequest.Create(url)
      let! resp = r.GetResponseAsync() // let! позволяет дождаться результата
      use stream = resp.GetResponseStream()
      use reader = new StreamReader(stream)
      let html = reader.ReadToEnd()
      use fs = new FileStream(@&quot;c:&#92;temp&#92;file.htm&quot;, FileMode.Create,
                              FileAccess.Write, FileShare.None, 1024, true);
      let bytes = Encoding.UTF8.GetBytes(html);
      do! fs.AsyncWrite(bytes, 0, bytes.Length) // ждем пока все запишется
    with
      | :? WebException -&gt; ()
  }
// вызов ниже делает синхронный вызов метода, но поведение внутри метода - асинхронное
Async.RunSynchronously(DownloadPage(&quot;http://habrahabr.ru&quot;))
</pre>
<p>
  <strong>C#</strong>
</p>
<pre>
public IEnumerator&lt;int&gt; DownloadPage(string url, AsyncEnumerator ae)
{
  var wr = WebRequest.Create(url);
  wr.BeginGetResponse(ae.End(), null);
  yield return 1;
  var resp = wr.EndGetResponse(ae.DequeueAsyncResult());
  var stream = resp.GetResponseStream();
  var reader = new StreamReader(stream);
  string html = reader.ReadToEnd();
  using (var fs = new FileStream(@&quot;c:&#92;temp&#92;file.htm&quot;, FileMode.Create,
                      FileAccess.Write, FileShare.None, 1024, true))
  {
    var bytes = Encoding.UTF8.GetBytes(html);
    fs.BeginWrite(bytes, 0, bytes.Length, ae.End(), null);
    yield return 1;
    fs.EndWrite(ae.DequeueAsyncResult());
  }
}
</pre>
</li>
<li>Метапрограммирование в F# <em>неполноценно</em>. То, что там есть цитирование, еще ничего не значит, т.к. нам хочется не транслировать F# в какой-то там язык, мы хотим то цитирование и &ldquo;сплайс&rdquo; которыми мы можем помочь компилятору сгенерировать некие структуры в процессе компиляции. Настоящее статическое метапрограммирование есть пока что только в Boo, но оно <em>будет</em> в C#.</li>
<li>Создание DSLей &ndash; да, оно проще. Если интересно &ndash; <a rel="nofollow" target="_blank" href="http://www.codeproject.com/KB/dotnet/dslfsharp.aspx">вот моя статья</a>. Только DSLи &ndash; это пока направление которое в основном, во-первых, для internal use, а во-вторых только для продвинутых фирм вроде моей. Точно не для общего пользования. Не верите? <a rel="nofollow" target="_blank" href="http://lmgtfy.com/?q=f%23+dsl">Let me google that for you</a>.</li>
<li>Идея о том, что F# лучше чем C# для сложного алгоритмического программирования в финансовых и аналогичных индустриях <em>не раскрыта</em>. Да, его используют. Детальных case studies мало, и опять же, никто толком не может объяснить <em>почему</em>. И вообще, какая разница, во что <a rel="nofollow" target="_blank" href="http://www.codeproject.com/KB/recipes/mmlsharp.aspx">транслировать формулы</a>?</li>
</ul>
<p>Есть еще нарекания в плане &ldquo;общей вменяемости&rdquo; &ndash; например набор всяких <code>&lt;@ @&gt;</code>, <code>&lt;@@ @@&gt;</code>, <code>[]</code>, <code>[| |]</code>, <code>{}</code>, <code>(|x|_|)</code>, <code>-&gt;</code>, <code>&lt;-</code>, <code>&gt;&gt;</code>, <code>:&gt;</code>, <code>:?&gt;</code>, <code>|&gt;</code> это же просто бред какой-то! Это &ldquo;магические операторы&rdquo;, иначе не назвать.</p>
<p>Вообщем, я действительно <em>хочу</em> использовать F#, но когда я реально начинаю его использовать, то каждая из фич которая изначально кажется selling point языка оказывается неповоротливой и непрактичной. Например, я надеялся что pattern matching поможет мне структурировать разбор строк вот <a rel="nofollow" target="_blank" href="http://bitbucket.org/nesteruk/csharpshorthand">в этом проекте</a>. На самом же деле, код получился <a rel="nofollow" target="_blank" href="https://nesteruk.wordpress.com/2010/03/05/c-zen-coding-%D1%83%D0%B6%D0%B5-%D0%BD%D0%B0-f/">практически нечитабельным</a>. Где тут maintainability? Правильно &ndash; ее нет в помине.</p>
<h3>Boo</h3>
<p>Я конечно понимаю что товарищ <a rel="nofollow" target="_blank" href="http://ayende.com/">Айенде</a>, будучи &ldquo;впереди планеты всей&rdquo; в плане работы с базами данных, решил поделиться своими замечаниями на тему того, как метапрограммирование на языке Boo может принести реальный business value. Проблема в том, что книжка у него отровенно не удалась, и тем самым аргумент как бы затух.</p>
<p>Идея Boo в том, что у вас есть якобы более лаконичный синтаксис (а-ля Python) плюс возможности расширения компилятора которые делают возможным мета-изыски которых мы затаив дыхание ждем в C#. Ну так что, давайте обсудим эти два &ldquo;бенефита&rdquo; на предмет их полезности.</p>
<p>Вообще, идея того что Питон чем-то &ldquo;лаконичней&rdquo; чем C# или какой-то там другой язык &ndash; это попытка продать абстрактное &ldquo;нечто&rdquo;, не подкрепляя это толком никакими аргументами. Возьмем например произвольный кусок кода из проекта:</p>
<pre>
class ManaIndicatorsAttribute(AbstractAstAttribute):   
  public override def Apply(node as Node):
    c = node as ClassDefinition
    for i in range(ManaSumAttribute.LandTypes.Count):
      basic = ManaSumAttribute.LandTypes[i] as string
      hybridLands as List = []
      for j in range(HybridManaAttribute.HybridLandTypes.Count):
        hybrid = HybridManaAttribute.HybridLandTypes[j] as string
        if (hybrid.Contains(basic)):
          hybridLands.Add(hybrid)
      rbasic = ReferenceExpression(basic.ToLower())
      b = Block();
      b1 = [| return true if $rbasic &gt; 0 |]
      b.Statements.Add(b1)
      for k in range(hybridLands.Count):
        rhybrid = ReferenceExpression((hybridLands[k] as string).ToLower())
        b2 = [| return true if $rhybrid &gt; 0 |]
        b.Statements.Add(b2)
      r = [|
        $(&quot;Is&quot; + basic):
          get:
            $b;
      |]
      c.Members.Add(r)
</pre>
<p>Ну-с, и где тут &lsquo;лаконичность&rsquo;? На практике получается жесткий, слабочитаемый код, в котором не спасает вывод типов, в котором записи вроде <code>return x if y</code> добавляют только дополнительную степень неоднозначиности, а вы бы видели IL который сгенерирован &ndash; у меня при виде того как код на Boo разворачивается в код на C# с помощью Рефлектора глаза на лоб лезут &ndash; такое впечатление что этому языку просто плевать на стэк. Поэтому простое суммирование пяти переменных переведенное в C# вернется вам не как <code>a + b + c + d + e</code> а скорее как <code>((((a + b) + c) + d) + e)</code>.</p>
<p>Насчет вещей, аналогичных LINQ. Да, действительно, до Linq в Питоне был козырь в плане разбора списков и прочих, т.е. можно было написать <code>list[1,-1]</code> или например подобное:
</p>
<pre>
List(y for y in (x**2 for x in range(10)) if y % 3 != 0)
</pre>
<p>Теперь это <em>неактуально</em> т.к. в том же C# можно сделать то же самое, причем с поддержкой IntelliSense и без необходимости запоминать всякие <code>range()</code> (какая разница с <code>Enumerable.Range()</code>? меньше букв?) и прочие названия. Приемущество Linq в том, что это <em>унифицированный</em> API, который выглядит одинаково вне зависимости от того, используете ли вы Linq to Objects, Linq to Events (Rx) или Linq to CepStream (StreamInsight). Тут в основном одни и те же ключевые слова, плюс IntelliSense если вы что-то забыли.</p>
<p>Генераторы&hellip; ах, генераторы, идея-то хорошая, но вот скажите мне, что делает следующий кусочек кода:</p>
<pre>
def TestGenerator():
  i = 1
  yield i
  for x in range(10):
    i *= 2
    yield i
</pre>
<p>Утипизация? Тем кому она нужна уже имеют ее в C# с помощью таких библиотек как <a rel="nofollow" target="_blank" href="http://github.com/philiplaureano/LinFu">LinFu</a>. Регулярные выражения через <code>/</code>? Ну что ж, может это и удобней, но лично мне все равно, т.к. я использую <a rel="nofollow" target="_blank" href="http://www.ultrapico.com/Expresso.htm">приложение</a>, которое решает за меня все эти проблемы (хотя соглашусь, что конверсия в C#-строку выглядит коряво). Что остается?</p>
<p>Остается пожалуй только метапрограммирование. Это, на данный момент, <em>единственный козырь</em> в языке который, как мы с коллегами считаем, умрет сразу же после выхода C#5. И если вы считаете что метапрограммивание нужно сегодня и нужно срочно использовать Boo, вот вам несколько контр-аргументов:</p>
<ul>
<li>Язык и инструментарий не развиваются. <a rel="nofollow" target="_blank" href="http://boolangstudio.codeplex.com/">BooLangStudio</a> мертва. Документация на сайтах частично устарела.</li>
<li>Использовать две IDE достаточно напряжно. Я имею ввиду, что вам придется компилировать Boo через <a rel="nofollow" target="_blank" href="http://www.icsharpcode.net/opensource/sd/">SharpDevelop</a>, а потом импортировать сборки в ваши C# проекты. Никакого configuration management рядом не стояло.</li>
<li>Компилятор сырой, и у меня были мета-методы которые вообще не сходились, т.е. программа компилировалась в невалидный IL. Никаких гарантий безопасности компилятор не дает.</li>
<li>Про IntelliSense или аналогичные вещи можно забыть &ndash; Boo вы будете программировать вслепую.</li>
</ul>
<p>Вообщем, для тех кого это действительно интересует, у меня есть вводная статья про метапрограммирование на Boo. Только вот стоит ли напрягаться? Ведь C#5 не за горами, и есть большая вероятность, что с его выходом можно будет пометить Boo как <code>[Obsolete]</code>.</p>
<h3>IronPython</h3>
<p>Вся критика по языку Boo может быть обращена к <a rel="nofollow" target="_blank" href="http://ironpython.net/">IronPython</a> ибо синтаксис похожий. Единственный плюс &ndash; что IronPython как бы более &ldquo;зрелый&rdquo; и даже имеет поддержку в Visual Studio (<a rel="nofollow" target="_blank" href="http://ironpython.net/tools/">IronPythonTools</a>). Ну и да, &ldquo;динамичность&rdquo; этого языка несет в себе, якобы, некоторые приемущества которые всем уже известны.</p>
<p>Только есть одно <em>но</em> &ndash; тема CLR vs DLR (не знаю можно ли так писать) &ndash; явно не раскрыта. Например, почему создатели языка Go намеренно сделали его статическим? Правильно &ndash; скорость. А что делать с языком который не дает ощутимых бенефитов в плане синтаксиса, и который по скорости не тянет (чего стоит скорость декораторов, например &ndash; да легче помучаться и на C# написать, или подвязать тот же <a rel="nofollow" target="_blank" href="http://www.sharpcrafters.com/">PostSharp</a>).</p>
<h3>IronRuby</h3>
<p>Если питонообразные языки человек с опытом C# еще как-то может понять, то Ruby &ndash; это чистая магия, т.е. язык который нужно долго и прагматично изучать с нуля. А стоит ли это того? Alt.Net сообщество уже прожужжало нам все уши на тему того, что Ruby лучше для тестирования (см. например <a rel="nofollow" target="_blank" href="http://cukes.info/">Cucumber</a>), и я с этим не спорю &ndash; действительно, чем ближе мы в BDD приближаемся к обычному английскому, тем больше к нам аппелирует сама концепция BDD. Только вот есть одно <em>но</em> &ndash; BDD пока штука не доказанная, она как и приемочное тестирование в стиле <a rel="nofollow" target="_blank" href="http://fitnesse.org/">Fitnesse</a> является интересной абстракцией к которой индустрия присматривается, но не делает ее стандартом для разработки.</p>
<p>Чем еще хорош Ruby? Да, он неплохо поддерживает <em>динамическое</em> метапрограммирование, есть даже <a rel="nofollow" target="_blank" href="http://pragprog.com/titles/ppmetr/metaprogramming-ruby">книжка</a> на эту тему. Но занимаясь именно динамическим, а не статическим, метапрограммированием, следует понимать что это не совсем одно и то же &ndash; динамическое программирование это серьезное заигрывание с концепциями а-ля <code>ExpandoObject</code>, то есть манипуляция типов на этапе исполнения &ndash; нечто, что после безумной головной боли можно реализовать и на <a rel="nofollow" target="_blank" href="http://www.mono-project.com/Cecil">Mono.Cecil</a>. В то же время, статическое метапрограммирование &ndash; это возможность расширять не тип, а <em>компилятор</em>. Тем самым, сравнивать эти два подхода не очень уместно, и то что Роб Конери хочет &ldquo;метапрограммирование сегодня и сейчас&rdquo; &ndash; это лично <em>его</em> представление о том, что это такое, и мне кажется он смешивает краски.</p>
<p>Следует заметить, что у IronRuby в отличии от IronPython нет поддержки в Visual Studio. Поэтому придется использовать или SharpDevelop или (сюрприз!!!) IntelliJ IDEA/<a rel="nofollow" target="_blank" href="http://www.jetbrains.com/ruby/index.html">RubyMine</a>. При этом вы получите IntelliSense для ваших собственных конструкций, но его у вас не будет для различных .Net-библиотек.</p>
<h3>Заключение</h3>
<p>Прежде всего &ndash; да &ndash; существуют и другие языки в стеке .Net, например <a rel="nofollow" target="_blank" href="http://ironscheme.codeplex.com/">IronScheme</a>. Но чем дальше мы отходим от &ldquo;канона&rdquo; тем дальше мы и от обычного бизнес-программирования, а следовательно каким бы элегантным не был тот или иной язык, можно с уверенностью говорить что без участия комьюнити, uptake такого языка будет равен нулю. Примером может служить язык <a rel="nofollow" target="_blank" href="http://nemerle.org/Main_Page">Nemerle</a>, которого, несмотря на наличие интересных (но ни в коей мере не революционных) идей, ожидает та же участь что и Boo.</p>
<p>Проблемы со сторонними языками можно охарактеризовать примерно так:</p>
<ul>
<li>Бизнес не примет их без поддержки Microsoft</li>
<li>Количество людей, хорошо знающих эти языки мало&#x301;, а значит те сотрудники что у вас их знают рискуют стать незаменимыми</li>
<li>Клиент вряд ли согласиться на проект на языке, особенно если саппорт он хочет получить не у вас, а где-то еще</li>
<li>Инструментарий пока не очень готов &ndash; это касается даже таких языков как F#</li>
<li>Реально не хватает success stories, которые четко показывают бенефиты</li>
</ul>
<p>В заключение этой статьи я призываю всех .Net-разработчиков порадоваться, что у нас есть такой гибкий язык как C#, который удовлетворяет все 100% (да-да, именно 100%) наших потребностей. С другой стороны, никто не мешает экспериментировать &ndash; главное чтобы ваши эксперименты потом попадали в production, а то иначе это все академизм и теоретизирование. Удачи! <img src="http://nesteruk.org/projects/visitlogger/log" alt=""/></p>
<p>
  <strong>Update 1</strong> Как подсказал коллега <a rel="nofollow" target="_blank" href="http://twitter.com/butaji" title="butaji's posts on twitter">@butaji</a>, DLR полезен тем что позволяет легко &ldquo;скриптовать&rdquo; ваши .Net-приложения, то есть фактически получать возможность скриптинга ваших .Net-конструктов без использования COM Automation или еще более кустарных извратов. Это конечно огромный плюс в тех ситуациях когда это действительно нужно, особенно если учесть альтернативы (создание всяких проприетарных DSL и т.п.).
</p>
<p>
  <strong>Update 2</strong> Судя по всему, с DLR-языками, в частности с IronRuby, все <a rel="nofollow" target="_blank" href="http://blog.jimmy.schementi.com/2010/08/start-spreading-news-future-of-jimmy.html" title="http://blog.jimmy.schementi.com/2010/08/start-spreading-news-future-of-jimmy.html">достаточно плохо</a>.
</p>
<p>
  <strong>Update 3</strong><br />
  Судя по всему, огромным приемуществом DLR являются ситуации, когда нам нужно постоянно подтачивать нашу программу уже после компиляции. Коллега <a rel="nofollow" target="_blank" href="http://twitter.com/butaji" title="butaji's posts on twitter">@butaji</a> уже это упомянул, но мне пока это не попадалось как вопиющий юз-кейс. А теперь я даже обзавелся компонентом который делает синтактическую подсветку. Буду встраивать; посмотрим что получится.</p><br />Filed under: <a rel="nofollow" target="_blank" href='https://nesteruk.wordpress.com/category/net/'>.NET</a>, <a rel="nofollow" target="_blank" href='https://nesteruk.wordpress.com/category/c/'>C#</a>, <a rel="nofollow" target="_blank" href='https://nesteruk.wordpress.com/category/net/f/'>f#</a>  <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gocomments/nesteruk.wordpress.com/490/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/nesteruk.wordpress.com/490/"/></a> <img alt="" border="0" src="https://pixel.wp.com/b.gif?host=nesteruk.wordpress.com&#038;blog=373435&#038;post=490&#038;subd=nesteruk&#038;ref=&#038;feed=1" width="1" height="1"/>]]></content:encoded>
         <media:content medium="image" url="https://0.gravatar.com/avatar/f01cbd2238e2a78e4c43fa596f51d6a1?s=96&amp;amp;d=https%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&amp;amp;r=PG">
            <media:title type="html">nesteruk</media:title>
         </media:content>
         <media:content medium="image" url="http://nesteruk.org/projects/visitlogger/log"/>
      </item>
      <item>
         <title>Хозяйке на заметку</title>
         <link>http://skiminog.livejournal.com/71849.html</link>
         <description>Декартово произведение произвольного числа последовательностей на F#. Красиво.&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;font-family:monospace;font-size:9pt;color:black;background:white;border:1px solid #d0d0d0;&quot;&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;let&lt;/span&gt; product seqs =&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; List.rev seqs&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&amp;gt; List.fold &lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (&lt;span style=&quot;color:blue;&quot;&gt;fun&lt;/span&gt; acc cur &lt;span style=&quot;color:blue;&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; [&lt;span style=&quot;color:blue;&quot;&gt;for&lt;/span&gt; seq &lt;span style=&quot;color:blue;&quot;&gt;in&lt;/span&gt; acc &lt;span style=&quot;color:blue;&quot;&gt;do&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span style=&quot;color:blue;&quot;&gt;for&lt;/span&gt; item &lt;span style=&quot;color:blue;&quot;&gt;in&lt;/span&gt; cur &lt;span style=&quot;color:blue;&quot;&gt;do&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;span style=&quot;color:blue;&quot;&gt;yield&lt;/span&gt; item::seq])&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; [List.empty]&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Здесь использованы: пайплайны, свертка и list comprehensions. А также элементарное индуктивное определение декартова произведения.</description>
         <guid isPermaLink="false">urn:lj:livejournal.com:atom1:skiminog:71849</guid>
         <pubDate>Wed, 14 Jul 2010 13:37:24 +0000</pubDate>
      </item>
      <item>
         <title>Про моноиды (с примерами на F#)</title>
         <link>http://samolisov.blogspot.com/2010/06/f.html</link>
         <description>ВведениеApocalips порадовал статьей, в которой четко и доходчиво объяснил что такое моноид применительно к алгебре над списками и теории категорий. В данной заметке представлен очень вольный перевод его статьи, снабженный примерами на F# (у Apocalips'a примеры на Scala).Прежде всего рассмотрим обобщенное определение моноида:type IMonoid&amp;lt;'T&amp;gt; =    abstract member mempty : 'T    abstract member</description>
         <author>Pavel Samolisov</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3043523252258851613.post-7336194712390926278</guid>
         <pubDate>Tue, 15 Jun 2010 19:09:00 +0000</pubDate>
      </item>
      <item>
         <title>Дискретно-событийное моделирование</title>
         <link>http://dsorokin.blogspot.com/2010/06/blog-post.html</link>
         <description>&lt;div&gt;Для своей маленькой библиотеки имитационного моделирования &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://sourceforge.net/projects/aivika/&quot;&gt;Айвика&lt;/a&gt; [http://sourceforge.net/projects/aivika/] в документацию добавил законченную главу о дискретно-событийном моделировании (DES) и интеграции подмоделей DES в единую гибридную модель. Там получилось все очень функционально.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Вообще, я часто думаю, а можно ли перевести библиотеку на Хаскель? Тем более, самый первый прототип был именно на Хаскеле. Но тут два препятствия. Во-первых, нужна мемоизация, которая бы действовала, пока симуляция запущена. Ну, это, мне кажется, можно обойти, ради скорости сфальшивив в некоторых местах через &lt;i&gt;unsafePerformIO&lt;/i&gt;. Все равно, все будет спрятано за монадами, что даст определенные непробиваемые гарантии (как сейчас на F# в Айвике).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Второе препятствие более сложное и принципиальное. Имитационные модели почти все стохастические, т.е. недетерминированные. И я пока не знаю, как это эффективно реализовать, да так, чтобы система типов осталась простой и ясной. В F# с этим проблем нет.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;</description>
         <author>dsorokin</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-8641042312683198534.post-1006661327315826014</guid>
         <pubDate>Sun, 06 Jun 2010 13:43:00 +0000</pubDate>
      </item>
      <item>
         <title>Обновленная документация к Айвике</title>
         <link>http://dsorokin.blogspot.com/2010/05/blog-post.html</link>
         <description>&lt;div&gt;Если кому интересно, то я сегодня выложил обновленную версию свой библиотеки моделирования &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://sourceforge.net/projects/aivika/&quot;&gt;Айвика&lt;/a&gt; [http://sourceforge.net/projects/aivika/]. Там содержится более полная документация. Я описал то, как реализуются в Айвике activity-oriented и event-oriented парадигмы дискретно-событийного моделирования (DES). Также есть краткая информация о монаде DynamicsCont, которая лежит в основе моей реализации process-oriented парадигмы DES. В общем, среди парадигм теперь осталось осветить этот самый process-oriented DES и агентное моделирование (agent-based modeling).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Удивительное дело получается. Сплав методов функционального программирования и имитационного моделирования. Наиболее поразительны результаты в области DES. Тут и две монады, одна из которых является монадным трансформером, параметризованным по другой монаде. Тут еще computation expressions, которые являются в F# синтаксическим сахаром для монад и моноидов. Они делают сочинение моделей DES довольно приятным занятием. Тут же замыкания, которые используются для передачи данных вместе с событиями. Само событие у меня – это просто значение (), обернутое в монаду Dynamics. В общем, красота.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Что несколько удручает, так это большая нагрузка на систему управления памятью (GC). Монады означают, что создается во время моделирования до черта кратко-живущих функций с замыканиями (модуль системной динамики этим не страдает). Но дотнетовский GC неплох, очень неплох. Его двойник в Mono оказался на одной модельке намного тормознее.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Мне все же кажется, что придуманная мною единая схема имитационного моделирования имеет право на жизнь. Можно по-быстрому запрототипировать довольно сложную гибридную модель. Так что, быть!&lt;/div&gt;</description>
         <author>dsorokin</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-8641042312683198534.post-854699491551009087</guid>
         <pubDate>Mon, 31 May 2010 18:23:00 +0000</pubDate>
      </item>
      <item>
         <title>Aivika версии 2.0</title>
         <link>http://dsorokin.blogspot.com/2010/05/aivika-20.html</link>
         <description>&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family:georgia;&quot;&gt;&lt;p class=&quot;MsoNormal&quot;&gt;В ходе разработки моей небольшой библиотеки моделирования &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://sourceforge.net/projects/aivika/&quot;&gt;Айвика&lt;/a&gt; на языке F# произошел ряд важных прорывных событий. Во-первых, я значительно ускорил модуль системной динамики. Обсчет модели по методу Рунге-Кутта стал в раз 5 быстрее. Потом я добавил агентное моделирование (АМ), как его понял после прочтения статьи Андрея Борщева (одного из создателей системы AnyLogic). Для этого я переписал очередь событий модуля дискретно-событийного моделирования (DES), который стал на порядки производительнее. В общем, теперь охватываются все три основные парадигмы имитационного моделирования (ИМ), и в целом я доволен скоростью имитации. Также создал каталог с примерами моделей, каждая из которых снабжена справочной информацией и ссылками. Теперь более подробно.&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot;&gt;&lt;b&gt;Модуль системной динамики (SD)&lt;/b&gt;&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot;&gt;Мне удалось значительно ускорить этот модуль за счет отказа от функций нескольких аргументов. После компиляции такие функции вызываются в конечном итоге через метод InvokeFast, который вопреки своему названию совершенно не быстр. Там используется RTTI, что делает каждый такой вызов достаточно медленным. Если же функция имеет всего один аргумент, то тогда вызывается напрямую абстрактный метод Invoke, минуя RTTI. Вызов Invoke очень эффективен.&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot;&gt;Поэтому я переписал внутренности модуля так, чтобы везде использовалась функция одного аргумента. Теперь монада Dynamics стала просто частным случаем монады Reader с небольшим исключением: некоторые функции создают жестко контролируемый побочный эффект. Мне кажется, это можно как-то записать и в хаскеле, но там придется программировать на Си, реализуя местами функциональность монады ST.&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot;&gt;В итоге модуль системной динамики стал где-то в пять раз быстрее прежнего. Учитывая, что все в Айвике в конечном счете построено на монаде Dynamics, это имеет колоссальные последствия для всей библиотеки в целом.&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot;&gt;Еще я лучше осознал смысл термина комбинатор. Оказывается, что все функции eDSL системной динамики являются у меня комбинаторами. Причем выглядят они почти так же как в специализированных системах Simtegra MapSys, ithink или Vensim. Но у меня функции, которые принимают одни функции и создают другие, обладая свойством замыкания.&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot;&gt;&lt;b&gt;Агентное моделирование (АМ)&lt;/b&gt;&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot;&gt;Система AnyLogic использует карты состояний (statecharts) для описания агентов. Я придумал API, которое позволяет достаточно декларативно задавать агенты и их состояния так, как если бы мы использовали эти самые карты состояний. Получается кратко и наглядно. Все действия задаются в монаде Dynamics. Широко используются такие возможности F# как взаимно-рекурсивные определения через let rec и объектные выражения (object expressions). Благодаря монаде Dynamics агенты легко интегрируются с модулем системной динамики.&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot;&gt;&lt;b&gt;Дискретно-событийное моделирование (DES)&lt;/b&gt;&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot;&gt;Агентное моделирование реализовано поверх очереди событий, которая является сердцем DES.&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot;&gt;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family:Georgia, serif;color:rgb(0, 0, 238);&quot;&gt;&lt;img src=&quot;http://2.bp.blogspot.com/_RZXTBoE6nVc/S_k_FVlliGI/AAAAAAAAAAU/h45Vm2lNY5M/s400/Hierarchy.png&quot; border=&quot;0&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5474476182972237922&quot; style=&quot;display:block;margin-top:0px;margin-right:auto;margin-bottom:10px;margin-left:auto;text-align:center;cursor:pointer;width:346px;height:400px;&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;div&gt;В предыдущей версии очередь была реализована как proof-of-concept, т.е. через двусторонний список… Тормоза стали особенно заметны после добавления АМ. Сначала я переписал очередь через иммутабельный хип, описанный в одной замечательной книге по хаскелю. Но функции добавления и удаления по-прежнему продолжали висеть в списке десяти самых тормозных функций, показываемых профайлером SharpDevelop. Тогда я переписал очередь через императивный бинарный хип, реализованный на основе массива. Функции работы c очередью ушли из списка. Агентное моделирование просто взлетело.&lt;/div&gt;&lt;p class=&quot;MsoNormal&quot;&gt;&lt;b&gt;Примеры моделей&lt;/b&gt;&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot;&gt;Я создал аналоги моделей, используемых в системах Simtegra MapSys (SD), Berkeley&amp;amp;Madonna (SD), AnyLogic (АМ) и SimPy (DES). Также реализовал пару моделей, описанных в книге Ильи Труба “Объектно-ориентированное моделирование на C++”.&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot;&gt;&lt;b&gt;Планы&lt;/b&gt;&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot;&gt;Считаю, что библиотека Айвика находится в достаточно зрелом состоянии. Например, ее можно использовать для создания визуализированных моделей, проигрываемых поверх Silverlight.&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot;&gt;Сейчас в документации достаточно полно освещен модуль системной динамики. Теперь нужно описать модули дискретно-событийного моделирования (DES) и агентного моделирования (АМ). Думаю, что можно заняться продвижением. Важно, что библиотеку можно использовать и из C#, но наиболее полно возможности доступны только через F#.&lt;/p&gt;&lt;/span&gt;&lt;p&gt;&lt;/p&gt;</description>
         <author>dsorokin</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-8641042312683198534.post-8853948095010761736</guid>
         <pubDate>Sun, 23 May 2010 18:28:00 +0000</pubDate>
         <media:thumbnail height="72" url="http://2.bp.blogspot.com/_RZXTBoE6nVc/S_k_FVlliGI/AAAAAAAAAAU/h45Vm2lNY5M/s72-c/Hierarchy.png" width="72" xmlns:media="http://search.yahoo.com/mrss/"/>
      </item>
      <item>
         <title>Google code jam. Qualification Round 2010.</title>
         <link>http://evgeny-lazin.blogspot.com/2010/05/google-code-jam-qualification-round.html</link>
         <description>&lt;p&gt;Решил вчера поучаствовать в отборочном раунде code jam. Раунд состоял из трех достаточно простых задач, мне хватило терпения только на первые две, хотя как решать третью я тоже понял :)&lt;/p&gt;  &lt;p&gt;Первая задача, &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://code.google.com/codejam/contest/dashboard?c=433101#s=p0&quot;&gt;snaper chain&lt;/a&gt; – самая простая, достаточно понять, что состояние snapper-ов в цепочке после K щелчков, будет эквивалентно двоичному представлению числа K. Вот мое решение на F#:&lt;/p&gt;  &lt;pre style=&quot;background:#ffffff;color:#000000;&quot;&gt;&lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;open&lt;/span&gt; System
&lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;open&lt;/span&gt; System&lt;span style=&quot;color:#008c00;&quot;&gt;.&lt;/span&gt;IO

&lt;span style=&quot;color:#808030;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;/&lt;/span&gt; read the input file
&lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;let&lt;/span&gt; args &lt;span style=&quot;color:#808030;&quot;&gt;=&lt;/span&gt; Environment&lt;span style=&quot;color:#008c00;&quot;&gt;.&lt;/span&gt;GetCommandLineArgs&lt;span style=&quot;color:#808030;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;)&lt;/span&gt;
&lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;let&lt;/span&gt; inputPath &lt;span style=&quot;color:#808030;&quot;&gt;=&lt;/span&gt; args.&lt;span style=&quot;color:#808030;&quot;&gt;[&lt;/span&gt;args&lt;span style=&quot;color:#008c00;&quot;&gt;.&lt;/span&gt;Length &lt;span style=&quot;color:#808030;&quot;&gt;-&lt;/span&gt; &lt;span style=&quot;color:#008c00;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;]&lt;/span&gt;
&lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;let&lt;/span&gt; outputPath &lt;span style=&quot;color:#808030;&quot;&gt;=&lt;/span&gt; Path&lt;span style=&quot;color:#008c00;&quot;&gt;.&lt;/span&gt;ChangeExtension&lt;span style=&quot;color:#808030;&quot;&gt;(&lt;/span&gt;inputPath&lt;span style=&quot;color:#808030;&quot;&gt;,&lt;/span&gt; &lt;span style=&quot;color:#0000e6;&quot;&gt;&amp;quot;.out&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;)&lt;/span&gt;

&lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;let&lt;/span&gt; inputStr &lt;span style=&quot;color:#808030;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;new&lt;/span&gt; StreamReader&lt;span style=&quot;color:#808030;&quot;&gt;(&lt;/span&gt;inputPath&lt;span style=&quot;color:#808030;&quot;&gt;)&lt;/span&gt;
&lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;let&lt;/span&gt; outputStr &lt;span style=&quot;color:#808030;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;new&lt;/span&gt; StreamWriter&lt;span style=&quot;color:#808030;&quot;&gt;(&lt;/span&gt;outputPath&lt;span style=&quot;color:#808030;&quot;&gt;)&lt;/span&gt;

&lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;let&lt;/span&gt; testsNum &lt;span style=&quot;color:#808030;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color:#808030;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;|&lt;/span&gt; inputStr&lt;span style=&quot;color:#008c00;&quot;&gt;.&lt;/span&gt;ReadLine&lt;span style=&quot;color:#808030;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;)&lt;/span&gt;

&lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;let&lt;/span&gt; inputSeq&lt;span style=&quot;color:#808030;&quot;&gt;:&lt;/span&gt;seq&lt;span style=&quot;color:#808030;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&quot;color:#808030;&quot;&gt;=&lt;/span&gt; seq &lt;span style=&quot;color:#808030;&quot;&gt;{&lt;/span&gt;
    &lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;while&lt;/span&gt; inputStr&lt;span style=&quot;color:#008c00;&quot;&gt;.&lt;/span&gt;EndOfStream &lt;span style=&quot;color:#808030;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;false&lt;/span&gt; &lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;do&lt;/span&gt;
        &lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;let&lt;/span&gt; line &lt;span style=&quot;color:#808030;&quot;&gt;=&lt;/span&gt; inputStr&lt;span style=&quot;color:#008c00;&quot;&gt;.&lt;/span&gt;ReadLine&lt;span style=&quot;color:#808030;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;)&lt;/span&gt;
        &lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;let&lt;/span&gt; lst &lt;span style=&quot;color:#808030;&quot;&gt;=&lt;/span&gt; line&lt;span style=&quot;color:#008c00;&quot;&gt;.&lt;/span&gt;Split&lt;span style=&quot;color:#808030;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#0000e6;&quot;&gt;' '&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;)&lt;/span&gt;
        yield &lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;int&lt;/span&gt; lst.&lt;span style=&quot;color:#808030;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#008c00;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;,&lt;/span&gt; &lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;int&lt;/span&gt; lst.&lt;span style=&quot;color:#808030;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#008c00;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;]&lt;/span&gt;
    &lt;span style=&quot;color:#808030;&quot;&gt;}&lt;/span&gt;

&lt;span style=&quot;color:#808030;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;/&lt;/span&gt; write the output file
&lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;let&lt;/span&gt; snapperState n k &lt;span style=&quot;color:#808030;&quot;&gt;=&lt;/span&gt;
    &lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;let&lt;/span&gt; l &lt;span style=&quot;color:#808030;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color:#008c00;&quot;&gt;2&lt;/span&gt; &lt;span style=&quot;color:#808030;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;&amp;lt;&lt;/span&gt; n &lt;span style=&quot;color:#808030;&quot;&gt;-&lt;/span&gt; &lt;span style=&quot;color:#008c00;&quot;&gt;1&lt;/span&gt;
    &lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;let&lt;/span&gt; m &lt;span style=&quot;color:#808030;&quot;&gt;=&lt;/span&gt; k % l
    &lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;match&lt;/span&gt; l &lt;span style=&quot;color:#808030;&quot;&gt;-&lt;/span&gt; &lt;span style=&quot;color:#008c00;&quot;&gt;1&lt;/span&gt; &lt;span style=&quot;color:#808030;&quot;&gt;=&lt;/span&gt; m &lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;with&lt;/span&gt;
    &lt;span style=&quot;color:#808030;&quot;&gt;|&lt;/span&gt; &lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;true&lt;/span&gt;  &lt;span style=&quot;color:#808030;&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&quot;color:#0000e6;&quot;&gt;&amp;quot;ON&amp;quot;&lt;/span&gt;
    &lt;span style=&quot;color:#808030;&quot;&gt;|&lt;/span&gt; &lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;false&lt;/span&gt; &lt;span style=&quot;color:#808030;&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&quot;color:#0000e6;&quot;&gt;&amp;quot;OFF&amp;quot;&lt;/span&gt;

&lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;let&lt;/span&gt; &lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;mutable&lt;/span&gt; caseIx &lt;span style=&quot;color:#808030;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color:#008c00;&quot;&gt;1&lt;/span&gt;
&lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;for&lt;/span&gt; n&lt;span style=&quot;color:#808030;&quot;&gt;,&lt;/span&gt; k &lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;in&lt;/span&gt; inputSeq &lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;do&lt;/span&gt;
    &lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;let&lt;/span&gt; line &lt;span style=&quot;color:#808030;&quot;&gt;=&lt;/span&gt; sprintf &lt;span style=&quot;color:#0000e6;&quot;&gt;&amp;quot;Case #&lt;/span&gt;&lt;span style=&quot;color:#0f69ff;&quot;&gt;%d&lt;/span&gt;&lt;span style=&quot;color:#0000e6;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#0f69ff;&quot;&gt;%s&lt;/span&gt;&lt;span style=&quot;color:#0000e6;&quot;&gt;&amp;quot;&lt;/span&gt; caseIx &lt;span style=&quot;color:#808030;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;|&lt;/span&gt; snapperState n k
    outputStr&lt;span style=&quot;color:#008c00;&quot;&gt;.&lt;/span&gt;WriteLine&lt;span style=&quot;color:#808030;&quot;&gt;(&lt;/span&gt;line&lt;span style=&quot;color:#808030;&quot;&gt;)&lt;/span&gt;
    caseIx &lt;span style=&quot;color:#808030;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;-&lt;/span&gt; caseIx &lt;span style=&quot;color:#808030;&quot;&gt;+&lt;/span&gt; &lt;span style=&quot;color:#008c00;&quot;&gt;1&lt;/span&gt;

outputStr&lt;span style=&quot;color:#008c00;&quot;&gt;.&lt;/span&gt;Close&lt;span style=&quot;color:#808030;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;)&lt;/span&gt;
inputStr&lt;span style=&quot;color:#008c00;&quot;&gt;.&lt;/span&gt;Close&lt;span style=&quot;color:#808030;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;)&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;Вторая задача, &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://code.google.com/codejam/contest/dashboard?c=433101#s=p1&quot;&gt;fair warning&lt;/a&gt; – намного сложнее. Суть задачи – в следующем, у нас есть набор чисел – t1, t2,.. tn. Нужно найти такое значение y, для которого справедливо условие – (Y + ti) mod T = 0, для любого i &amp;lt; n. Причем, T – должно быть максимально возможным. Помимо этого, исходные данные могут содержать большие числа, так и написано: &lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;64 bits will not save you. You have been warned.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Я использовал следующий алгоритм – сначала массив чисел ti сортируется, затем – нормализуется (из каждого элемента вычитается значение минимального элемента); далее, вычисляется наибольший общий делитель элементов массива(функция gcdv), в результате чего мы получаем значение T, после чего достаточно легко рассчитать значение Y. Вот мое решение:&lt;/p&gt;

&lt;pre style=&quot;background:#ffffff;color:#000000;&quot;&gt;&lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;open&lt;/span&gt; System
&lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;open&lt;/span&gt; System&lt;span style=&quot;color:#008c00;&quot;&gt;.&lt;/span&gt;IO
&lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;open&lt;/span&gt; System&lt;span style=&quot;color:#008c00;&quot;&gt;.&lt;/span&gt;Numerics

&lt;span style=&quot;color:#808030;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;/&lt;/span&gt; read the input file
&lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;let&lt;/span&gt; args &lt;span style=&quot;color:#808030;&quot;&gt;=&lt;/span&gt; Environment&lt;span style=&quot;color:#008c00;&quot;&gt;.&lt;/span&gt;GetCommandLineArgs&lt;span style=&quot;color:#808030;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;)&lt;/span&gt;
&lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;let&lt;/span&gt; inputPath &lt;span style=&quot;color:#808030;&quot;&gt;=&lt;/span&gt; args.&lt;span style=&quot;color:#808030;&quot;&gt;[&lt;/span&gt;args&lt;span style=&quot;color:#008c00;&quot;&gt;.&lt;/span&gt;Length &lt;span style=&quot;color:#808030;&quot;&gt;-&lt;/span&gt; &lt;span style=&quot;color:#008c00;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;]&lt;/span&gt;
&lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;let&lt;/span&gt; outputPath &lt;span style=&quot;color:#808030;&quot;&gt;=&lt;/span&gt; Path&lt;span style=&quot;color:#008c00;&quot;&gt;.&lt;/span&gt;ChangeExtension&lt;span style=&quot;color:#808030;&quot;&gt;(&lt;/span&gt;inputPath&lt;span style=&quot;color:#808030;&quot;&gt;,&lt;/span&gt; &lt;span style=&quot;color:#0000e6;&quot;&gt;&amp;quot;.out&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;)&lt;/span&gt;

&lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;let&lt;/span&gt; inputStr &lt;span style=&quot;color:#808030;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;new&lt;/span&gt; StreamReader&lt;span style=&quot;color:#808030;&quot;&gt;(&lt;/span&gt;inputPath&lt;span style=&quot;color:#808030;&quot;&gt;)&lt;/span&gt;
&lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;let&lt;/span&gt; outputStr &lt;span style=&quot;color:#808030;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;new&lt;/span&gt; StreamWriter&lt;span style=&quot;color:#808030;&quot;&gt;(&lt;/span&gt;outputPath&lt;span style=&quot;color:#808030;&quot;&gt;)&lt;/span&gt;

&lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;let&lt;/span&gt; testsNum &lt;span style=&quot;color:#808030;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color:#808030;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;|&lt;/span&gt; inputStr&lt;span style=&quot;color:#008c00;&quot;&gt;.&lt;/span&gt;ReadLine&lt;span style=&quot;color:#808030;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;)&lt;/span&gt;
printfn &lt;span style=&quot;color:#0000e6;&quot;&gt;&amp;quot;N: &lt;/span&gt;&lt;span style=&quot;color:#0f69ff;&quot;&gt;%d&lt;/span&gt;&lt;span style=&quot;color:#0000e6;&quot;&gt;&amp;quot;&lt;/span&gt; testsNum

&lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;let&lt;/span&gt; inputSeq &lt;span style=&quot;color:#808030;&quot;&gt;=&lt;/span&gt; seq &lt;span style=&quot;color:#808030;&quot;&gt;{&lt;/span&gt;
    &lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;while&lt;/span&gt; inputStr&lt;span style=&quot;color:#008c00;&quot;&gt;.&lt;/span&gt;EndOfStream &lt;span style=&quot;color:#808030;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;false&lt;/span&gt; &lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;do&lt;/span&gt;
        &lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;let&lt;/span&gt; line &lt;span style=&quot;color:#808030;&quot;&gt;=&lt;/span&gt; inputStr&lt;span style=&quot;color:#008c00;&quot;&gt;.&lt;/span&gt;ReadLine&lt;span style=&quot;color:#808030;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;)&lt;/span&gt;
        &lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;let&lt;/span&gt; strlst &lt;span style=&quot;color:#808030;&quot;&gt;=&lt;/span&gt; line&lt;span style=&quot;color:#008c00;&quot;&gt;.&lt;/span&gt;Split&lt;span style=&quot;color:#808030;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#0000e6;&quot;&gt;' '&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;)&lt;/span&gt;.&lt;span style=&quot;color:#808030;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#008c00;&quot;&gt;1&lt;/span&gt;..&lt;span style=&quot;color:#808030;&quot;&gt;]&lt;/span&gt;
        &lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;let&lt;/span&gt; intlst &lt;span style=&quot;color:#808030;&quot;&gt;=&lt;/span&gt; Array&lt;span style=&quot;color:#008c00;&quot;&gt;.&lt;/span&gt;map &lt;span style=&quot;color:#808030;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;fun&lt;/span&gt; x &lt;span style=&quot;color:#808030;&quot;&gt;-&amp;gt;&lt;/span&gt; BigInteger&lt;span style=&quot;color:#008c00;&quot;&gt;.&lt;/span&gt;Parse&lt;span style=&quot;color:#808030;&quot;&gt;(&lt;/span&gt;x&lt;span style=&quot;color:#808030;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;)&lt;/span&gt; strlst
        yield intlst
    &lt;span style=&quot;color:#808030;&quot;&gt;}&lt;/span&gt;

&lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;let&lt;/span&gt; gcd a b &lt;span style=&quot;color:#808030;&quot;&gt;=&lt;/span&gt; BigInteger&lt;span style=&quot;color:#008c00;&quot;&gt;.&lt;/span&gt;GreatestCommonDivisor&lt;span style=&quot;color:#808030;&quot;&gt;(&lt;/span&gt;a&lt;span style=&quot;color:#808030;&quot;&gt;,&lt;/span&gt; b&lt;span style=&quot;color:#808030;&quot;&gt;)&lt;/span&gt;

&lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;let&lt;/span&gt; gcdv vals &lt;span style=&quot;color:#808030;&quot;&gt;=&lt;/span&gt; Array&lt;span style=&quot;color:#008c00;&quot;&gt;.&lt;/span&gt;reduce gcd vals
            
&lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;let&lt;/span&gt; getDiff events &lt;span style=&quot;color:#808030;&quot;&gt;=&lt;/span&gt; 
    &lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;if&lt;/span&gt; Array&lt;span style=&quot;color:#008c00;&quot;&gt;.&lt;/span&gt;length events &lt;span style=&quot;color:#808030;&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&quot;color:#008c00;&quot;&gt;2&lt;/span&gt; &lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;then&lt;/span&gt;
        failwith &lt;span style=&quot;color:#0000e6;&quot;&gt;&amp;quot;error in getDiff, events array is to small&amp;quot;&lt;/span&gt;
    Array&lt;span style=&quot;color:#008c00;&quot;&gt;.&lt;/span&gt;sortInPlace events
    &lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;let&lt;/span&gt; min &lt;span style=&quot;color:#808030;&quot;&gt;=&lt;/span&gt; events.&lt;span style=&quot;color:#808030;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#008c00;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;]&lt;/span&gt;
    min&lt;span style=&quot;color:#808030;&quot;&gt;,&lt;/span&gt; Array&lt;span style=&quot;color:#008c00;&quot;&gt;.&lt;/span&gt;map &lt;span style=&quot;color:#808030;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;fun&lt;/span&gt; x &lt;span style=&quot;color:#808030;&quot;&gt;-&amp;gt;&lt;/span&gt; x &lt;span style=&quot;color:#808030;&quot;&gt;-&lt;/span&gt; min&lt;span style=&quot;color:#808030;&quot;&gt;)&lt;/span&gt; events.&lt;span style=&quot;color:#808030;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#008c00;&quot;&gt;1&lt;/span&gt;..&lt;span style=&quot;color:#808030;&quot;&gt;]&lt;/span&gt;

&lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;let&lt;/span&gt; &lt;span style=&quot;color:#808030;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;|&lt;/span&gt;Length&lt;span style=&quot;color:#808030;&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;)&lt;/span&gt; arr &lt;span style=&quot;color:#808030;&quot;&gt;=&lt;/span&gt; Array&lt;span style=&quot;color:#008c00;&quot;&gt;.&lt;/span&gt;length arr

&lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;let&lt;/span&gt; &lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;mutable&lt;/span&gt; caseIx &lt;span style=&quot;color:#808030;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color:#008c00;&quot;&gt;1&lt;/span&gt;

&lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;for&lt;/span&gt; events &lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;in&lt;/span&gt; inputSeq &lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;do&lt;/span&gt;

    &lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;let&lt;/span&gt; result &lt;span style=&quot;color:#808030;&quot;&gt;=&lt;/span&gt;
        &lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;match&lt;/span&gt; events &lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;with&lt;/span&gt;
        &lt;span style=&quot;color:#808030;&quot;&gt;|&lt;/span&gt; Length &lt;span style=&quot;color:#008c00;&quot;&gt;0&lt;/span&gt;
        &lt;span style=&quot;color:#808030;&quot;&gt;|&lt;/span&gt; Length &lt;span style=&quot;color:#008c00;&quot;&gt;1&lt;/span&gt; &lt;span style=&quot;color:#808030;&quot;&gt;-&amp;gt;&lt;/span&gt; 0I
        &lt;span style=&quot;color:#808030;&quot;&gt;|&lt;/span&gt; &lt;span style=&quot;color:#008c00;&quot;&gt;_&lt;/span&gt; &lt;span style=&quot;color:#808030;&quot;&gt;-&amp;gt;&lt;/span&gt; 
            &lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;let&lt;/span&gt; min&lt;span style=&quot;color:#808030;&quot;&gt;,&lt;/span&gt; diff &lt;span style=&quot;color:#808030;&quot;&gt;=&lt;/span&gt; getDiff events 
            &lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;let&lt;/span&gt; factor &lt;span style=&quot;color:#808030;&quot;&gt;=&lt;/span&gt; gcdv diff
            &lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;if&lt;/span&gt; min % factor &lt;span style=&quot;color:#808030;&quot;&gt;=&lt;/span&gt; 0I &lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;then&lt;/span&gt; 0I
            &lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;else&lt;/span&gt; factor &lt;span style=&quot;color:#808030;&quot;&gt;-&lt;/span&gt; &lt;span style=&quot;color:#808030;&quot;&gt;(&lt;/span&gt;min % factor&lt;span style=&quot;color:#808030;&quot;&gt;)&lt;/span&gt;

    &lt;span style=&quot;color:#800000;font-weight:bold;&quot;&gt;let&lt;/span&gt; line &lt;span style=&quot;color:#808030;&quot;&gt;=&lt;/span&gt; sprintf &lt;span style=&quot;color:#0000e6;&quot;&gt;&amp;quot;Case #&lt;/span&gt;&lt;span style=&quot;color:#0f69ff;&quot;&gt;%d&lt;/span&gt;&lt;span style=&quot;color:#0000e6;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#0f69ff;&quot;&gt;%s&lt;/span&gt;&lt;span style=&quot;color:#0000e6;&quot;&gt;&amp;quot;&lt;/span&gt; caseIx &lt;span style=&quot;color:#808030;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;|&lt;/span&gt; result&lt;span style=&quot;color:#008c00;&quot;&gt;.&lt;/span&gt;ToString&lt;span style=&quot;color:#808030;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;)&lt;/span&gt;
    outputStr&lt;span style=&quot;color:#008c00;&quot;&gt;.&lt;/span&gt;WriteLine&lt;span style=&quot;color:#808030;&quot;&gt;(&lt;/span&gt;line&lt;span style=&quot;color:#808030;&quot;&gt;)&lt;/span&gt;
    caseIx &lt;span style=&quot;color:#808030;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;-&lt;/span&gt; caseIx &lt;span style=&quot;color:#808030;&quot;&gt;+&lt;/span&gt; &lt;span style=&quot;color:#008c00;&quot;&gt;1&lt;/span&gt;

outputStr&lt;span style=&quot;color:#008c00;&quot;&gt;.&lt;/span&gt;Close&lt;span style=&quot;color:#808030;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;)&lt;/span&gt;
inputStr&lt;span style=&quot;color:#008c00;&quot;&gt;.&lt;/span&gt;Close&lt;span style=&quot;color:#808030;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#808030;&quot;&gt;)&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;Кстати, сразу после начала раунда я обнаружил что на моем домашнем компьютере нет ни Visual Studio, ни интерпретатора python-a, даже несчастного с++ компиялтора нет. Вышел из положения скачав F# CTP, код набирал в vim. F# interpreter – очень удобная штука, я его использовал в интерактивном режиме, в качестве REPL, а так-же для запуска своей писанины :)&lt;/p&gt;</description>
         <author>Евгений Лазин</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-7754674872362895099.post-7402812486923253294</guid>
         <pubDate>Sun, 09 May 2010 14:16:00 +0000</pubDate>
      </item>
      <item>
         <title>SICP и ФП. Хроники мозга. Вырезка #3: Quick Hull</title>
         <link>http://skiminog.livejournal.com/68017.html</link>
         <description>&lt;p&gt;Повторяя прочитанный у Евгения &lt;span class=&quot;ljuser  i-ljuser  i-ljuser-type-P     &quot;&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://antilamer.livejournal.com/profile&quot; class=&quot;i-ljuser-profile&quot;&gt;&lt;img class=&quot;i-ljuser-userhead&quot; src=&quot;http://l-stat.livejournal.net/img/userinfo.gif?v=17080?v=131.4&quot;/&gt;&lt;/a&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://antilamer.livejournal.com/&quot; class=&quot;i-ljuser-username&quot;&gt;&lt;b&gt;antilamer&lt;/b&gt;&lt;/a&gt;&lt;/span&gt;  Кирпичева материал про свертки, залез попутно в область, которую я пока не покрывал: префиксные суммы, сегментированные пробеги, и их связь со сверткой. И обнаружил там весьма занимательный для функциональщика алгоритм для построения выпуклой оболочки под названием &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://algolist.manual.ru/maths/geom/convhull/quickhull.php&quot;&gt;Quick Hull&lt;/a&gt;. Короткую его реализацию с помощью сегментированных пробегов я пока оставил до лучших времен, а вот простой наивный перевод на F# &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://docs.google.com/Doc?docid=dv682st_12drcf56c7&quot;&gt;определения алгоритма&lt;/a&gt; у Кирпичева почему бы и не сделать.&lt;br /&gt;&lt;br /&gt;Тем более что получается это очень просто. Весь код помещается в пределах одного экрана. Вроде бы без багов :)&lt;br /&gt;&lt;br /&gt;&lt;b&gt;UPD:&lt;/b&gt; Поубирал все явные декларации типов в функциях алгоритма. Компилятор F# умный, сам все выводит.&lt;/p&gt;&lt;br /&gt;&lt;div style=&quot;font-family:monospace;font-size:9pt;color:black;background:white;border:1px solid #d0d0d0;&quot;&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;type&lt;/span&gt; Point = &lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { x: float; y: float; }&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color:blue;&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;member&lt;/span&gt; (&amp;lt;) (a: Point, b: Point) =&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; (a.x &amp;lt; b.x) || (a.x = b.x &amp;amp;&amp;amp; a.y &amp;lt; b.y)&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color:blue;&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;member&lt;/span&gt; (-) (a: Point, b: Point) =&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; { x = a.x - b.x; y = a.y - b.y }&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color:blue;&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;member&lt;/span&gt; (^^) (a: Point, b: Point) =&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; a.x * b.y - b.x * a.y&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color:blue;&quot;&gt;override&lt;/span&gt; this.ToString() =&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; sprintf &lt;span style=&quot;color:maroon;&quot;&gt;&amp;quot;(%f, %f)&amp;quot;&lt;/span&gt; this.x this.y&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&amp;nbsp;&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;type&lt;/span&gt; Segment = { start: Point; finish: Point }&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&amp;nbsp;&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;let&lt;/span&gt; quickHull points =&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color:blue;&quot;&gt;let&lt;/span&gt; &lt;span style=&quot;color:blue;&quot;&gt;rec&lt;/span&gt; hullStep line = &lt;span style=&quot;color:blue;&quot;&gt;function&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; | [] &lt;span style=&quot;color:blue;&quot;&gt;-&amp;gt;&lt;/span&gt; [line.start; line.finish]&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; | points &lt;span style=&quot;color:blue;&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color:blue;&quot;&gt;let&lt;/span&gt; p, q, PQ = line.start, line.finish, line.finish - line.start&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&amp;nbsp;&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color:blue;&quot;&gt;let&lt;/span&gt; distKey a = (p - a) ^^ (q - a)&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color:blue;&quot;&gt;let&lt;/span&gt; a = List.maxBy distKey points&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color:blue;&quot;&gt;let&lt;/span&gt; AP, AQ = (p - a), (q - a)&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&amp;nbsp;&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color:blue;&quot;&gt;let&lt;/span&gt; besidesP x = (AP ^^ PQ) * (AP ^^ (x - p)) &amp;lt; 0.0&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color:blue;&quot;&gt;let&lt;/span&gt; besidesQ x = (AQ ^^ (x - q)) * (AQ ^^ PQ) &amp;gt; 0.0&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color:blue;&quot;&gt;let&lt;/span&gt; pointsOfP = List.filter besidesP points&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color:blue;&quot;&gt;let&lt;/span&gt; pointsOfQ = List.filter besidesQ points&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&amp;nbsp;&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color:blue;&quot;&gt;let&lt;/span&gt; ansP = hullStep {start = a; finish = p} pointsOfP&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color:blue;&quot;&gt;let&lt;/span&gt; ansQ = hullStep {start = a; finish = q} pointsOfQ&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; ansP @ ansQ&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&amp;nbsp;&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color:blue;&quot;&gt;let&lt;/span&gt; p, q = List.min points, List.max points&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color:blue;&quot;&gt;let&lt;/span&gt; PQ = q - p&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&amp;nbsp;&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color:blue;&quot;&gt;let&lt;/span&gt; upper (x: Point) = PQ ^^ (x - q) &amp;gt; 0.0&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color:blue;&quot;&gt;let&lt;/span&gt; lower (x: Point) = PQ ^^ (x - q) &amp;lt; 0.0&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color:blue;&quot;&gt;let&lt;/span&gt; upPoints, downPoints = List.filter upper points, List.filter lower points&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&amp;nbsp;&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color:blue;&quot;&gt;let&lt;/span&gt; ansUp = hullStep {start = p; finish = q} upPoints&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style=&quot;color:blue;&quot;&gt;let&lt;/span&gt; ansDown = hullStep {start = q; finish = p} downPoints&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ansUp @ ansDown |&amp;gt; Set.ofList |&amp;gt; Set.toList&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&amp;nbsp;&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;let&lt;/span&gt; example = [ { x = 0.0; y = 0.0 };&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; { x = 0.0; y = 1.0 };&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; { x = 1.0; y = 1.0 };&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; { x = 1.0; y = 0.0 };&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; { x = 0.5; y = 0.8 } ]&lt;/p&gt;&lt;p style=&quot;margin:0px;font-family:monospace;&quot;&gt;&lt;span style=&quot;color:blue;&quot;&gt;let&lt;/span&gt; hull = quickHull example&lt;/p&gt;&lt;/div&gt;</description>
         <guid isPermaLink="false">urn:lj:livejournal.com:atom1:skiminog:68017</guid>
         <pubDate>Fri, 07 May 2010 22:02:21 +0000</pubDate>
      </item>
      <item>
         <title>F# и циклические зависимости.</title>
         <link>http://evgeny-lazin.blogspot.com/2010/05/f.html</link>
         <description>&lt;p&gt;Предметом разговора сегодня будет язык программирования F#, который вызвал у меня неслабую зависимость. Я не буду пока рассказывать чем именно, всему свое время. Вместо этого, я хочу обсудить некоторые “недостатки”.&lt;/p&gt;  &lt;p&gt;Главный “недостаток” этого языка программирования, если конечно судить по записям в блогах и сообщениям на форумах – довольно странный для .NET разработчиков механизм компиляции. В C# или VB.NET, порядок компиляции не имеет значения, программист вообще не имеет возможности на него влиять. Мало того, эти языки позволяют с легкостью делать подобное:&lt;/p&gt;  &lt;pre style=&quot;border-bottom:#cecece 1px solid;border-left:#cecece 1px solid;padding-bottom:5px;background-color:#fbfbfb;min-height:40px;padding-left:5px;width:650px;padding-right:5px;overflow:auto;border-top:#cecece 1px solid;border-right:#cecece 1px solid;padding-top:5px;&quot;&gt;&lt;pre style=&quot;background-color:#fbfbfb;margin:0em;width:100%;font-family:consolas,;font-size:12px;&quot;&gt;&lt;span style=&quot;color:#0000ff;&quot;&gt;class&lt;/span&gt; Foo
&lt;/pre&gt;&lt;pre style=&quot;background-color:#ffffff;margin:0em;width:100%;font-family:consolas,;font-size:12px;&quot;&gt;{  
&lt;/pre&gt;&lt;pre style=&quot;background-color:#fbfbfb;margin:0em;width:100%;font-family:consolas,;font-size:12px;&quot;&gt;  &lt;span style=&quot;color:#0000ff;&quot;&gt;private&lt;/span&gt; Bar bar;  
&lt;/pre&gt;&lt;pre style=&quot;background-color:#ffffff;margin:0em;width:100%;font-family:consolas,;font-size:12px;&quot;&gt;  ...
&lt;/pre&gt;&lt;pre style=&quot;background-color:#fbfbfb;margin:0em;width:100%;font-family:consolas,;font-size:12px;&quot;&gt;}
&lt;/pre&gt;&lt;pre style=&quot;background-color:#ffffff;margin:0em;width:100%;font-family:consolas,;font-size:12px;&quot;&gt;&lt;/pre&gt;&lt;pre style=&quot;background-color:#fbfbfb;margin:0em;width:100%;font-family:consolas,;font-size:12px;&quot;&gt;&lt;span style=&quot;color:#0000ff;&quot;&gt;class&lt;/span&gt; Bar
&lt;/pre&gt;&lt;pre style=&quot;background-color:#ffffff;margin:0em;width:100%;font-family:consolas,;font-size:12px;&quot;&gt;{  
&lt;/pre&gt;&lt;pre style=&quot;background-color:#fbfbfb;margin:0em;width:100%;font-family:consolas,;font-size:12px;&quot;&gt;  &lt;span style=&quot;color:#0000ff;&quot;&gt;private&lt;/span&gt; Foo foo;
&lt;/pre&gt;&lt;pre style=&quot;background-color:#ffffff;margin:0em;width:100%;font-family:consolas,;font-size:12px;&quot;&gt;  ...
&lt;/pre&gt;&lt;pre style=&quot;background-color:#fbfbfb;margin:0em;width:100%;font-family:consolas,;font-size:12px;&quot;&gt;}&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;То есть, определять классы, которые зависят друг от друга (являются взаимно рекурсивными).&amp;#160; Классы Foo и Bar могут быть в разных файлах, это не имеет значения, компилятор C# во всем прекрасно разберется.&lt;/p&gt;

&lt;p&gt;В случае F#, все не так просто. Во первых, файлы проекта компилируются в строго определенном порядке. И от этого порядка зависит – будет ли проект скомпилирован, или нет. Во вторых, этот порядок определяется программистом. В каком порядке следуют файлы в проекте, в том они и будут компилироваться, в этом порядке и будет работать вывод типов. Если класс Bar зависит от класса Foo, то файл, в котором определен класс Foo должен компилироваться раньше чем файл, в котором определен класс Bar. Предыдущий пример, на F# будет выглядеть так:&lt;/p&gt;

&lt;pre style=&quot;border-bottom:#cecece 1px solid;border-left:#cecece 1px solid;padding-bottom:5px;background-color:#fbfbfb;min-height:40px;padding-left:5px;width:650px;padding-right:5px;overflow:auto;border-top:#cecece 1px solid;border-right:#cecece 1px solid;padding-top:5px;&quot;&gt;&lt;pre style=&quot;background-color:#fbfbfb;margin:0em;width:100%;font-family:consolas,;font-size:12px;&quot;&gt;&lt;span style=&quot;color:#0000ff;&quot;&gt;type&lt;/span&gt; Foo =
&lt;/pre&gt;&lt;pre style=&quot;background-color:#ffffff;margin:0em;width:100%;font-family:consolas,;font-size:12px;&quot;&gt;    val bar : Bar
&lt;/pre&gt;&lt;pre style=&quot;background-color:#fbfbfb;margin:0em;width:100%;font-family:consolas,;font-size:12px;&quot;&gt;    ...
&lt;/pre&gt;&lt;pre style=&quot;background-color:#ffffff;margin:0em;width:100%;font-family:consolas,;font-size:12px;&quot;&gt;&lt;/pre&gt;&lt;pre style=&quot;background-color:#fbfbfb;margin:0em;width:100%;font-family:consolas,;font-size:12px;&quot;&gt;&lt;span style=&quot;color:#0000ff;&quot;&gt;and&lt;/span&gt; Bar =
&lt;/pre&gt;&lt;pre style=&quot;background-color:#ffffff;margin:0em;width:100%;font-family:consolas,;font-size:12px;&quot;&gt;    val foo : Foo
&lt;/pre&gt;&lt;pre style=&quot;background-color:#fbfbfb;margin:0em;width:100%;font-family:consolas,;font-size:12px;&quot;&gt;    ...&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;обратите внимание на ключевое слово and – с его помощью в F# определяются взаимно рекурсивные типы. При этом, оба класса должны находится в одном файле.&lt;/p&gt;

&lt;p&gt;Естественно, это вызывает бурю гневных постов в блогах и на форумах, так-как очень далеко от подхода, используемого в C# и VB.NET.&lt;/p&gt;

&lt;p&gt;Так вот, на самом деле – это очень круто! Круто, потому-что нам пришлось явным образом указать – какие классы являются взаимно рекурсивными. Это означает, что внести в код циклическую зависимость можно только специально.&lt;/p&gt;

&lt;p&gt;Явный порядок компиляции – одна из моих любимых особенностей F#, так как она заставляет программиста заранее продумать архитектуру проекта. Допустим у нас есть большой проект, мы условно разделили его на два слоя – представление и бизнес логику. Классы из presentation слоя – используют классы из business layer-a, а тот в свою очередь – никак не зависит от представления. Если все это добро находится в одной сборке, то нам ничто не мешает использовать код из presentation слоя в бизнес логике. Это будет ошибкой проектирования, тем не менее, многие языки программирования позволяют с легкостью это сделать. С F# этот номер не пройдет, так как файлы слоя представления будут компилироваться позже файлов, содержащих бизнес логику.&lt;/p&gt;

&lt;p&gt;Другое преимущество этого подхода состоит в том, что алгоритм вывода типов становится намного проще, а следовательно работает очень быстро. В частности, благодаря этому, подсказки и сообщения об ошибках в IDE появляются практически мгновенно, что не может не радовать :)&lt;/p&gt;</description>
         <author>Евгений Лазин</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-7754674872362895099.post-1770826058357198319</guid>
         <pubDate>Tue, 04 May 2010 23:08:00 +0000</pubDate>
      </item>
      <item>
         <title>Работа над ошибками</title>
         <link>http://dsorokin.blogspot.com/2010/04/blog-post.html</link>
         <description>&lt;div&gt;Выпустил новую версию 1.0.4.0 библиотеки моделирования &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://sourceforge.net/projects/aivika/&quot;&gt;Aivika&lt;/a&gt; на F#. В прежней версии обнаружил ошибку в реализации блоков try-finally и try-with для вычислительного выражения dynamicscont. По своей сути это частный случай монадного трансформера, построенного на основе продолжения. Дело в том, что фактически надо хранить два продолжения, а не одно. Первое продолжение используется для основной ветки вычислений. Второе продолжение - для обработки исключительных ситуаций. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Обновленный тип выглядит так:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;code&gt;type DynamicsCont&amp;lt;'a&amp;gt; = Dynamics&amp;lt;('a -&amp;gt; unit) * (exn -&amp;gt; unit)&amp;gt; -&amp;gt; Dynamics&amp;lt;unit&amp;gt;&lt;/code&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Выводится из следующего типа Cont с учетом одного упрощения, характерного именно для монадного типа Dynamics:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;code&gt;type Cont&amp;lt;'a&amp;gt; = ('a -&amp;gt; unit) * (exn -&amp;gt; unit) -&amp;gt; unit&lt;/code&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Здесь функция от двух продолжений: основного потока вычислений и обработчика ошибок. Особенность заключается в том, что монадический переход bind должен быть защищен в узком месте блоком try. В случае возникновения ошибки должно активироваться второе продолжение для обработки ошибок.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Сначала я составил необходимые функции для Cont. Потом сверил с реализацией стандартного async. Убедился, что все правильно. Затем перенес на тип DynamicsCont. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Если есть интерес, то я мог бы написать эти функции для Cont. В интернете такой информации не видел. Там обычно рассматривается упрощенный случай из одного продолжения, не учитывающий обработку блоков try.&lt;/div&gt;</description>
         <author>dsorokin</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-8641042312683198534.post-9184780191836730441</guid>
         <pubDate>Sat, 01 May 2010 09:36:00 +0000</pubDate>
      </item>
      <item>
         <title>Aivika версии 1.0.3.0</title>
         <link>http://dsorokin.blogspot.com/2010/04/aivika-1030.html</link>
         <description>&lt;div&gt;Выложил новую версию библиотеки моделирования &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://sourceforge.net/projects/aivika/&quot;&gt;Aivika&lt;/a&gt;. Написана она на F# с использованием двух монад. Эта библиотека позволяет создавать и запускать имитацию гибридных моделей. Сейчас охватывается системная динамика (System Dynamics) и Discrete Event Simulation (как time-driven, event-driven так и process-driven simulation). В планах добавление agent-based modeling. В тестах обгоняет SimPy примерно в два раза на его же типе задач, хотя Aivika умеет значительно больше. Есть недописанный обрывок документации. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Сейчас не буду вдаваться в маркетинговые лозунги. Напишу лишь пару технических деталей. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;В основе лежит (императивная) монада Dynamics, которая умеет системную динамику, т.е. запускать имитацию и интегрировать динамическую систему. Что характерно, дифф.-уравнения задаются в высшей степени декларативно. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Поверх этой монады есть ее продолжение DynamicsCont&amp;lt;’a&amp;gt; = Dynamics&amp;lt;’a -&amp;gt; unit&amp;gt; -&amp;gt; Dynamics&amp;lt;unit&amp;gt;. Фишка в том, что используя синтаксис вычислительный выражений, можно писать как бы “обычный” код на F# в монаде DynamicsCont, который будет временами прерываться. Это нужно для реализации “процессов”, которые могут усыпляться, просыпаться, ставиться в очередь на выполнение в такое-то время, блокироваться для захвата разделяемого ресурса и т.д. Все это предполагается в process-driven simulation. Используются свойства продолжения.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Так вот, такой код, используя лифт, может вызывать вычисления в исходной монаде Dynamics, т.е. интегрироваться с динамическими системами. Частный случай монадного трансформера. Это позволяет строить гибридный модели, где одна часть может быть описана дифф.урами, а другая задаваться дискретными процессами. В перспективе сюда добавлю агенты –  вся инфраструктура готова.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Все хозяйство представляет собой embedded domain specific language (eDSL). Поскольку внутри используются монады, то легко встраивать вызовы функций .NET внутрь симуляции через вычислительные выражения, т.е. через монадический bind. eDSL же дает возможность встраивать симуляции в обычные .NET приложения. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Подозреваю, что подобные системы стоят дорого. Проблема в том, что мой код получился очень маленьким по объему (90 кб)… и не таким быстрым.&lt;/div&gt;</description>
         <author>dsorokin</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-8641042312683198534.post-8472131963251076810</guid>
         <pubDate>Wed, 14 Apr 2010 11:40:00 +0000</pubDate>
      </item>
      <item>
         <title>Работаем с F# в Emacs</title>
         <link>http://samolisov.blogspot.com/2010/04/f-emacs.html</link>
         <description>Сегодня мы поговорим о том, как использовать замечательный редактор Emacs для разработки на языке F# от одной небезызвестной корпорации. Не секрет, что синтаксис языка программирования F# был чуть менее, чем целиком позаимстован с синтаксиса OCaml, поэтому, чтобы на нем было удобно программировать в Emacs - достаточно адаптировать режим для OCaml, добавив работу с отступами, потому что в F# как и</description>
         <author>Pavel Samolisov</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3043523252258851613.post-935694566145871895</guid>
         <pubDate>Sun, 04 Apr 2010 12:48:00 +0000</pubDate>
         <media:thumbnail height="72" url="http://4.bp.blogspot.com/_TJ8tF1fr0PM/S7hdcMWBIOI/AAAAAAAAATs/89ytGktITZw/s72-c/1.png" width="72" xmlns:media="http://search.yahoo.com/mrss/"/>
      </item>
      <item>
         <title>Software People 2010</title>
         <link>http://ru-fsharp.livejournal.com/2353.html</link>
         <description>2010-04-22 в Москве пройдет конференция «&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://softwarepeople.ru/sp2010/&quot;&gt;Software People 2010&lt;/a&gt;». В числе выступающих значится и Дон Сайм с докладом «F# — Bringing Functional Programming into the Mainstream». На случай, если кто из участников сообщества будет присутствовать (что всем рекомендую, мероприятие обещает быть интересным) — убедительно прошу подробно конспектировать :)&lt;br /&gt;&lt;br /&gt;Сергей Зефиров будет брать интервью, он предлагает задать вопросы: &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://thesz.livejournal.com/1079695.html&quot;&gt;http://thesz.livejournal.com/1079695.html&lt;/a&gt;</description>
         <author>Qbit</author>
         <guid isPermaLink="false">urn:lj:livejournal.com:atom1:ru_fsharp:2353</guid>
         <pubDate>Sat, 03 Apr 2010 20:33:55 +0000</pubDate>
      </item>
      <item>
         <title>Вуду^5</title>
         <link>http://metaclass.livejournal.com/476128.html</link>
         <description>Генерил кодогенератором опердень, понадобилось добавить способ описания предикатов проверки прав доступа пользователей (типа &quot;этот пользователь видит только данные своего филиала, или же только относящиеся к налоговой инспекции в городе где этот филиал&quot;). Ну отдельные проверки понятно - запрос типа &quot;exists(select 1 from UserDepartments where UserID=current_user and DeptID=OperdenTable_DeptID)&quot; но мне понадобилось их объединять в итоговый предикат отдельно описанными логическими функциями. &lt;br /&gt; Не нашел ничего лучше, как вкрутить первый попавшийся в гугле под руки парсер s-выражений на F#, который был там приведен как пример использования fsyacc и fslex, затем буквально за 5 минут написал конвертор этих выражений в условия для where в sql-запросах.&lt;br /&gt;&lt;br /&gt; Т.е., ко всей этой опердени на смеси SQL,F#,дельфи и жутких xml-метаданных еще добавилось и подмножество лиспа :)&lt;br /&gt; &lt;br /&gt; Кстати, весь модуль опердени (2 справочника, 4 ведомости, куча проверок, внешних ключей и зависимостей от других модулей)), ради которого это все затевалось, за полдня на оном безумии сделала специально вышедшая из декрета сотрудница.&lt;br /&gt;&lt;br /&gt; Но, тем не менее, теперь я понимаю, почему нормальных готовых решений с кодогенерацией опердени почти не существует. Там надо учесть столько мелочей (в модели и кодогенераторе), что это пригодно либо только для очень ограниченных решений, либо становится настолько сложным, что никто этим пользоваться не станет.</description>
         <guid isPermaLink="false">urn:lj:livejournal.com:atom1:metaclass:476128</guid>
         <pubDate>Wed, 31 Mar 2010 17:55:20 +0000</pubDate>
      </item>
      <item>
         <title>F#, Reflector, Firebird и кодогенерация (ака вуду^4)</title>
         <link>http://metaclass.livejournal.com/474720.html</link>
         <description>Смотрю .NET Reflector на внутренности программы на F# и всячески торчу. &lt;br /&gt; 50 строк на F# разворачивается в четыре автосгенеренных класса-замыкания, автоматически управляющих десятком объектов для доступа к базе данных и все это в итоге представляет собой функцию &quot;коннект к Firebird -&amp;gt; хитрозаколдованная структура с данными&quot;.&lt;br /&gt;&lt;br /&gt; А я еще собираюсь и сам код на F# сгенерить из результатов парсинга запросов в БД, чтобы вообще руками ничего не писать, кроме SQL запросов. Т.е. &quot;чтобы было все и мне за это ничего не было&quot;.&lt;br /&gt; &lt;br /&gt;Т.е. идея примерно такая: &lt;br /&gt;1)есть структура реляционной БД - мне в ее категориях проще проектировать и думать.&lt;br /&gt;2)есть запросы к ней и связи между ними - которые мне тоже проще придумать, чем делать маппинги в ORM или писать запросы на LINQToSQL, который вообще не факт что поддерживается для Firebird.&lt;br /&gt;&lt;br /&gt;Я описываю запросы на SQL, кодогенератором автоматически конвертирую их в функции F# вида (&quot;коннект к БД&quot; -&amp;gt; &quot;параметр запроса 1&quot; -&amp;gt; &quot;параметр запроса 2&quot; -&amp;gt; ... -&amp;gt; &quot;ленивая последовательность записей с результатами&quot;). &lt;br /&gt; Затем полученные функции я собираю в законченную структуру, описывая связи между ними уже на F# и получаю на выходе что-то вроде &quot;Запись, поля которой представляют собой ленивые последовательности с результами запросов, причем внутри эти результатов могут быть такие же поля - ленивые последовательности с результатами вложенных запросов&quot;.&lt;br /&gt; &lt;br /&gt; Не совсем понятно, почему бы это все не сделать на обычном NHibernate, но тут ключевой аспект - что работа не сущностями и маппингами их на базу, а с результатами произвольных SQL-запросов, что мне гораздо более важно.</description>
         <guid isPermaLink="false">urn:lj:livejournal.com:atom1:metaclass:474720</guid>
         <pubDate>Sat, 27 Mar 2010 08:45:35 +0000</pubDate>
      </item>
      <item>
         <title>Обратные связи</title>
         <link>http://dsorokin.blogspot.com/2010/03/blog-post.html</link>
         <description>Язык F# в наследство от OCaml получил интересную возможность задавать рекуррентные отношения декларативно, как есть. Например, в моих сообщениях постоянно используется одна и та же система дифф-уров. Теперь ее можно переписать на F# следующим образом:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&amp;nbsp; let rec a = integF (lazy (- ka*a)) 100.0&lt;br /&gt;&amp;nbsp; and b = integF (lazy (ka*a - kb*b)) 0.0&lt;br /&gt;&amp;nbsp; and c  = integF (lazy (kb*b)) 0.0&lt;br /&gt;&amp;nbsp; and ka = 1.0&lt;br /&gt;&amp;nbsp; and kb = 1.0&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Это – работающий пример, где функция &lt;code&gt;integF&lt;/code&gt; возвращает интеграл (как некое вычисление в монаде моделирования) по заданной производной и начальному значению. Здесь мы видим, что (1) переменные можно задавать произвольно без указания зависимости, (2) обратные связи задаются через явную ленивость. Фактически есть еще третий очень важный пункт: (3) компилятор сам следит за разрешимостью системы (в отличие от того же Haskell). Мне особенно нравится этот пункт, поскольку он делает подобный метод пригодным для широкого практического применения. Например, у нас имеется eDSL, а неискушенные пользователи задают свои системы. Компилятор сам все проверит и укажет на ошибку в случае необходимости. Неоценимое свойство.&lt;br /&gt;&lt;br /&gt;Правда, в случае одной более сложной системы компилятор F# (v1.9.9.9) почему-то неправильно вывел переменные. Соответствующий bug report был отослан. Я думаю, что это – временное явление.&lt;br /&gt;&lt;br /&gt;Рекуррентные отношения можно задавать и более хитрым способом, используя генераторы массивов:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&amp;nbsp; let smoothNI (x: Lazy&amp;lt;Dynamics&amp;lt;float&amp;gt;&amp;gt;) (t: Lazy&amp;lt;Dynamics&amp;lt;float&amp;gt;&amp;gt;) n (i: Dynamics&amp;lt;float&amp;gt;) =&lt;br /&gt;&amp;nbsp;&amp;nbsp; let rec s = [|&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for k = 0 to n-1 do&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if k = 0 then&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; yield integ (lazy ((x.Value - s.[k]) / (t.Value / (float n)))) i&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; yield integ (lazy ((s.[k-1] - s.[k]) / (t.Value / (float n)))) i |]&lt;br /&gt;&amp;nbsp;&amp;nbsp; in s.[n-1]&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Здесь возвращается функция (значение в монаде моделирования), которая называется &lt;i&gt;экспоненциальной порядка n сглаживающей x по времени t с начальным значением i&lt;/i&gt;. &lt;br /&gt;&lt;br /&gt;Мне нравится.</description>
         <author>dsorokin</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-8641042312683198534.post-1303203619028229581</guid>
         <pubDate>Tue, 23 Mar 2010 19:31:00 +0000</pubDate>
      </item>
      <item>
         <title>C# Zen Coding уже на F#</title>
         <link>https://nesteruk.wordpress.com/2010/03/05/c-zen-coding-%d1%83%d0%b6%d0%b5-%d0%bd%d0%b0-f/</link>
         <description>В моем предыдущем посте, где я описал идею CSharpZen, я пообещал две вещи &amp;#8211; дописать расширение для Visual Studio 2010, а также записать вебкаст того, как это можно использовать. Но пока я дописывал код для трансформатора, мне снова показалось что код может стать более понятным если его переписать на F#. И понеслось&amp;#8230; Почему опять F#? [&amp;#8230;]&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;https://pixel.wp.com/b.gif?host=nesteruk.wordpress.com&amp;#038;blog=373435&amp;#038;post=271&amp;#038;subd=nesteruk&amp;#038;ref=&amp;#038;feed=1&quot; width=&quot;1&quot; height=&quot;1&quot;/&gt;</description>
         <guid isPermaLink="false">http://nesteruk.wordpress.com/?p=271</guid>
         <pubDate>Fri, 05 Mar 2010 19:45:39 +0000</pubDate>
         <content:encoded><![CDATA[<p>В моем <a rel="nofollow" target="_blank" href="https://nesteruk.wordpress.com/2010/03/03/%D1%81%D0%BE%D0%BA%D1%80%D0%B0%D1%89%D0%B5%D0%BD%D0%BD%D1%8B%D0%B9-%D0%B3%D0%B5%D0%BD%D0%B5%D1%80%D0%B0%D1%82%D0%BE%D1%80-c-%D0%B2-%D1%81%D1%82%D0%B8%D0%BB%D0%B5-zen-coding/">предыдущем посте</a>, где я описал идею CSharpZen, я пообещал две вещи &ndash; дописать расширение для Visual Studio 2010, а также записать вебкаст того, как это можно использовать. Но пока я дописывал код для трансформатора, мне снова показалось что код может стать более понятным если его переписать на F#. И понеслось&hellip;</p>
<p>Почему опять F#? Я уже <a rel="nofollow" target="_blank" href="https://nesteruk.wordpress.com/2010/02/18/%D0%BE%D0%B1%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0-%D1%81%D1%82%D1%80%D0%BE%D0%BA-%D1%81%D1%80%D0%B0%D0%B2%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5-c-%D0%B8-f/">писал</a> о том что строковые трансформации лучше делать на F# и что они хоть и работают медленнее (хотя Zen Coding вообще написан на питоне и использует DLR), но код легче понимать. А у меня еще появляется работа с массивами неопределенной длины (например при обработке свойств может быть <code>p:sb x</code> а может <code>p:new sb x</code>) что весьма неплохо ложится на pattern matching.</p>
<p>В этом посте я хочу пройтись по проблемам прошлого поста и показать как в очередной раз F# позволяет нам производить аналогичный код но в более понятной форме.</p>
<h3>Проблема использования метаданных</h3>
<p>Помните как мы определили метаданные для видимости как аттрибуты? Так вот, этот подход хоть и казался полезным (держим метаданные рядом с полями), но на самом деле был жутко неудобным. В F# такой подход не сработает. Вместо этого, мы определяем перечисление отдельно&hellip;</p>
<pre>type Visibility =
| Public
| Internal
| ProtectedInternal
| Protected
| Private
</pre>
<p>&hellip;а метаданные определяем как массив кортежей которые содержат все нужные нам данные.</p>
<pre>type Constants =
  static member visibilityTokens =
    [|(Visibility.Public, &quot;+&quot;, &quot;public&quot;); 
      (Visibility.Internal, @&quot;&#92;&quot;, &quot;internal&quot;);
      (Visibility.ProtectedInternal, @&quot;/&#92;&quot;, &quot;protected internal&quot;);
      (Visibility.Protected, @&quot;/&quot;, &quot;protected&quot;);
      (Visibility.Private, &quot;-&quot;, &quot;private&quot;)|]
  ...
</pre>
<p>Теперь для поиска конретных элементов метаданных мы просто используем <code>Array.find</code> по кортежам. Например, та же функция вытаскивания <code>Visibility</code> из начала строки теперь выглядит вот так:</p>
<pre>static member getVisibilityToken (entry:String) =
  try
    let idx = Constants.visibilityTokens |&gt; Array.findIndex(fun (a,b,c) -&gt; entry.StartsWith(b))
    let (a, b, c) = Constants.visibilityTokens.[idx]
    (a, entry.Replace(b, String.Empty))
  with
    :? KeyNotFoundException -&gt;
       let (a, b, c) = Constants.visibilityTokens.[0]
       (a, entry)
</pre>
<h3>Свойства расширения</h3>
<p>F# знаменит тем что можно делать не только extension methods но и extension properties. Это хорошо. Единственная проблема это то, что методы расширения приходится класть в отдельный модуль, а я это не люблю &ndash; предпочитаю держать все в одном файле и типе, безо всяких там модулей. А тут не получилось &ndash; пришлось описывать все отдельно:</p>
<pre>module Extensions =
  type String with
    member x.Cap =
      let parts = x.Split([|'_'|], StringSplitOptions.RemoveEmptyEntries)
      parts |&gt; Array.map(fun f -&gt; Char.ToUpper(f.[0]).ToString() +
               (if f.Length &gt; 1 then f.Substring(1) else String.Empty))
            |&gt; String.Concat
</pre>
<p>Этот код вообще эклектичен &ndash; взять хотя бы «заинлайненый» блок <code>if-then-else</code> прямо внутри <code>map</code>-а. Это что-то. И это что-то не очень-то читабельно. Хотя кому как.</p>
<h3>Сборщик кода</h3>
<p>Помните <code>CodeBuilder</code>? Так вот, решил я его на F# переписать. В чем-то он лучше, но вот навязчивое желание F# сохранять результаты вычислений или их игнорировать весьма раздражает. Код ниже дает качественно новое определение фразе «послать в игнор»:</p>
<pre>type CodeBuilder(spaces) =
  let mutable indent = 0
  let sb = StringBuilder()
  member x.IndentText =
    String.Empty.PadRight(spaces * indent)
  member x.Indent() =
    indent &lt;- indent + 1
    x
  member x.Unindent() =
    indent &lt;- Math.Max(0, indent - 1)
    x
  member x.Append(text:String) =
    sb.Append(x.IndentText).Append(text) |&gt; ignore
    x
  member x.AppendLine(text:String) =
    sb.Append(x.IndentText).AppendLine(text) |&gt; ignore
    x
  override x.ToString() =
    sb.ToString()
</pre>
<h3>Неадекват с мутабельностью и null</h3>
<p>Кажется я уже об этом как-то писал. Суть в том, что F# лютой ненавистью ненавидит мутабельность и <code>null</code>. То есть он их поддерживает, но чтобы их использовать&hellip; короче Жигули тоже поддерживают езду по дороге, скажем так. Но то, что я вам сейчас покажу это вообще лебединая песня.</p>
<p>Для начала напомню что для того чтобы значение можно было изменять, его нужно пометить как <code>mutable</code> и для записи использовать оператор <code>&lt;-</code>:</p>
<pre>let mutable x = 0
x &lt;- 2
</pre>
<p>Все бы хорошо, но это нелегитивно внутри паттерн-мэтчинга:</p>
<pre>match myDrug with
| Vicodin -&gt; x &lt;- 2 // Вам нельзя.
</pre>
<p>Суть в том, что при таком раскладе вы больше не можете пользоваться «обычным» подходом, вам нужно пересесть на синтаксис который использует &lsquo;ref cells&rsquo;. Я даже это переводить не буду, <a rel="nofollow" target="_blank" href="http://lorgonblog.spaces.live.com/blog/cns!701679AD17B6D310!677.entry">почитать можно тут</a>. Если коротко, то используется совсем другой синтаксис:</p>
<pre>let x = ref 0
x := !x + 1
</pre>
<p>А теперь представьте что вам нужно делать то же самое но для nullable-полей. Помните мои меременные <code>context</code> и <code>rootContext</code>? Вот-вот. Они nullable, и как вы помните, F# не поддерживает эту парадигму (точнее поддерживает, но через одно место) в результате чего мне не написать подобное:</p>
<pre>let context:IVisitable = null     // fail
let context:IVisitable = ref null // epic fail
</pre>
<p>На самом деле, F# имеет свою парадигму <code>option&lt;'t&gt;</code> для подобных вещей. Только она тоже сработает только после дозы шаманства:</p>
<pre>let context : IVisitable option = ref none // FAIL
let context : Ref&lt;IVisitable option&gt; = ref None // OK, finally *phew*
</pre>
<p>Имхо, это просто <strong>умопомрачительно</strong>. Вы можете себе представить индийскую аутсорсинговую компанию, в которой программисты будут разбираться с подобным кодом? Я &ndash; нет.</p>
<h3>Мутабельность переменных</h3>
<p>И еще про мутабельность. В свое время я <a rel="nofollow" target="_blank" href="http://www.gotdotnet.ru/blogs/nesteruk/4296/">написал статейку</a> про то как я использую F# DSL для оценки проектов. Так вот, там фигурирует такая неопрятная вещь как публичное поле-список:</p>
<pre>[&lt;DefaultValue&gt;] val mutable Groups : Group list
</pre>
<p>Для отказа от <code>List&lt;T&gt;</code> реальных причин нет &ndash; зато есть желание делать все чуть более «функционально». За это мы платим тем, что при добавлении элемента, список полностью заменяется. Не знаю стоимость этой операции, возможно не так дорого, но выглядит странно.</p>
<pre>x.Groups &lt;- newGroup :: x.Groups
</pre>
<p>Зато теперь я могу показать как выглядит определение пространства имен:</p>
<pre>type Namespace() =
  [&lt;DefaultValue&gt;] val mutable Name : String
  [&lt;DefaultValue&gt;] val mutable Classes : Class list
  ...
</pre>
<p>Вот вам и ужасный синтаксис во всей «красе». Зато все работает. Главные плюсы вообщем-то не здесь, а в паттерн-матчинге самого парсера.</p>
<h3>Паттерн матчинг рулит</h3>
<p>Вот собственно где все самое интересное. То, как организован паттер-матчинг в F# позволяет нам лаконично (ненавижу это слово!) описывать разные условия. Вот небольшой пример:</p>
<pre>// split the new classifier and match against it
let parts = x.splitToList(newClassifier, ':')
match parts with
| (* NAMESPACE *) &quot;ns&quot; :: tail -&gt;
  let ns = Namespace()
  match tail with
  | name :: _ -&gt; ns.Name &lt;- name
  | _ -&gt; ns.Name &lt;- co.DefaultNamespace
  let nsv = ns :&gt; IVisitable
  context := Some nsv
  setRootContext nsv
</pre>
<p>Получив классификатор, мы можем проверить, есть у него имя или нет. При этом избыточные элементы мэтчинга отбрасываются. Но если нам вдруг понадобится иметь «сложные» классификаторы вроде <code>a:b:c</code> то добавить их поддержку проще простого &ndash; это всего лишь еще один кейс:</p>
<pre>| name :: somethingElse :: -&gt; // что-то умное
</pre>
<p>Зато гибкость теряется в весьма неудобной (излишней) конверсии <code>Namespace</code> в <code>Visitable</code>. О да, кстати, давайте я быстренько покажу как работают интерфейсы в F#.</p>
<h3>Интерфейсы</h3>
<p>У нас всего один интерфейс &ndash; <code>IVisitable</code>. Но в F# ключевое слово <code>interface</code> используется только когда вы <em>реализуете</em> интерфейс в отдельном классе. Если вы просто хотите объявить интерфейс, то делаете класс с абстрактными объявлениями методов:</p>
<pre>type IVisitable = 
  abstract Visit : CodeBuilder * ConversionOptions -&gt; unit
</pre>
<p>Реализация интерфейса всегда явная, т.е. вы прописываете у какого интерфейса и что вы реализуете. Вот пример полного определения класса <code>Namespace</code>:</p>
<pre>type Namespace() =
  [&lt;DefaultValue&gt;] val mutable Name : String
  [&lt;DefaultValue&gt;] val mutable Classes : Class list
  interface IVisitable with
    member x.Visit(cb, co) =
      cb.Append(&quot;namespace &quot;).Append(x.Name.Cap).AppendLine(&quot; {&quot;).Indent() |&gt; ignore
      List.iter(fun c -&gt; (c :&gt; IVisitable).Visit(cb, co)) |&gt; ignore
      cb.Unindent().AppendLine(&quot;}&quot;) |&gt; ignore
</pre>
<h3>Многоуровневый паттерн-мэтчинг</h3>
<p>В парсере ни много ни мало 5 (пять!!!) уровней паттерн-мэтчинга. Вот четыре их них которые задействованы в разборе определения класса:</p>
<pre>| (* CLASS *) &quot;c&quot; :: tail -&gt;
  // get the name
  match tail with
  | [] -&gt; raise(Exception(&quot;Class is missing a name&quot;))
  | name :: _ -&gt;
    let c = Class(name, visibility)
    let cv = c :&gt; IVisitable
    context := Some cv
    match !rootContext with
    | Some(x) -&gt;
      match x with
      | :? Namespace as ns -&gt; ns.Classes &lt;- c :: ns.Classes
      | _ -&gt; ()
    | None -&gt; ()
    setRootContext cv
</pre>
<p>Поскольку класс обязательно нужно положить внутрь простанства имен (если таковое имеется), нам приходится делать двойное сравнение с <code>Option&lt;Namespace&gt;</code> &ndash; сначала нужно проверить что это действительно <code>Some(x)</code>, а потом проверить что тип совпадает (мало ли&hellip;). Проблема в том, что само по себе <code>Ref&lt;Namespace option&gt;</code> не ведет себя полиморфно и одним оператором <code>:?</code> в мэтче не обойтись. А жаль. Было бы удобно.</p>
<h3>Реализация свойств</h3>
<p>Ну и последний вынос мозга на сегодня. Помните я говорил что в свойство можно вставлять слово <code>new</code>? Интересно, но pattern matching возвращает значения. В контексте свойства мы можем взять свойство <code>args</code> (хвост наших токенов) и вернуть из него кортеж!</p>
<pre>let (name, mustInit, skipCount) = match args with
| name :: _ when typeName.IsNotAClassifier -&gt; (name, false, 1)
| &quot;new&quot; :: name :: _ when typeName.IsNotAClassifier -&gt; (name, false, 2)
| _ -&gt; raise(Exception(&quot;Property name is missing&quot;))
let p = Property(name, visibility, typeName, mustInit)
</pre>
<p>Угадайте зачем нужен <code>skipCount</code>. На самом деле он нужен чтобы «отмотать» несколько первых элементов списка <code>args</code> для последующей обработки. Сама отмотка реализована достаточно брутально:</p>
<pre>let rec skipElements count theList =
  match theList with
  | h :: t when count &gt; 0 -&gt; skipElements (count-1) t
  | _ -&gt; theList
</pre>
<p>Думаете что <code>theList</code> должен быть первым параметром? А вот и нет. Если определить его именно так, можно получить частичное применение «огрызка» нашего списка токенов:</p>
<pre>args |&gt; skipElements 2 |&gt; buildStructure
</pre>
<p>Вот собственно зачем нам был нужен <code>skipElements</code>.</p>
<h3>Заключение</h3>
<p>Интересно почему обработка строк и массивов всегдя тянет меня на F# &ndash; ведь в нем море проблем в которых можно утонуть и, что самое главное, когда пишешь код в нефункциональном стиле, написание занимает в 4 раза больше времени чем на C#. Возможно имеет больший смысл писать обработку на кастомном DSL, предназначенном именно для таких задач. А на чем писать такой DSL? Возможно на F#.</p>
<p>Я обновил проект, так что если интересно, весь описанный в этом посте F# код лежит <a rel="nofollow" target="_blank" href="http://bitbucket.org/nesteruk/csharpshorthand/">в репозитарии</a>.</p>
<p>Интересное наблюдение: после нескольких часов мучений с F# чувствую себя не героем а идиотом. К чему бы это?&nbsp;■</p><br />Filed under: <a rel="nofollow" target="_blank" href='https://nesteruk.wordpress.com/category/c/'>C#</a>, <a rel="nofollow" target="_blank" href='https://nesteruk.wordpress.com/category/net/f/'>f#</a>  <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gocomments/nesteruk.wordpress.com/271/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/nesteruk.wordpress.com/271/"/></a> <img alt="" border="0" src="https://pixel.wp.com/b.gif?host=nesteruk.wordpress.com&#038;blog=373435&#038;post=271&#038;subd=nesteruk&#038;ref=&#038;feed=1" width="1" height="1"/>]]></content:encoded>
         <media:content medium="image" url="https://0.gravatar.com/avatar/f01cbd2238e2a78e4c43fa596f51d6a1?s=96&amp;amp;d=https%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&amp;amp;r=PG">
            <media:title type="html">nesteruk</media:title>
         </media:content>
      </item>
      <item>
         <title>Устанавливаем F# и FSharp.PowerPack под Mono</title>
         <link>http://samolisov.blogspot.com/2010/02/f-fsharppowerpack-mono.html</link>
         <description>Суровому челябинскому программисту захотелось экзотики. А что у нас является экзотикой? Правильно - продукция маленькой и незаметной компании из Redmond'а. В частности - ее платформа .NET и набирающий популярность функциональный язык программирования F#. Вот об установке этого чуда под Mono - открытую реализацию CLR под *nix подобные ОС мы и поговорим.Прежде всего следует установить сам Mono,</description>
         <author>Pavel Samolisov</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3043523252258851613.post-2302119632731222351</guid>
         <pubDate>Sat, 20 Feb 2010 09:14:00 +0000</pubDate>
         <media:thumbnail height="72" url="http://3.bp.blogspot.com/_TJ8tF1fr0PM/S3-QsY20tQI/AAAAAAAAASk/LYWvVvsEjZU/s72-c/1.png" width="72" xmlns:media="http://search.yahoo.com/mrss/"/>
      </item>
      <item>
         <title>Обработка строк — сравнение C# и F#</title>
         <link>https://nesteruk.wordpress.com/2010/02/18/%d0%be%d0%b1%d1%80%d0%b0%d0%b1%d0%be%d1%82%d0%ba%d0%b0-%d1%81%d1%82%d1%80%d0%be%d0%ba-%d1%81%d1%80%d0%b0%d0%b2%d0%bd%d0%b5%d0%bd%d0%b8%d0%b5-c-%d0%b8-f/</link>
         <description>&lt;p&gt;У меня есть приложение, с помощью которого я пишу статьи вроде этой. Называется это приложение TypograFix и суть его в том, что оно помогает мне готовить тексты к публикации в итернете. Одна из фич этого приложения &amp;#8211; правильное типографирование текста, которое делается с помощью парсера, который обходит текст и производит нужные замены (например, меняет &lt;code&gt;--&amp;#62;&lt;/code&gt; на &lt;code&gt;--&amp;#38;gt;&lt;/code&gt; что до читателя доходит как &amp;#8594;. До сегоняшнего момента, код который делает эту замену был написал на C#. Читается он, прямо скажем, сложно. В этом посте я хочу показать как можно написать подобный парсер на F#, и в чем отличия подобного подхода.&lt;/p&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;https://pixel.wp.com/b.gif?host=nesteruk.wordpress.com&amp;#038;blog=373435&amp;#038;post=216&amp;#038;subd=nesteruk&amp;#038;ref=&amp;#038;feed=1&quot; width=&quot;1&quot; height=&quot;1&quot;/&gt;</description>
         <guid isPermaLink="false">http://nesteruk.wordpress.com/?p=216</guid>
         <pubDate>Thu, 18 Feb 2010 10:32:42 +0000</pubDate>
         <content:encoded><![CDATA[<p>У меня есть приложение, с помощью которого я пишу статьи вроде этой. Называется это приложение TypograFix и суть его в том, что оно помогает мне готовить тексты к публикации в итернете. Одна из фич этого приложения &ndash; правильное типографирование текста, которое делается с помощью парсера, который обходит текст и производит нужные замены (например, меняет <code>--&gt;</code> на <code>--&amp;gt;</code> что до читателя доходит как &rarr;. До сегоняшнего момента, код который делает эту замену был написал на C#. Читается он, прямо скажем, сложно. В этом посте я хочу показать как можно написать подобный парсер на F#, и в чем отличия подобного подхода.</p>
<p>Было бы здорово, если бы для замены определенных последовательностей в тексте можно было использовать <code>String.Replace()</code> или на худой конец <code>Regex.Replace()</code>. К сожалению, для HTML это не вариант &ndash; вам нужно знать не только местоположение символа, но также и <em>контекст</em>, то есть общую ситуацию в которой парсер находится в данный момент. Например, если вы в теге <code>&lt;code&gt;</code>, то естественно что замены кавычек делать не стоит. Более того, подход при котором в конце получается объектная модель (например с использованием Microsoft.mshtml или другого парсера) мне тоже не подходит т.к. я люблю периодически отказываться от тегов в пользу символьной репрезентации &ndash; например я использую символы <code>{{</code> и <code>}}</code> для разделения блоков кода.</p>
<p>Так вот, к чему это я? На данный момент, мой подход можно проиллюстрировать вот так:</p>
<pre>public string Transform(string text)
{
  var sb = new StringBuilder();
  for (int i = 0; i &lt; text.Length; ++i)
  {
    switch (text[i])
    {
      case '-':
        if (text[i+1] == '-' &amp;&amp; text[i+2] == '&gt;')
        {
          sb.Append(&quot;&amp;rarr;&quot;);
          i += 2;
          continue;
        }
        else goto default;
    }
  }
}
</pre>
<p>Согласитесь, выглядит не очень. У меня сейчас этот метод (с тысячью всяких примочек) занимает несколько сотен строк кода, и абсолютно не рефакторится по причине завязки на разные состояния взаимодействия (большинство из которых вообще представляют из себя поля на уровне класса).</p>
<p>Как нам может помочь F#? В принципе, он может дать нам возможность лучше разделить наш код на отдельные кейсы (например &ldquo;кавычки&rdquo; или &ldquo;тире и прочерки&rdquo;) которые нам нужно обрабатывать. Единственная проблема &ndash; нам придется отказаться от строк в пользу списков, что безусловно ударит по производительности. Моя задача &ndash; типичный пример того, как можно отдать чуть-чуть производительности на откуп читабельности кода.</p>
<p>Итак, давайте начнем с основ. Поскольку строка &ndash; это последовательность символов (ну, по крайней мере так считает F#), ее нужно для начала преобразовать в список. Делается это достаточно просто:</p>
<pre>let x = &quot;Hello&quot;
let y = Seq.toList(x)
Console.WriteLine(List.length y) // пишет 5
Console.WriteLine(List.toArray y) // пишет Hello
</pre>
<p>Пример выше иллюстрирует текст как список (именно список, а не последовательность &ndash; sequence &ndash; букв), а также возможность получения обратно строки (в примере выше &ndash; как <code>char[]</code>, но из этого можно и <code>System.String</code> построить). Если у вас возникло удивление от названия метода <code>toList()</code> (еще недавно ведь было <code>to_list()</code>, не так ли?), вам нужно обновить свой компилятор F#.</p>
<p>Имея список, можно делать его обход. Основной порыв в данном случае &ndash; начать &ldquo;подсматривать&rdquo; элементы списка и соответственно заменять их по мере необходимости. Примерно вот так:</p>
<pre>let rec Transform text =
  match text with
  | '-' :: '-' :: '&gt;' :: t -&gt; Seq.toList(&quot;&amp;rarr;&quot;) @ Transform t
  | h :: t -&gt; h :: Transform t
  | [] -&gt; []
 
let input = &quot;a --&gt; b&quot;
let result = input |&gt; Seq.toList |&gt; Transform |&gt; List.toArray
Console.WriteLine(new string(result)) // пишет a --&amp;rarr; b
</pre>
<p>Такой подход позволяет нам четко выделять все кейсы в отдельные строчки и при этом нам не нужно использовать злое слово <code>goto</code>. Почему? Для этого нам сначала нужно разобраться с контекстом. Что такое контекст? Это по сути дела некий набор состояний &ndash; один большой мутабельный god object который содержит различные состояния определенной трансформации. Есть два таких состояния:</p>
<ul>
<li>
<p>Собственно контекст, т.е. стек (<code>Stack&lt;string&gt;</code>) которые содержит те теги, в которых парсер находится на данный момент.</p>
</li>
<li>
<p>Набор переменных, которые символизируют различные внутренние состояния, не связанные с тегами. Например, <code>bool</code> флажок, описывающий, открыты ли у нас кавычки.</p>
</li>
</ul>
<p>Вообщем-то, представление в данном случае не важно. Важно лишь то, что все специальные случаи вроде &ldquo;обрабатывать как есть если мы в теге <code>&lt;code&gt;</code>&rdquo; можно с помощью очень полезного для pattern matching-а ключевого слова <code>where</code>:</p>
<pre>// подразумевается, что этот метод стал вложенным в другой метод,
// в котором объявлены элементы контекста
let rec Transform text =
  match text with
  | h :: t when context.CannotReplace -&gt; h :: Transform t
  ...
</pre>
<p>Но это еще не все. В нашем коде фигурирует паттерн <code>'-' :: '-' :: '&gt;'</code>, а писать такое, согласитесь, весьма неудобно. Легче было бы написать <code>"--&gt;"</code>, но к сожалению такой подход не сработает, т.к. просто вставить сюда строку нельзя. Зато можно определить дополнительную функцию (partial pattern matching) которая делала бы проверку именно &ldquo;префикса&rdquo; текущей строки:</p>
<pre>let rec (|Prefix|_|) s l =
  if s = &quot;&quot; then
    Some(Prefix l)
  else
    match l with
    | h :: (Prefix (s.Substring(1)) xs) when h = s.[0] -&gt; Some(Prefix xs)
    | _ -&gt; None
</pre>
<p>Используя эту вспомогательную функцию, мы можем писать подобый код:</p>
<pre>let rec Transform text =
  match text with
  | Prefix &quot;--&gt;&quot; t -&gt; Seq.toList(&quot;&amp;rarr;&quot;) @ Transform t
  | h :: t -&gt; h :: Transform t
  | [] -&gt; []
</pre>
<p>Этот подход несколько понизил читаемость кода т.к. теперь перед каждым случаем использования длинного префикса (а для однобуквенных префиксов он не особо нужен) теперь фигурирует слово <code>Prefix</code>. Конечно я мог бы выбрать слово покороче, но суть не в этом, а в том что это слово есть, и следовательно оно отвлекает.</p>
<p>Давайте посмотрим на более сложный пример в плане паттерн-матчинга &ndash; попробуем заменить <code>x</code> на <code>&amp;times;</code> только в тех случаях, когда буква <code>x</code> расположена между двумя числами (например в 2&times;2). Как это сделать? Примерно вот так:</p>
<pre>let rec Transform text =
  match text with
  | Prefix &quot;--&gt;&quot; t -&gt; Seq.toList(&quot;&amp;rarr;&quot;) @ Transform t
  | a :: 'x' :: c :: t when Char.IsDigit(a) &amp;&amp; Char.IsDigit(c) -&gt;
      a :: Seq.toList(&quot;&amp;times;&quot;) @ c :: Transform t
  | h :: t -&gt; h :: Transform t
  | [] -&gt; []
</pre>
<p>В примере выше сразу несколько &ldquo;усложнений&rdquo; ситуации &ndash; мы опять используем длинный список элементов в паттерне, но помимо этого мы используем <code>when</code> а также делаем достаточно неинтуитивную конкатенацию списков. Неинтуитивную потому, что обычно есть соблазн писать либо <code>::</code> либо <code>@</code> для соединения списков, а тут получается что мы соединяем два списка с головами <code>a</code> и <code>c</code> соответственно. Ну да ладно, не проблема, ведь все работает.</p>
<p>До сих пор мы ограничивались ситуациями, в которых паттерн имел фиксированную длину, но это не всегда так. Например, для производства заметок (refernces) я использую квадратные скобки (<code>[вот так]</code>), и тем самым нужно отловить начало и конец ссылки для того чтобы поместить содержимое в буфер. В последствии это содержимое добавляется в соответствующую секцию, но я в примере ниже опущу этот момент ради экономии места.</p>
<pre>let Transform text:String =
  let input = text |&gt; Seq.toList
  let buffer = new StringBuilder()
  let buffering = ref false
  let rec TransformImpl text =
    match text with
    | ']' :: t when !buffering -&gt;
      Console.WriteLine(buffer.ToString());
      // обрабатываем ссылку, а потом...
      buffering := false
      TransformImpl t
    | h :: t when !buffering -&gt;
      buffer.Append(h:char)
      TransformImpl t
    | '[' :: t -&gt;
      buffer.Clear()
      buffering := true
      TransformImpl t
    | Prefix &quot;--&gt;&quot; t -&gt; Seq.toList(&quot;&amp;rarr;&quot;) @ TransformImpl t
    | a :: 'x' :: c :: t when Char.IsDigit(a) &amp;&amp; Char.IsDigit(c) -&gt;
        a :: Seq.toList(&quot;&amp;times;&quot;) @ c :: TransformImpl t
    | h :: t -&gt; h :: TransformImpl t
    | [] -&gt; []
  new string(input |&gt; TransformImpl |&gt; List.toArray)
</pre>
<p>В примере выше, нам пришлось воспользоваться ключевым словом <code>ref</code> для того чтобы сделать переменную <code>buffering</code> изменяемой внутри нашего паттерн-матчинга. Причем в данном случае, мы не могли воспользоваться ключевым словом <code>mutable</code> и оператором <code>&lt;-</code>, а вместо этого нам пришлось использовать <code>ref</code> (т.е. создание ссылочного типа), а также операторами <code>:=</code> для присваивания и <code>!</code> для считывания. Увы, в данном примере F# не добавил читабельности.</p>
<p>Такой подход, на самом деле неидеален &ndash; нам пришлось разнести &ldquo;начало&rdquo; и &ldquo;конец&rdquo; паттерна на разные обработчики, которые в последствии даже не смогут стоять рядом друг с другом. Впрочем, для того чтобы получить &ldquo;конечную&rdquo; строку которую нам нужно выдернуть из списка, можно всего-навсего определить очередной &ldquo;активный паттерн&rdquo;, что я возможно когда-нибудь и сделаю.</p>
<p>Итак, попробую прорезюмировать плюсы и минусы данного подхода. Сначала о хорошем:</p>
<ul>
<li>
<p>Больше не нужно писать большой <code>switch</code>-блок в котором используется злое ключевое слово <code>goto</code>.</p>
</li>
<li>
<p>Если длина ожидаемого паттерна фиксирована, его можно описать с помощью обычной строки.</p>
</li>
</ul>
<p>С другой стороны, к сожалению, есть ряд минусов в плане полезности F#:</p>
<ul>
<li>
<p>Паттерны с неорганиченной длинной сложнее разбирать. В C# мы бы могли использовать поиск по строке и <code>Substring()</code> для выделения определенного элемента.</p>
</li>
<li>
<p>У паттернов должен быть определенный порядок исполнения, нарушив который мы ломаем всю систему. Тем самым, имеет место ситуация, в которой схожие по предназначению паттерны находятся далеко друг от друга лишь потому, что некоторые из них обязательно должны быть в начале разбора. N.b.: я не исключаю, что можно выделять выборку целых блоков внутри одного паттерн-матчинга путем создания дополнительных вложенных функций.</p>
</li>
<li>
<p>Использование F# не добавило задаче той системности, которая могла бы сделать код полностью читаемым. Все равно нужно писать документацию к разным кейсам, точно так же как я это делал в C#.</p>
</li>
<li>
<p>Существуют определенные проблемы с мутабельностью, которые периодически будут появляться со временем разростания &ldquo;контекста&rdquo; разбора.</p>
</li>
</ul>
<p>Надеюсь что в этом примере мне удалось наглядно продемонстрировать альтернативный подход к разбору строк в ситуации, когда обычные парсеры не работают. Не уверен что стоит рекоммендовать этот подход для всех типов задач, т.к. обычно для парсеров скорость разбора является критичной. Для меня к счастью она таковой не является, поэтому я продолжу использовать F#. Посмотрим, к чему меня это приведет.&nbsp;■</p><br />Filed under: <a rel="nofollow" target="_blank" href='https://nesteruk.wordpress.com/category/net/f/'>f#</a>  <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gocomments/nesteruk.wordpress.com/216/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/nesteruk.wordpress.com/216/"/></a> <img alt="" border="0" src="https://pixel.wp.com/b.gif?host=nesteruk.wordpress.com&#038;blog=373435&#038;post=216&#038;subd=nesteruk&#038;ref=&#038;feed=1" width="1" height="1"/>]]></content:encoded>
         <media:content medium="image" url="https://0.gravatar.com/avatar/f01cbd2238e2a78e4c43fa596f51d6a1?s=96&amp;amp;d=https%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&amp;amp;r=PG">
            <media:title type="html">nesteruk</media:title>
         </media:content>
         <category>f#</category>
      </item>
      <item>
         <title>F# 1.9.9.9 February 2010 CTP</title>
         <link>http://ru-fsharp.livejournal.com/2199.html</link>
         <description>&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.microsoft.com/downloads/details.aspx?FamilyID=ba52e650-4e77-4b0b-b987-9f9ecd3bab3b&amp;amp;displaylang=en&quot;&gt;F# 1.9.9.9 February 2010 CTP&lt;/a&gt;&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://fsharppowerpack.codeplex.com/&quot;&gt;F# PowerPack&lt;/a&gt; — теперь отдельно на Codeplex.&lt;br /&gt;(&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.rsdn.ru/forum/decl/3700527.aspx&quot;&gt;via&lt;/a&gt; RSDN)&lt;br /&gt;&lt;br /&gt;Upd 2010-02-11&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.microsoft.com/downloads/details.aspx?displaylang=en&amp;amp;FamilyID=8ff66036-37e2-4ae4-9651-3317c028c6ec&quot;&gt;Microsoft Visual Studio 2010 F# Runtime 2.0 RC&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Ну и к слову, недавно на channel9 вышла &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://channel9.msdn.com/shows/Going+Deep/C9-Lectures-Dr-Don-Syme-Introduction-to-F-1-of-3/&quot;&gt;первая лекция Дона Сайма&lt;/a&gt;. Смотреть её, откровенно говоря, необязательно :) Будем надеяться, что остальные поживее будут.&lt;br /&gt;&lt;br /&gt;Куда полезней посмотреть &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://channel9.msdn.com/shows/Going+Deep/C9-Lectures-Dr-Erik-Meijer-Functional-Programming-Fundamentals-Chapter-13-of-13/&quot;&gt;последнюю лекцию Эрика Мейера&lt;/a&gt;.</description>
         <author>Qbit</author>
         <guid isPermaLink="false">urn:lj:livejournal.com:atom1:ru_fsharp:2199</guid>
         <pubDate>Wed, 10 Feb 2010 23:29:54 +0000</pubDate>
      </item>
      <item>
         <title>Монада моделирования. Код</title>
         <link>http://dsorokin.blogspot.com/2010/02/blog-post_06.html</link>
         <description>Открыл новый проект &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://sourceforge.net/projects/aivika/&quot;&gt;Aivika&lt;/a&gt; на SourceForge. Там лежат исходники моделирующей библиотеки для F#. Пожалуй, функцию &lt;b&gt;memo&lt;/b&gt; нужно будет оптимизировать. Вероятно, из-за нее тормозит. Но есть задача важнее. Теперь буду пытаться продвигать идею на инглише.</description>
         <author>dsorokin</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-8641042312683198534.post-7344722027330417760</guid>
         <pubDate>Sat, 06 Feb 2010 14:18:00 +0000</pubDate>
      </item>
      <item>
         <title>Монада моделирования</title>
         <link>http://dsorokin.blogspot.com/2010/02/blog-post.html</link>
         <description>&lt;p class=&quot;MsoNormal&quot;&gt;&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot;&gt;&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot;&gt;&lt;p class=&quot;MsoNormal&quot;&gt;После начала изучения хаскеля прошедшей осенью придумал простую монаду, которая позволяет моделировать сложные динамические системы, заданные с помощью дифференциальных уравнений, где производная берется по времени. Сначала идея была реализована на хаскеле, и мне особенно нравилось, что благодаря ленивости языка можно было записывать дифференциальные уравнения в произвольном порядке так, как это принято в математике и в специальных моделирующих программах типа &lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;Vensim&lt;/span&gt; и &lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;ithink&lt;/span&gt;, а также написанных мною &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.simtegra.com&quot;&gt;Simtegra MapSys&lt;/a&gt; и &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://sourceforge.net/projects/mapsim/&quot;&gt;MapSim&lt;/a&gt;. Последний является самодостаточным движком предыдущего.&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;Но с этой реализацией идеи возникла проблема, которую я пока не знаю как красиво разрешить в хаскеле. Моделируемая динамическая система на самом деле может быть стохастической, т.е. недетерминированной. Каждый новый прогон модели может порождать новые результаты. То есть, запускающая имитацию функция не является чистой. Тут на помощь пришел язык &lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;F&lt;/span&gt;#, который я начал изучать чуть позже. В нем уже достаточно легко сочетать функциональный и императивный подходы. В итоге это привело к любопытному результату, оформленному в виде библиотеки на &lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;F&lt;/span&gt;# с рабочим названием &lt;i style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;Aivika&lt;/span&gt;&lt;/i&gt;, которую я здесь и попытаюсь описать.&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;Сначала приведу пример простой динамической системы, записанной на языке &lt;i style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;MapSim&lt;/span&gt;&lt;/i&gt;:&lt;/p&gt;  &lt;p class=&quot;a&quot;&gt;&lt;span lang=&quot;EN-US&quot;&gt;A = integ (-F, 100);&lt;br /&gt;B = integ (F - G, 0);&lt;br /&gt;C = integ (G, 0);&lt;br /&gt;&lt;br /&gt;F = ka * A;&lt;br /&gt;G = kb * B;&lt;br /&gt;&lt;br /&gt;ka = 1;&lt;br /&gt;kb = 1;&lt;/span&gt;&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;Здесь функция &lt;b style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;integ&lt;/span&gt;&lt;/b&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;задает интеграл. Ее первым параметром является производная по времени, а вторым – начальное значение. То есть, &lt;i style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;A&lt;/span&gt;(&lt;/i&gt;&lt;i style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;t&lt;/span&gt;)&lt;/i&gt; является интегралом (еще говорят &lt;i style=&quot;&quot;&gt;резервуаром&lt;/i&gt;), производная которого равна &lt;i style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;dA&lt;/span&gt;/&lt;/i&gt;&lt;i style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;dt&lt;/span&gt; = –&lt;/i&gt;&lt;i style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;ka&lt;/span&gt;*&lt;/i&gt;&lt;i style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;A&lt;/span&gt;(&lt;/i&gt;&lt;i style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;t&lt;/span&gt;)&lt;/i&gt;. В начальный момент времени значение &lt;i style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;A&lt;/span&gt;(&lt;/i&gt;&lt;i style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;t&lt;/span&gt;&lt;sub&gt;0&lt;/sub&gt;)&lt;/i&gt; равно 100. Это задача Коши.&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;Такая система может быть интегрирована методами Эйлера и Рунге-Кутта второго и четвертого порядков. Задается начальное время &lt;i style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;starttime&lt;/span&gt;&lt;/i&gt;, конечное &lt;i style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;stoptime&lt;/span&gt;&lt;/i&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;и основной шаг интегрирования &lt;i style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;dt&lt;/span&gt;&lt;/i&gt;. Затем временная шкала разбивается на узлы: &lt;i style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;starttime&lt;/span&gt;, &lt;/i&gt;&lt;i style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;starttime&lt;/span&gt; + &lt;/i&gt;&lt;i style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;dt&lt;/span&gt;, &lt;/i&gt;&lt;i style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;starttime&lt;/span&gt; + 2*&lt;/i&gt;&lt;i style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;dt&lt;/span&gt;, …, &lt;/i&gt;&lt;i style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;stoptime&lt;/span&gt;&lt;/i&gt;. В случае методов Рунге-Кутта создаются еще дополнительные внутренние под-узлы. В итоге каждый узел сетки интегрирования однозначно задается парой целых чисел: номером итерации и номером фазы. Метод Эйлера имеет всего одну фазу. Метод Рунге-Кутта второго порядка – две фазы. Метод четвертого порядка – четыре фазы.&lt;/p&gt;  &lt;p class=&quot;a&quot;&gt;&lt;span lang=&quot;EN-US&quot;&gt;type Iteration = int&lt;br /&gt;type Phase = int&lt;br /&gt;type Method = Euler | RungeKutta2 | RungeKutta4&lt;/span&gt;&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;Здесь и далее я буду использовать &lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;F&lt;/span&gt;# для записи кода.&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;Система может быть стохастической. Поэтому используется генератор случайных чисел, которым можно управлять, задавая параметр следующего типа&lt;/p&gt;  &lt;p class=&quot;a&quot;&gt;&lt;span lang=&quot;EN-US&quot;&gt;type&lt;/span&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt; &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;Randomness&lt;/span&gt;&lt;span style=&quot;&quot;&gt; = &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;SimpleRnd&lt;/span&gt;&lt;span style=&quot;&quot;&gt; | &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;StrongRnd&lt;/span&gt;&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;Тогда параметры моделирования, их еще называют спеками моделирования, могут быть описаны значением типа&lt;/p&gt;  &lt;p class=&quot;a&quot;&gt;&lt;span lang=&quot;EN-US&quot;&gt;type Specs = {&lt;br /&gt;&lt;span style=&quot;&quot;&gt;    &lt;/span&gt;spcStartTime: float; spcStopTime: float; spcDT: float;&lt;br /&gt;&lt;span style=&quot;&quot;&gt;    &lt;/span&gt;spcMethod: Method; spcRandomness: Randomness&lt;br /&gt;}&lt;/span&gt;&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;Для нашего примера мы могли бы взять следующие параметры: начальное время – 0, конечное время – 10, основной шаг интегрирования – 0,1, метод – Рунге-Кутта четвертого порядка, а режим генератора – «сильная» псевдо-случайность, хотя последний никак не используется в этой модели.&lt;/p&gt;  &lt;p class=&quot;a&quot;&gt;&lt;span lang=&quot;EN-US&quot;&gt;let specs = {&lt;br /&gt;&lt;span style=&quot;&quot;&gt;    &lt;/span&gt;spcStartTime=0.0; spcStopTime=10.0; spcDT=0.1;&lt;br /&gt;&lt;span style=&quot;&quot;&gt;    &lt;/span&gt;spcMethod=RungeKutta4; spcRandomness=StrongRnd&lt;br /&gt;}&lt;/span&gt;&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;Саму систему мы можем начать описывать с констант &lt;i style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;ka&lt;/span&gt;&lt;/i&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;и &lt;i style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;kb&lt;/span&gt;&lt;/i&gt;.&lt;/p&gt;  &lt;p class=&quot;a&quot;&gt;&lt;span lang=&quot;EN-US&quot;&gt;let&lt;/span&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt; &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;ka&lt;/span&gt;&lt;span style=&quot;&quot;&gt; = 1.0&lt;br /&gt;&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;let&lt;/span&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt; &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;kb&lt;/span&gt;&lt;span style=&quot;&quot;&gt; = 1.0&lt;/span&gt;&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;Затем объявляем интегралы и задаем для них начальные значения.&lt;/p&gt;  &lt;p class=&quot;a&quot;&gt;&lt;span lang=&quot;EN-US&quot;&gt;let a = Integ 100.0&lt;br /&gt;let b = Integ 0.0&lt;br /&gt;let c = Integ 0.0&lt;/span&gt;&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;Каждый из трех интегралов имеет свойства &lt;b style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;Value&lt;/span&gt;&lt;/b&gt;, &lt;b style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;Inflow&lt;/span&gt;&lt;/b&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;и &lt;b style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;Outflow&lt;/span&gt;&lt;/b&gt;. Эти свойства связаны дифференциальными уравнениями, одно из которых я покажу на примере интеграла &lt;i style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;a&lt;/span&gt;&lt;/i&gt;:&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot; align=&quot;center&quot; style=&quot;text-align:center;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;d/dt (a.Value) = (a.Inflow – a.Outflow)&lt;/span&gt;&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;Такие же уравнения имеют место для других интегралов. Свойство &lt;b style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;Value&lt;/span&gt;&lt;/b&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;возвращает текущее значение интеграла, и оно доступно только по чтению. Свойства &lt;b style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;Inflow&lt;/span&gt;&lt;/b&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;и &lt;b style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;Outflow&lt;/span&gt;&lt;/b&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;можно менять. Они оба вместе задают производную. По-умолчанию, они представляют нулевые значения. То есть, если мы не зададим ни одно из свойств &lt;b style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;Inflow&lt;/span&gt;&lt;/b&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;и &lt;b style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;Outflow&lt;/span&gt;&lt;/b&gt;, то производная будет равна нулю, а интеграл окажется константой. &lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;Продолжаем описание задачи с определения дополнительных функций, которые зависят уже от текущих значений интегралов.&lt;/p&gt;  &lt;p class=&quot;a&quot;&gt;&lt;span lang=&quot;EN-US&quot;&gt;let f = ka * a.Value&lt;br /&gt;let g = kb * b.Value&lt;/span&gt;&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;И завершаем описание задачи собственно самими дифференциальными уравнениями:&lt;/p&gt;  &lt;p class=&quot;a&quot;&gt;&lt;span lang=&quot;EN-US&quot;&gt;a.Inflow &amp;lt;- -f&lt;br /&gt;b.Inflow &amp;lt;- f – g&lt;br /&gt;c.Inflow &amp;lt;- g&lt;/span&gt;&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;Удивительно, но это все – что нам нужно, чтобы немедленно запросить библиотеку промоделировать, скажем, переменную &lt;i style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;a&lt;/span&gt;&lt;/i&gt; и вернуть результат:&lt;/p&gt;  &lt;p class=&quot;a&quot;&gt;&lt;span lang=&quot;EN-US&quot;&gt;&amp;gt; runDynamics a.Value specs;;&lt;br /&gt;val it : float [] =&lt;br /&gt;&lt;span style=&quot;&quot;&gt;  &lt;/span&gt;[|100.0; 90.48375; 81.87309014; 74.0818422; 67.03202889; 60.65309344;&lt;br /&gt;&lt;span style=&quot;&quot;&gt;    &lt;/span&gt;54.88119344; 49.65856187; 44.93292897; 40.65699912; 36.78797744;&lt;br /&gt;&lt;span style=&quot;&quot;&gt;    &lt;/span&gt;33.28714154; 30.11945393; 27.2532114; 24.65972767; 22.31304633;&lt;br /&gt;&lt;span style=&quot;&quot;&gt;    &lt;/span&gt;20.18968106; 18.26838054; 16.52991577; 14.95688766; 13.53355284;&lt;br /&gt;&lt;span style=&quot;&quot;&gt;    &lt;/span&gt;12.24566612; 11.08033792; 10.02590526; 9.071815051; 8.208518451;&lt;br /&gt;&lt;span style=&quot;&quot;&gt;    &lt;/span&gt;7.427375314; 6.720567711; 6.081021686; 5.50233646; 4.978720367;...|]&lt;/span&gt;&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;Более того, мы можем запросить результаты не только для одной переменной, но и для целой группы, попросив включить в список и модельное время:&lt;/p&gt;  &lt;p class=&quot;a&quot;&gt;&lt;span style=&quot;&quot;&gt;&amp;gt; &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;runDynamics&lt;/span&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt; &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;Dynamics&lt;/span&gt;&lt;span style=&quot;&quot;&gt;.&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;ofArray&lt;/span&gt;&lt;span style=&quot;&quot;&gt; [| &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;&quot;&gt;; &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;&quot;&gt;.&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;Value&lt;/span&gt;&lt;span style=&quot;&quot;&gt;; &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;b&lt;/span&gt;&lt;span style=&quot;&quot;&gt;.&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;Value&lt;/span&gt;&lt;span style=&quot;&quot;&gt;; &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;c&lt;/span&gt;&lt;span style=&quot;&quot;&gt;.&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;Value&lt;/span&gt;&lt;span style=&quot;&quot;&gt; |] &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;specs&lt;/span&gt;&lt;span style=&quot;&quot;&gt;;;&lt;br /&gt;[|[|0.0; 100.0; 0.0; 0.0|];&lt;br /&gt;&lt;span style=&quot;&quot;&gt;  &lt;/span&gt;[|0.1; 90.48375; 9.048333333; 0.4679166667|];&lt;br /&gt;&lt;span style=&quot;&quot;&gt;  &lt;/span&gt;[|0.2; 81.87309014; 16.37454263; 1.752367234|];&lt;br /&gt;&lt;span style=&quot;&quot;&gt;  &lt;/span&gt;[|0.3; 74.0818422; 22.22445032; 3.693707481|];&lt;br /&gt;&lt;span style=&quot;&quot;&gt;  &lt;/span&gt;[|0.4; 67.03202889; 26.81268809; 6.155283021|];&lt;br /&gt;&lt;span style=&quot;&quot;&gt;  &lt;/span&gt;[|0.5; 60.65309344; 30.32640707; 9.020499487|]; ...|]&lt;/span&gt;&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;Поразительная краткость, не правда ли?&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;Все это стало возможным благодаря использованию монады моделирования, которая является вариацией стандартной монады &lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;Reader&lt;/span&gt;. Еще меня натолкнула на ее написание замечательная книга «&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;The&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;Haskell&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;School&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;of&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;Expression&lt;/span&gt;» автора &lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;Paul&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;Hudak&lt;/span&gt;.&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;Итак, мы моделируем некоторый динамический процесс, который в каждый момент времени возвращает некоторое значение типа &lt;i style=&quot;&quot;&gt;'&lt;/i&gt;&lt;i style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;a&lt;/span&gt;&lt;/i&gt;. Обозначим этот полиморфный тип как &lt;b style=&quot;&quot;&gt;Dynamics&amp;lt;'a&amp;gt;&lt;/b&gt;.&lt;/p&gt;  &lt;p class=&quot;a&quot;&gt;&lt;span lang=&quot;EN-US&quot;&gt;[ ]&lt;br /&gt;type Dynamics&amp;lt;'a&amp;gt; (iter: Iterator&amp;lt;'a&amp;gt;) =&lt;br /&gt;&lt;span style=&quot;&quot;&gt;    &lt;/span&gt;member d.Iterator = iter&lt;br /&gt;&lt;br /&gt;let iterator (p: Dynamics&amp;lt;'a&amp;gt;) = p.Iterator&lt;/span&gt;&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;Внутри этого типа сидит итератор, который по заданным спекам моделирования возвращает в каждом узле интегрирования некоторое значение. Если вы помните, такие узлы однозначно определялись парой целых чисел: номером итерации и фазой.&lt;/p&gt;  &lt;p class=&quot;a&quot;&gt;&lt;span lang=&quot;EN-US&quot;&gt;type Iterator&amp;lt;'a&amp;gt; = Run -&amp;gt; Specs -&amp;gt; Iteration -&amp;gt; Phase -&amp;gt; 'a&lt;/span&gt;&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;То есть, итератор – это просто функция. Здесь появился новый тип &lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;Run&lt;/span&gt;, &lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;c&lt;/span&gt; которым связан недетерминизм и не только. В упрощенном виде (после удаления некоторых оптимизаций) этот тип выглядит так.&lt;/p&gt;  &lt;p class=&quot;a&quot;&gt;&lt;span lang=&quot;EN-US&quot;&gt;type Run () =&lt;br /&gt;&lt;span style=&quot;&quot;&gt;    &lt;/span&gt;let mutable disposed = false&lt;br /&gt;&lt;span style=&quot;&quot;&gt;    &lt;/span&gt;let disposedEvent = new Event&amp;lt;_&amp;gt;()&lt;br /&gt;&lt;span style=&quot;&quot;&gt;    &lt;/span&gt;member x.Disposed = disposedEvent.Publish&lt;br /&gt;&lt;span style=&quot;&quot;&gt;    &lt;/span&gt;member x.IsDisposed = disposed&lt;br /&gt;&lt;span style=&quot;&quot;&gt;    &lt;/span&gt;interface IDisposable with&lt;br /&gt;&lt;span style=&quot;&quot;&gt;        &lt;/span&gt;member x.Dispose() =&lt;br /&gt;&lt;span style=&quot;&quot;&gt;            &lt;/span&gt;if not disposed then&lt;br /&gt;&lt;span style=&quot;&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;&quot;&gt;      &lt;/span&gt;disposedEvent.Trigger()&lt;br /&gt;&lt;span style=&quot;&quot;&gt;                &lt;/span&gt;disposed &amp;lt;- true&lt;/span&gt;&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;Когда мы запускаем имитацию, мы создаем уникальный экземпляр типа &lt;b style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;Run&lt;/span&gt;&lt;/b&gt;. Затем во время интегрирования мы передаем это значение в итератор динамического процесса. Ориентируясь на такое значение, любая функция может создать некоторые внутренние данные, которые будут актуальны, пока существует значение типа &lt;b style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;Run&lt;/span&gt;&lt;/b&gt;. Например, это может быть таблица кеширования предыдущих значений для интеграла внутри объекта типа &lt;b style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;Integ&lt;/span&gt;&lt;/b&gt;. Когда имитация заканчивается, значение типа &lt;b style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;Run&lt;/span&gt;&lt;/b&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;разрушается, но предварительно вызывается метод &lt;b style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;Dispose&lt;/span&gt;&lt;/b&gt;, который посылает сигнал &lt;b style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;Disposed&lt;/span&gt;&lt;/b&gt;. Одна из внутренних функций интеграла или уровнем ниже ловит этот сигнал, и разрушает таблицу кеширования. Так достигается следующее. &lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;Запуски динамического процесса могут давать разные результаты. Но внутри одного запуска мы можем запоминать и использовать предыдущие вычисления по шкале времени, актуальные для этого запуска. После окончания мы можем удалить все использованные внутренние структуры. Это открывает путь к кешированию и тому подобным методикам.&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;Сам запуск динамического процесса очень прост. Его вызов уже использовался в примерах выше.&lt;/p&gt;  &lt;p class=&quot;a&quot;&gt;&lt;span lang=&quot;EN-US&quot;&gt;let runDynamics d specs = [|&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;&quot;&gt;    &lt;/span&gt;use r = new Run ()&lt;br /&gt;&lt;span style=&quot;&quot;&gt;    &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;&quot;&gt;    &lt;/span&gt;let f1 = iterator d r specs&lt;br /&gt;&lt;span style=&quot;&quot;&gt;    &lt;/span&gt;let f2 = fun n -&amp;gt; f1 n 0&lt;br /&gt;&lt;span style=&quot;&quot;&gt;    &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;&quot;&gt;    &lt;/span&gt;for i = 0 to (Specs.iterations specs - 1) do yield f2 i&lt;br /&gt;|]&lt;/span&gt;&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;Здесь функция &lt;b style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;iterations&lt;/span&gt;&lt;/b&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;возвращает общее число итераций по заданным спекам. &lt;span style=&quot;&quot;&gt; &lt;/span&gt;На выходе нас интересуют значения динамического процесса в основных узлах сетки интегрирования – поэтому запрашивается нулевая фаза. Ниже будет приведено определение функции &lt;b style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;integ&lt;/span&gt;&lt;/b&gt;, на примере которого можно понять то, как работают фазы.&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;Собственно, все. Дальше монада моделирования определяется просто. Ее функции &lt;b style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;return&lt;/span&gt;&lt;/b&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;и &lt;b style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;bind&lt;/span&gt;&lt;/b&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;почти такие же, как и в случае монады &lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;Reader&lt;/span&gt;.&lt;/p&gt;  &lt;p class=&quot;a&quot;&gt;&lt;span lang=&quot;EN-US&quot;&gt;[ ]&lt;br /&gt;type DynamicsBuilder() =&lt;br /&gt;&lt;span style=&quot;&quot;&gt;    &lt;/span&gt;member d.Return (a) =&lt;br /&gt;&lt;span style=&quot;&quot;&gt;        &lt;/span&gt;new Dynamics&amp;lt;'a&amp;gt; (fun r s n ph -&amp;gt; a)&lt;br /&gt;&lt;span style=&quot;&quot;&gt;    &lt;/span&gt;member d.Bind (m, k) =&lt;br /&gt;&lt;span style=&quot;&quot;&gt;        &lt;/span&gt;new Dynamics&amp;lt;'b&amp;gt; (fun r s n ph -&amp;gt;&lt;br /&gt;&lt;span style=&quot;&quot;&gt;            &lt;/span&gt;let a = iterator m r s n ph&lt;br /&gt;&lt;span style=&quot;&quot;&gt;            &lt;/span&gt;let m' = k a&lt;br /&gt;&lt;span style=&quot;&quot;&gt;            &lt;/span&gt;iterator m' r s n ph)&lt;/span&gt;&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;Тогда мы можем определить свой &lt;i style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;workflow&lt;/span&gt;&lt;/i&gt;. Назовем его &lt;b style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;dynamics&lt;/span&gt;&lt;/b&gt;.&lt;span style=&quot;&quot;&gt;  &lt;/span&gt;Он позволяет использовать синтаксический сахар в &lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;F&lt;/span&gt;#, похожий на нотацию &lt;i style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;do&lt;/span&gt;&lt;/i&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;из хаскеля, где &lt;b style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;let&lt;/span&gt;!&lt;/b&gt; будет эквивалентен стрелке.&lt;/p&gt;  &lt;p class=&quot;a&quot;&gt;&lt;span lang=&quot;EN-US&quot;&gt;let&lt;/span&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt; &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;dynamics&lt;/span&gt;&lt;span style=&quot;&quot;&gt; = &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;new&lt;/span&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt; &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;DynamicsBuilder&lt;/span&gt;&lt;span style=&quot;&quot;&gt;()&lt;/span&gt;&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;Более того, мы можем определить арифметические операции и основные функции типа синуса в соответствии с образцом:&lt;/p&gt;  &lt;p class=&quot;a&quot;&gt;&lt;span lang=&quot;EN-US&quot;&gt;type Dynamics&amp;lt;'a&amp;gt; with&lt;br /&gt;&lt;span style=&quot;&quot;&gt;    &lt;/span&gt;static member (+) (a: Dynamics , b: Dynamics ) =&lt;br /&gt;&lt;span style=&quot;&quot;&gt;        &lt;/span&gt;Dynamics.lift2 (+) a b&lt;/span&gt;&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;Здесь функция &lt;b style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;lift&lt;/span&gt;2&lt;/b&gt; достаточно идиоматична. Она берет некоторую функцию и два значения, обернутые в монаду. Значения извлекаются, к ним применяется функция, и результат снова заворачивается в монаду.&lt;/p&gt;  &lt;p class=&quot;a&quot;&gt;&lt;span lang=&quot;EN-US&quot;&gt;module Dynamics =&lt;br /&gt;&lt;span style=&quot;&quot;&gt;    &lt;/span&gt;let lift2 f m1 m2 = dynamics {&lt;br /&gt;&lt;span style=&quot;&quot;&gt;        &lt;/span&gt;let! a1 = m1&lt;br /&gt;&lt;span style=&quot;&quot;&gt;        &lt;/span&gt;let! a2 = m2&lt;br /&gt;&lt;span style=&quot;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;&quot;&gt;    &lt;/span&gt;return f a1 a2}&lt;/span&gt;&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;Но я использовал версию оптимальнее, которая уже учитывает внутреннее устройство монады:&lt;/p&gt;  &lt;p class=&quot;a&quot;&gt;&lt;span lang=&quot;EN-US&quot;&gt;module Dynamics =&lt;br /&gt;&lt;span style=&quot;&quot;&gt;    &lt;/span&gt;let lift2 f m1 m2 = Dynamics&amp;lt;_&amp;gt; (fun r s n ph -&amp;gt;&lt;br /&gt;&lt;span style=&quot;&quot;&gt;        &lt;/span&gt;let a1 = iterator m1 r s n ph&lt;br /&gt;&lt;span style=&quot;&quot;&gt;        &lt;/span&gt;let a2 = iterator m2 r s n ph&lt;br /&gt;&lt;span style=&quot;&quot;&gt;        &lt;/span&gt;in f a1 a2)&lt;/span&gt;&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;Этих сведений о монаде достаточно, чтобы определить интегралы и стохастические функции, а также утилиту мемоизации &lt;b style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;memo&lt;/span&gt;&lt;/b&gt;, которая кеширует предыдущие значения заданного динамического процесса внутри одного запуска, вычисляя их строго последовательно по узлам интегрирования.&lt;/p&gt;  &lt;p class=&quot;a&quot;&gt;&lt;span lang=&quot;EN-US&quot;&gt;module Dynamics =&lt;br /&gt;&lt;span style=&quot;&quot;&gt;    &lt;/span&gt;val memo: Dynamics&amp;lt;'a&amp;gt; -&amp;gt; Dynamics&amp;lt;'a&amp;gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;Здесь для краткости приведу лишь функцию &lt;b style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;integ&lt;/span&gt;&lt;/b&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;– аналог одноименной функции &lt;i style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;MapSim&lt;/span&gt;&lt;/i&gt;, причем только для интегрирования по методу Рунге-Кутта второго порядка. Для других методов определены аналогичные внутренние функции &lt;b style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;integEuler&lt;/span&gt;&lt;/b&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;и &lt;b style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;integRK&lt;/span&gt;4&lt;/b&gt;.&lt;/p&gt;  &lt;p class=&quot;a&quot;&gt;&lt;span style=&quot;&quot;&gt;&lt;span style=&quot;&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;let integ (f: Dynamics ) (i: Dynamics ) =&lt;br /&gt;&lt;span style=&quot;&quot;&gt;        &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;&quot;&gt;        &lt;/span&gt;// integEuler and integRK4&lt;br /&gt;&lt;span style=&quot;&quot;&gt;        &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;&quot;&gt;        &lt;/span&gt;let integRK2 (y: Dynamics&amp;lt;_&amp;gt;) (f: Dynamics&amp;lt;_&amp;gt;) (i: Dynamics&amp;lt;_&amp;gt;) r s =&lt;br /&gt;&lt;span style=&quot;&quot;&gt;            &lt;/span&gt;let vy n = iterator y r s n 0&lt;br /&gt;&lt;span style=&quot;&quot;&gt;            &lt;/span&gt;let vi n = iterator i r s n 0&lt;br /&gt;&lt;span style=&quot;&quot;&gt;            &lt;/span&gt;let k1 n = iterator f r s n 0&lt;br /&gt;&lt;span style=&quot;&quot;&gt;            &lt;/span&gt;let k2 n = iterator f r s n 1&lt;br /&gt;&lt;span style=&quot;&quot;&gt;            &lt;/span&gt;fun n ph -&amp;gt;&lt;br /&gt;&lt;span style=&quot;&quot;&gt;                &lt;/span&gt;match n, ph with&lt;br /&gt;&lt;span style=&quot;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;&quot;&gt;        &lt;/span&gt;| 0, 0 -&amp;gt; vi 0&lt;br /&gt;&lt;span style=&quot;&quot;&gt;                    &lt;/span&gt;| n, 0 -&amp;gt; vy (n-1) + s.spcDT/2.0 * (k1 (n-1) + k2 (n-1))&lt;br /&gt;&lt;span style=&quot;&quot;&gt;                    &lt;/span&gt;| n, 1 -&amp;gt; vy n + s.spcDT * k1 n&lt;br /&gt;&lt;span style=&quot;&quot;&gt;                    &lt;/span&gt;| _ -&amp;gt; failwithf &quot;integRK2: incorrect phase = %i&quot; ph&lt;br /&gt;&lt;span style=&quot;&quot;&gt;        &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;&quot;&gt;        &lt;/span&gt;let rec y = Dynamics.memo z&lt;br /&gt;&lt;span style=&quot;&quot;&gt;        &lt;/span&gt;and z = Dynamics&amp;lt;_&amp;gt; (fun r s -&amp;gt;&lt;br /&gt;&lt;span style=&quot;&quot;&gt;            &lt;/span&gt;match s.spcMethod with&lt;br /&gt;&lt;span style=&quot;&quot;&gt;                &lt;/span&gt;| Euler -&amp;gt; integEuler y f i r s&lt;br /&gt;&lt;span style=&quot;&quot;&gt;                &lt;/span&gt;| RungeKutta2 -&amp;gt; integRK2 y f i r s&lt;br /&gt;&lt;span style=&quot;&quot;&gt;                &lt;/span&gt;| RungeKutta4 -&amp;gt; integRK4 y f i r s)&lt;br /&gt;&lt;span style=&quot;&quot;&gt;        &lt;/span&gt;in y&lt;/span&gt;&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;Но одной функции &lt;b style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;integ&lt;/span&gt;&lt;/b&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;недостаточно в &lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;F&lt;/span&gt;#, потому что нужно разруливать как-то рекурсивные связи. Поэтому придумал трюк с отдельным типом &lt;b style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;Integ&lt;/span&gt;&lt;/b&gt; и тремя его свойствами &lt;b style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;Value&lt;/span&gt;&lt;/b&gt;,&lt;b style=&quot;&quot;&gt; &lt;/b&gt;&lt;b style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;Inflow&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;&lt;/b&gt;и&lt;b style=&quot;&quot;&gt; &lt;/b&gt;&lt;b style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;Outflow&lt;/span&gt;&lt;/b&gt;. Сам тип &lt;b style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;Integ&lt;/span&gt;&lt;/b&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;использует внутри функцию &lt;b style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;integ&lt;/span&gt;&lt;/b&gt;.&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;Итак, монада моделирования позволяет достаточно просто задавать дифференциальные уравнения и интегрировать их. Это очень декларативно. Но я думаю, что реальная сила этого метода будет проявляться при построении гибридных моделей. Например, с помощью функции &lt;b style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;memo&lt;/span&gt;&lt;/b&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;мы можем определять некоторые динамические процессы через конечный автомат, что уже достаточно императивно.&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;В заключение несколько слов о скорости имитации. Она ужасна. Мои тесты показали, что библиотека &lt;i style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;Aivika&lt;/span&gt;&lt;/i&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;медленнее &lt;i style=&quot;&quot;&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;MapSim&lt;/span&gt;&lt;/i&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;в десятки или сотни раз, хотя и там, и там – .&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;NET&lt;/span&gt;. И автор один и тот же &lt;span lang=&quot;EN-US&quot; style=&quot;font-family:Wingdings;&quot;&gt;&lt;span style=&quot;&quot;&gt;J&lt;/span&gt;&lt;/span&gt;.&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;Теперь вот думаю, а не написать ли мне подобное на &lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;Common&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;&lt;span lang=&quot;EN-US&quot; style=&quot;&quot;&gt;Lisp&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;– там некоторые вещи можно сделать быстрее за счет более умной кодогенерации.&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;</description>
         <author>dsorokin</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-8641042312683198534.post-1159864450732353296</guid>
         <pubDate>Wed, 03 Feb 2010 10:27:00 +0000</pubDate>
      </item>
      <item>
         <title>FP |&amp;gt; OOP</title>
         <link>http://skiminog.livejournal.com/63921.html</link>
         <description>В дополнение к предыдущему посту.&lt;br /&gt;&lt;br /&gt;Двумя главными преимуществами таких простых пайплайнов адепты F# называют:&lt;br /&gt;а) Автоматический вывод типов, действующий слева направо, что позволяет при использовании &lt;code&gt;x |&amp;gt; someExpression&lt;/code&gt; писать в выражении someExpression поля и методы x (такие как x.Smth), если тип х уже был известен.&lt;br /&gt;Так, если есть последовательность FileInfo, то если попытаться из каждого ее элемента выделить только имя файла таким макаром:&lt;br /&gt;&lt;div style=&quot;font-family:monospace;color:#006;border:1px solid #d0d0d0;background-color:#f0f0f0;&quot;&gt;&lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;let&lt;/span&gt; getNames &lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;myFileInfos: FileInfo &lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;seq&lt;/span&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt; &amp;nbsp;&lt;span style=&quot;color:#a52a2a;&quot;&gt;=&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &lt;a rel=&quot;nofollow&quot; style=&quot;color:#000060;&quot; target=&quot;_blank&quot; href=&quot;http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/manual/namespaces.html&quot;&gt;&lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;Seq&lt;/span&gt;&lt;/a&gt;.&lt;span style=&quot;color:#060;&quot;&gt;map&lt;/span&gt; &lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;fun&lt;/span&gt; x &lt;span style=&quot;color:#a52a2a;&quot;&gt;-&amp;gt;&lt;/span&gt; x.&lt;span style=&quot;color:#060;&quot;&gt;Name&lt;/span&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt; myFileInfos&lt;/div&gt;&lt;br /&gt;то компилятор заругается, поскольку при обработке лямбды он понятия не имеет, какой тип может иметь ее входящий параметр, определить этого не может, и совершенно не верит, что этот параметр в общем случае имеет свойство Name.&lt;br /&gt;Ситуация в корне меняется с применением пайплайна:&lt;br /&gt;&lt;div style=&quot;font-family:monospace;color:#006;border:1px solid #d0d0d0;background-color:#f0f0f0;&quot;&gt;&lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;let&lt;/span&gt; getNames &lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;myFileInfos: FileInfo &lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;seq&lt;/span&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt; &amp;nbsp;&lt;span style=&quot;color:#a52a2a;&quot;&gt;=&lt;/span&gt;&lt;br /&gt;&amp;nbsp; myFileInfos &lt;span style=&quot;color:#a52a2a;&quot;&gt;|&amp;gt;&lt;/span&gt; &lt;a rel=&quot;nofollow&quot; style=&quot;color:#000060;&quot; target=&quot;_blank&quot; href=&quot;http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/manual/namespaces.html&quot;&gt;&lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;Seq&lt;/span&gt;&lt;/a&gt;.&lt;span style=&quot;color:#060;&quot;&gt;map&lt;/span&gt; &lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;fun&lt;/span&gt; x &lt;span style=&quot;color:#a52a2a;&quot;&gt;-&amp;gt;&lt;/span&gt; x.&lt;span style=&quot;color:#060;&quot;&gt;Name&lt;/span&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;Здесь, благодаря обработке слева направо, тип элемента последовательности уже строго определен на момент описания лямбды, и компилятор это скушает, еще и облизнется.&lt;br /&gt;&lt;br /&gt;б) Второе преимущество вытекает из первого: возможность переделки нагруженных скобками ОО-выражений с вызовами методов удобочитаемыми и простыми последовательностями функциональных вызовов.&lt;br /&gt;К примеру, в своем проекте-песочнице, где я набиваю разные заковыристые функции на F# по мере чтения &quot;Expert F#&quot; и тематических блогов, результаты всех функций отображаются в простом окошке WPF. Примерно так:&lt;br /&gt;&lt;div style=&quot;font-family:monospace;color:#006;border:1px solid #d0d0d0;background-color:#f0f0f0;&quot;&gt;&lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;let&lt;/span&gt; test &lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;textBox: RichTextBox&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt; number answer &lt;span style=&quot;color:#a52a2a;&quot;&gt;=&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;let&lt;/span&gt; run x &lt;span style=&quot;color:#a52a2a;&quot;&gt;=&lt;/span&gt; Run&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;x&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;let&lt;/span&gt; bold x &lt;span style=&quot;color:#a52a2a;&quot;&gt;=&lt;/span&gt; Bold&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;x&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;let&lt;/span&gt; paragraph x &lt;span style=&quot;color:#a52a2a;&quot;&gt;=&lt;/span&gt; Paragraph&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;x&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;let&lt;/span&gt; add x &lt;span style=&quot;color:#a52a2a;&quot;&gt;=&lt;/span&gt; textBox.&lt;span style=&quot;color:#060;&quot;&gt;Document&lt;/span&gt;.&lt;span style=&quot;color:#060;&quot;&gt;Blocks&lt;/span&gt;.&lt;span style=&quot;color:#060;&quot;&gt;Add&lt;/span&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;x&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; number &lt;span style=&quot;color:#a52a2a;&quot;&gt;|&amp;gt;&lt;/span&gt; sprintf &lt;span style=&quot;color:#3cb371;&quot;&gt;&amp;quot;Testcase %d:&amp;quot;&lt;/span&gt; &lt;span style=&quot;color:#a52a2a;&quot;&gt;|&amp;gt;&lt;/span&gt; run &lt;span style=&quot;color:#a52a2a;&quot;&gt;|&amp;gt;&lt;/span&gt; bold &lt;span style=&quot;color:#a52a2a;&quot;&gt;|&amp;gt;&lt;/span&gt; paragraph &lt;span style=&quot;color:#a52a2a;&quot;&gt;|&amp;gt;&lt;/span&gt; add&lt;br /&gt;&amp;nbsp; &amp;nbsp; answer &lt;span style=&quot;color:#a52a2a;&quot;&gt;|&amp;gt;&lt;/span&gt; sprintf &lt;span style=&quot;color:#3cb371;&quot;&gt;&amp;quot;%A&amp;quot;&lt;/span&gt; &lt;span style=&quot;color:#a52a2a;&quot;&gt;|&amp;gt;&lt;/span&gt; run &lt;span style=&quot;color:#a52a2a;&quot;&gt;|&amp;gt;&lt;/span&gt; paragraph &lt;span style=&quot;color:#a52a2a;&quot;&gt;|&amp;gt;&lt;/span&gt; add&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;А теперь сравните с вот этой прелестью, сильно смахивающей на Лисп:&lt;br /&gt;&lt;div style=&quot;font-family:monospace;color:#006;border:1px solid #d0d0d0;background-color:#f0f0f0;&quot;&gt;&lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;let&lt;/span&gt; test &lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;textBox: RichTextBox&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt; number answer &lt;span style=&quot;color:#a52a2a;&quot;&gt;=&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; textBox.&lt;span style=&quot;color:#060;&quot;&gt;Document&lt;/span&gt;.&lt;span style=&quot;color:#060;&quot;&gt;Blocks&lt;/span&gt;.&lt;span style=&quot;color:#060;&quot;&gt;Add&lt;/span&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;Paragraph&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;Bold&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;Run&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;sprintf &lt;span style=&quot;color:#3cb371;&quot;&gt;&amp;quot;Testcase %d:&amp;quot;&lt;/span&gt; number&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; textBox.&lt;span style=&quot;color:#060;&quot;&gt;Document&lt;/span&gt;.&lt;span style=&quot;color:#060;&quot;&gt;Blocks&lt;/span&gt;.&lt;span style=&quot;color:#060;&quot;&gt;Add&lt;/span&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;Paragraph&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;Run&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;sprintf &lt;span style=&quot;color:#3cb371;&quot;&gt;&amp;quot;%A&amp;quot;&lt;/span&gt; answer&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;Не спорю, оно короче. Но при чуть более обширной схеме XAML уже пришлось бы сильно поднапрячься, чтобы выяснить, что в чем расположено. Ну или другой вариант: сгенерировать сразу большую строку XAML-a, вформатировав туда нужные данные, и скормить ее парсеру.&lt;br /&gt;Но зачем? Если можно так, как в первом случае :)&lt;br /&gt;&lt;br /&gt;Вообще-то, оба аргумента покрывают одну и ту же проблему: функции F# и методы .NET, на котором оно построено, имеют разную природу, синтаксис вызова и парадигму. И потому при переходе из одного мира в другой, и обратно, приходится порою чесать себе затылок.&lt;br /&gt;&lt;br /&gt;&quot;Запад есть запад, Восток есть Восток, и им не сойтись никогда&quot;. ©</description>
         <guid isPermaLink="false">urn:lj:livejournal.com:atom1:skiminog:63921</guid>
         <pubDate>Mon, 01 Feb 2010 23:31:11 +0000</pubDate>
      </item>
      <item>
         <title>SICP и ФП. Хроники мозга. Вырезка #2: машина Тьюринга на F#</title>
         <link>http://skiminog.livejournal.com/62131.html</link>
         <description>Этим вечером я, будучи очень начинающим функциональщиком, чисто тренировки ради решил написать на F# эмулятор машины Тьюринга. Что интересно, получается это замечательно просто. Из всего сделал такие выводы:&lt;br /&gt;&lt;br /&gt;1. Читабельность ФП-кода (как для непосвященного, так и для кодера) намного выше писабельности. Скорее всего потому что он выглядит почти как обыкновенная книга по математике на английском языке.&lt;br /&gt;2. Когда пишешь ФП-код, периодически приходится сразу заботиться о производительности. Панацеей становится хвостовая рекурсия и хорошее владение функциональными структурами данных или методами, которые позволяют их эмулировать. Ил и забить на чистоту и юзать массивы :)&lt;br /&gt;Но в моем случае я как честный человек писал тренировку, поэтому к массивам не прикасался, зато придумал для эмулятора удобный способ такой же сложности доступа к ячейке. В сущности, это сделало код еще более похожим на математическое определении конфигурации МТ.&lt;br /&gt;3. Конкретно язык F# обладает одной занятной особенностью: он перенасыщен языковыми конструкциями для особых случаев. В отличие от любого другого ЯП, который я учил в своей жизни, здесь уже через несколько дней начинаешь путаться. Потом все потихоньку утрясается, конечно, но осадок остается.&lt;br /&gt;4. Паттерн-матчинг — таки мощь :)&lt;br /&gt;&lt;br /&gt;Код под катом, если кому интересно. Естественно, он не претендует на идеальность, автор разрешает пользоваться им в любых целях с указанием исходного авторства, дополнения в комментах приветствуются бла бла бла...&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;font-family:monospace;color:#006;border:1px solid #d0d0d0;background-color:#f0f0f0;&quot;&gt;&lt;span style=&quot;color:#5d478b;font-style:italic;&quot;&gt;#light&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;open&lt;/span&gt; System&lt;br /&gt;&lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;open&lt;/span&gt; System.&lt;span style=&quot;color:#060;&quot;&gt;Linq&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color:#5d478b;font-style:italic;&quot;&gt;// ================= Type declarations ========================&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;type&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; Configuration &lt;span style=&quot;color:#a52a2a;&quot;&gt;=&lt;/span&gt; State &lt;span style=&quot;color:#a52a2a;&quot;&gt;*&lt;/span&gt; Tape &lt;span style=&quot;color:#a52a2a;&quot;&gt;*&lt;/span&gt; Tape&lt;br /&gt;&lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;and&lt;/span&gt; Tape &lt;span style=&quot;color:#a52a2a;&quot;&gt;=&lt;/span&gt; Symbol list&lt;br /&gt; &lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;and&lt;/span&gt; State &lt;span style=&quot;color:#a52a2a;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;int&lt;/span&gt;&lt;br /&gt; &lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;and&lt;/span&gt; Symbol &lt;span style=&quot;color:#a52a2a;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;char&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;type&lt;/span&gt;&lt;br /&gt; &amp;nbsp; &amp;nbsp; Rule &lt;span style=&quot;color:#a52a2a;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;State &lt;span style=&quot;color:#a52a2a;&quot;&gt;*&lt;/span&gt; Symbol&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color:#a52a2a;&quot;&gt;*&lt;/span&gt; &lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;State &lt;span style=&quot;color:#a52a2a;&quot;&gt;*&lt;/span&gt; Symbol &lt;span style=&quot;color:#a52a2a;&quot;&gt;*&lt;/span&gt; Direction&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt; &lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;and&lt;/span&gt; Direction &lt;span style=&quot;color:#a52a2a;&quot;&gt;=&lt;/span&gt; Left | Right | Stay&lt;br /&gt; &lt;br /&gt; &lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;type&lt;/span&gt;&lt;br /&gt; &amp;nbsp; &amp;nbsp; Program &lt;span style=&quot;color:#a52a2a;&quot;&gt;=&lt;/span&gt; Rule list&lt;br /&gt; &lt;br /&gt; &lt;span style=&quot;color:#5d478b;font-style:italic;&quot;&gt;// ==================== Useful functions =======================&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;let&lt;/span&gt; car &lt;span style=&quot;color:#a52a2a;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;function&lt;/span&gt;&lt;br /&gt; &amp;nbsp; &amp;nbsp; | h :: t &lt;span style=&quot;color:#a52a2a;&quot;&gt;-&amp;gt;&lt;/span&gt; h&lt;br /&gt; &amp;nbsp; &amp;nbsp; | &lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#91;&lt;/span&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#93;&lt;/span&gt; &lt;span style=&quot;color:#a52a2a;&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&quot;color:#3cb371;&quot;&gt;'_'&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;let&lt;/span&gt; cdr &lt;span style=&quot;color:#a52a2a;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;function&lt;/span&gt;&lt;br /&gt; &amp;nbsp; &amp;nbsp; | h :: t &lt;span style=&quot;color:#a52a2a;&quot;&gt;-&amp;gt;&lt;/span&gt; t&lt;br /&gt; &amp;nbsp; &amp;nbsp; | &lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#91;&lt;/span&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#93;&lt;/span&gt; &lt;span style=&quot;color:#a52a2a;&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#91;&lt;/span&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#93;&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &lt;span style=&quot;color:#5d478b;font-style:italic;&quot;&gt;// ======================= Turing machine ==========================&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;let&lt;/span&gt; write lTape rTape sym &lt;span style=&quot;color:#a52a2a;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;function&lt;/span&gt;&lt;br /&gt; &amp;nbsp; &amp;nbsp; | Stay &lt;span style=&quot;color:#a52a2a;&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;lTape, &lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#91;&lt;/span&gt;sym&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#93;&lt;/span&gt; @ cdr rTape&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt; &amp;nbsp; &amp;nbsp; | Left &lt;span style=&quot;color:#a52a2a;&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;cdr lTape, &lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#91;&lt;/span&gt;car lTape&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#93;&lt;/span&gt; @ &lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#91;&lt;/span&gt;sym&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#93;&lt;/span&gt; @ cdr rTape&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt; &amp;nbsp; &amp;nbsp; | Right &lt;span style=&quot;color:#a52a2a;&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;lTape @ &lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#91;&lt;/span&gt;sym&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#93;&lt;/span&gt;, cdr lTape&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;let&lt;/span&gt; apply state sym lTape rTape dir &lt;span style=&quot;color:#a52a2a;&quot;&gt;=&lt;/span&gt;&lt;br /&gt; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;let&lt;/span&gt; &lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;newLTape, newRTape&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color:#a52a2a;&quot;&gt;=&lt;/span&gt; write lTape rTape sym dir&lt;br /&gt; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;state, newLTape, newRTape&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;let&lt;/span&gt; step prog &lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;curSt, lTape, rTape&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color:#a52a2a;&quot;&gt;=&lt;/span&gt;&lt;br /&gt; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;let&lt;/span&gt; cur &lt;span style=&quot;color:#a52a2a;&quot;&gt;=&lt;/span&gt; car rTape&lt;br /&gt; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;let&lt;/span&gt; &lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;_, _&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt;, &lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;newSt, newSym, dir&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color:#a52a2a;&quot;&gt;=&lt;/span&gt; &lt;br /&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;a rel=&quot;nofollow&quot; style=&quot;color:#000060;&quot; target=&quot;_blank&quot; href=&quot;http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/manual/namespaces.html&quot;&gt;&lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;List&lt;/span&gt;&lt;/a&gt;.&lt;span style=&quot;color:#060;&quot;&gt;find&lt;/span&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;fun&lt;/span&gt; &lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;st, sym&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt;, &lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;_, _, _&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color:#a52a2a;&quot;&gt;-&amp;gt;&lt;/span&gt; st &lt;span style=&quot;color:#a52a2a;&quot;&gt;=&lt;/span&gt; curSt &amp;amp;&amp;amp; sym &lt;span style=&quot;color:#a52a2a;&quot;&gt;=&lt;/span&gt; cur&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt; prog&lt;br /&gt; &amp;nbsp; &amp;nbsp; apply newSt newSym lTape rTape dir&lt;br /&gt; &lt;br /&gt; &lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;let&lt;/span&gt; terminal &lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;state, _, _&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color:#a52a2a;&quot;&gt;=&lt;/span&gt;&lt;br /&gt; &amp;nbsp; &amp;nbsp; state &lt;span style=&quot;color:#a52a2a;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color:#c6c;&quot;&gt;0&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &lt;span style=&quot;color:#5d478b;font-style:italic;&quot;&gt;// ====================== Evaluation and printing ===========================&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;let&lt;/span&gt; tape &lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;str: &lt;a rel=&quot;nofollow&quot; style=&quot;color:#000060;&quot; target=&quot;_blank&quot; href=&quot;http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/manual/namespaces.html&quot;&gt;&lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;String&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color:#a52a2a;&quot;&gt;=&lt;/span&gt;&lt;br /&gt; &amp;nbsp; &amp;nbsp; str.&lt;span style=&quot;color:#060;&quot;&gt;ToCharArray&lt;/span&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;br /&gt; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color:#a52a2a;&quot;&gt;|&amp;gt;&lt;/span&gt; &lt;a rel=&quot;nofollow&quot; style=&quot;color:#000060;&quot; target=&quot;_blank&quot; href=&quot;http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/manual/namespaces.html&quot;&gt;&lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;List&lt;/span&gt;&lt;/a&gt;.&lt;span style=&quot;color:#060;&quot;&gt;ofArray&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;let&lt;/span&gt; toStr &lt;span style=&quot;color:#a52a2a;&quot;&gt;=&lt;/span&gt;&lt;br /&gt; &amp;nbsp; &amp;nbsp; &lt;a rel=&quot;nofollow&quot; style=&quot;color:#000060;&quot; target=&quot;_blank&quot; href=&quot;http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/manual/namespaces.html&quot;&gt;&lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;List&lt;/span&gt;&lt;/a&gt;.&lt;span style=&quot;color:#060;&quot;&gt;fold&lt;/span&gt; &lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;fun&lt;/span&gt; accum cur &lt;span style=&quot;color:#a52a2a;&quot;&gt;-&amp;gt;&lt;/span&gt; accum &lt;span style=&quot;color:#a52a2a;&quot;&gt;+&lt;/span&gt; cur.&lt;span style=&quot;color:#060;&quot;&gt;ToString&lt;/span&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color:#3cb371;&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;let&lt;/span&gt; print &lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;state, lTape, rTape&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color:#a52a2a;&quot;&gt;=&lt;/span&gt;&lt;br /&gt; &amp;nbsp; &amp;nbsp; Console.&lt;span style=&quot;color:#060;&quot;&gt;WriteLine&lt;/span&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;if&lt;/span&gt; state &lt;span style=&quot;color:#a52a2a;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color:#c6c;&quot;&gt;0&lt;/span&gt; &lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;then&lt;/span&gt; &lt;span style=&quot;color:#3cb371;&quot;&gt;&amp;quot;Final: {1}{2}{3}&amp;quot;&lt;/span&gt; &lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;else&lt;/span&gt; &lt;span style=&quot;color:#3cb371;&quot;&gt;&amp;quot;q{0}: &amp;nbsp; &amp;nbsp;{1}({2}){3}&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt;, &lt;br /&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; state, toStr &lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;a rel=&quot;nofollow&quot; style=&quot;color:#000060;&quot; target=&quot;_blank&quot; href=&quot;http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/manual/namespaces.html&quot;&gt;&lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;List&lt;/span&gt;&lt;/a&gt;.&lt;span style=&quot;color:#060;&quot;&gt;rev&lt;/span&gt; lTape&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt;, car rTape, toStr &lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;cdr rTape&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;state, lTape, rTape&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;let&lt;/span&gt; eval program &lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;string&lt;/span&gt;: &lt;a rel=&quot;nofollow&quot; style=&quot;color:#000060;&quot; target=&quot;_blank&quot; href=&quot;http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/manual/namespaces.html&quot;&gt;&lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;String&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt; startCur &lt;span style=&quot;color:#a52a2a;&quot;&gt;=&lt;/span&gt;&lt;br /&gt; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;let&lt;/span&gt; &lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;rec&lt;/span&gt; eval_iter program conf &lt;span style=&quot;color:#a52a2a;&quot;&gt;=&lt;/span&gt; &lt;br /&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;if&lt;/span&gt; terminal conf&lt;br /&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;then&lt;/span&gt; &lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;else&lt;/span&gt; eval_iter program &lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;step program conf &lt;span style=&quot;color:#a52a2a;&quot;&gt;|&amp;gt;&lt;/span&gt; print&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color:#c6c;&quot;&gt;1&lt;/span&gt;, &lt;a rel=&quot;nofollow&quot; style=&quot;color:#000060;&quot; target=&quot;_blank&quot; href=&quot;http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/manual/namespaces.html&quot;&gt;&lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;List&lt;/span&gt;&lt;/a&gt;.&lt;span style=&quot;color:#060;&quot;&gt;rev&lt;/span&gt; &lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;tape &lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;string&lt;/span&gt;.&lt;span style=&quot;color:#060;&quot;&gt;Substring&lt;/span&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color:#c6c;&quot;&gt;0&lt;/span&gt;, startCur&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt;, tape &lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;string&lt;/span&gt;.&lt;span style=&quot;color:#060;&quot;&gt;Substring&lt;/span&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;startCur&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color:#a52a2a;&quot;&gt;|&amp;gt;&lt;/span&gt; print &lt;br /&gt; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color:#a52a2a;&quot;&gt;|&amp;gt;&lt;/span&gt; eval_iter program&lt;br /&gt; &lt;br /&gt; &lt;span style=&quot;color:#5d478b;font-style:italic;&quot;&gt;// ========================== Example =======================&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;let&lt;/span&gt; add1_program &lt;span style=&quot;color:#a52a2a;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#91;&lt;/span&gt;&lt;br /&gt; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color:#c6c;&quot;&gt;1&lt;/span&gt;, &lt;span style=&quot;color:#3cb371;&quot;&gt;'0'&lt;/span&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt;, &lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color:#c6c;&quot;&gt;0&lt;/span&gt;, &lt;span style=&quot;color:#3cb371;&quot;&gt;'1'&lt;/span&gt;, Stay&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color:#a52a2a;&quot;&gt;;&lt;/span&gt;&lt;br /&gt; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color:#c6c;&quot;&gt;1&lt;/span&gt;, &lt;span style=&quot;color:#3cb371;&quot;&gt;'1'&lt;/span&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt;, &lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color:#c6c;&quot;&gt;1&lt;/span&gt;, &lt;span style=&quot;color:#3cb371;&quot;&gt;'0'&lt;/span&gt;, Left&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color:#a52a2a;&quot;&gt;;&lt;/span&gt;&lt;br /&gt; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color:#c6c;&quot;&gt;1&lt;/span&gt;, &lt;span style=&quot;color:#3cb371;&quot;&gt;'_'&lt;/span&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt;, &lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color:#c6c;&quot;&gt;0&lt;/span&gt;, &lt;span style=&quot;color:#3cb371;&quot;&gt;'1'&lt;/span&gt;, Stay&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#93;&lt;/span&gt;&lt;br /&gt; &lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;let&lt;/span&gt; number &lt;span style=&quot;color:#a52a2a;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color:#3cb371;&quot;&gt;&amp;quot;11111&amp;quot;&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; eval add1_program number &lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;number.&lt;span style=&quot;color:#060;&quot;&gt;Length&lt;/span&gt; &lt;span style=&quot;color:#a52a2a;&quot;&gt;-&lt;/span&gt; &lt;span style=&quot;color:#c6c;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt; Console.&lt;span style=&quot;color:#060;&quot;&gt;Read&lt;/span&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color:#6c6;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color:#a52a2a;&quot;&gt;|&amp;gt;&lt;/span&gt; &lt;span style=&quot;color:#06c;font-weight:bold;&quot;&gt;ignore&lt;/span&gt;&lt;/div&gt;&lt;a rel=&quot;nofollow&quot; name='cutid1-end'&gt;&lt;/a&gt;</description>
         <guid isPermaLink="false">urn:lj:livejournal.com:atom1:skiminog:62131</guid>
         <pubDate>Thu, 14 Jan 2010 23:58:10 +0000</pubDate>
      </item>
      <item>
         <title>skiminog @ 2009-12-12T22:20:00</title>
         <link>http://skiminog.livejournal.com/59424.html</link>
         <description>&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href='http://lorgonblog.spaces.live.com'&gt;http://lorgonblog.spaces.live.com&lt;/a&gt;&lt;br /&gt;Много, много F#.&lt;br /&gt;Особенно впечатляют 8 статей про тот самый пресловутый катаморфизм (&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://lorgonblog.spaces.live.com/blog/cns!701679AD17B6D310!170.entry&quot;&gt;вот начало&lt;/a&gt;). Вечерком в субботу — самое оно для мозга =)&lt;br /&gt;&lt;br /&gt;P.S. &lt;span class=&quot;ljuser  i-ljuser  i-ljuser-type-P     &quot;&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://sofigenr.livejournal.com/profile&quot; class=&quot;i-ljuser-profile&quot;&gt;&lt;img class=&quot;i-ljuser-userhead&quot; src=&quot;http://l-stat.livejournal.net/img/userinfo.gif?v=17080?v=131.4&quot;/&gt;&lt;/a&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://sofigenr.livejournal.com/&quot; class=&quot;i-ljuser-username&quot;&gt;&lt;b&gt;sofigenr&lt;/b&gt;&lt;/a&gt;&lt;/span&gt; , рекомендую! ;-)</description>
         <guid isPermaLink="false">urn:lj:livejournal.com:atom1:skiminog:59424</guid>
         <pubDate>Sat, 12 Dec 2009 20:20:42 +0000</pubDate>
      </item>
      <item>
         <title>«Programming F#» by Chris Smith</title>
         <link>http://ru-fsharp.livejournal.com/1833.html</link>
         <description>&lt;p&gt;
    &lt;span style=&quot;float:left;padding:3px 3px 3px 3px;&quot;&gt;
      &lt;img src=&quot;http://covers.oreilly.com/images/9780596153656/cat.gif&quot; alt=&quot;Programming F#&quot;/&gt;&lt;br /&gt;
      &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.amazon.com/Programming-Animal-Guide-Smith-Chris/dp/0596153643&quot;&gt;Купить&lt;/a&gt;&lt;br /&gt;
      
    &lt;/span&gt;
    В октябре вышла новая книжка «Programming F#» by &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://blogs.msdn.com/chrsmith/&quot;&gt;Chris Smith&lt;/a&gt;. Подробный отзыв я написать не могу, потому что, во-первых, ещё не дочитал и, во-вторых, сейчас на работе. Но на первый взгляд книжка хороша. Не нужно продираться через кучу вводных глав с доказательством труъёвости ФП и всякой философией, можно сразу начать осваивать синтаксис. В коде автор ориентируется на актуальное состояние языка (версия компилятора — 1.9.8.0), разъясняет особенности сборки многофайловых проектов в Visual Studio 2010, касается механизмов работы .NET CLR. Чем-то напоминает YAHT.
  &lt;/p&gt;</description>
         <author>Qbit</author>
         <guid isPermaLink="false">urn:lj:livejournal.com:atom1:ru_fsharp:1833</guid>
         <pubDate>Mon, 30 Nov 2009 08:47:14 +0000</pubDate>
      </item>
      <item>
         <title>PDC2008: An Introduction to Microsoft F#</title>
         <link>http://skiminog.livejournal.com/57073.html</link>
         <description>&lt;p&gt;Я год назад не интересовался и не просматривал видео с конференции PDC, поэтому только сейчас наткнулся на этот превосходный доклад:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;center&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://channel9.msdn.com/pdc2008/TL11/&quot;&gt;&lt;img src=&quot;http://mschnlnine.vo.llnwd.net/d1/pdc08/THUMBNAILS/TL11.jpg&quot;&gt;&lt;/a&gt;&lt;/center&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;По своей привычной традиции, процитирую самые замечательные шутки и фразы из речи докладчика:&lt;br /&gt;&lt;br /&gt;&lt;p&gt;(02:33) It's like going to a bar and telling the guy behind the counter &quot;I want cappucino&quot; or going to a bar and tell to the same guy &quot;You know, now you grind the coffee, then get the water, warm it, you know, at the same time prepare the milk, and I want these two things do in parallel...&quot; &lt;i&gt;(смех в зале)&lt;/i&gt; ...I came up with it five minutes ago.&lt;br /&gt;&lt;br /&gt;(03:30) Look at this. &lt;i&gt;(На слайде запись &quot;X = X + 1&quot;)&lt;/i&gt; As programmers' it makes perfect sense. But if you take the more declarative view of this and you look at this as a mathematician, this is an equation that doesn't make any sense.&lt;br /&gt;&lt;br /&gt;(07:42) By the way, this is Visual Studio, it doesn't look like Visual Studio, because I disabled everything. If you go to Tools &amp;gt; Options and uncheck like a crazy man, you can get it to look like this.&lt;br /&gt;&lt;br /&gt;(08:30) #light... I wouldn't mind it much, just put it on top of your files and life is good.&lt;br /&gt;&lt;br /&gt;(17:15) &quot;Match&quot;? Think of it as it's &quot;switch&quot; on steroids.&lt;br /&gt;&lt;br /&gt;(19:53) This operator, as we call &quot;pipeline operator&quot;, is the second most important operator in F#. The first one is &quot;let&quot;, which is a keyword, the second one is pipeline. So you're really know 2/3 of the language now.&lt;br /&gt;&lt;br /&gt;(27:25) That's ironical that I'm looking up for Microsoft at the Yahoo! website...&lt;br /&gt;&lt;br /&gt;(31:44) It's a functional language, but, you know, it's usable.&lt;br /&gt;&lt;br /&gt;(52:19) It's just a .NET class, there's no way to know that he came from F#... Well, there's no easy way.&lt;br /&gt;&lt;br /&gt;(56:10) And when I want to release control, I just say &quot;Bang!&quot; &lt;i&gt;(печатает &quot;!&quot;)&lt;/i&gt;, and I call the asynchronous version of my method &lt;i&gt;(печатает &quot;async&quot;)&lt;/i&gt;&lt;a rel=&quot;nofollow&quot; name='cutid1-end'&gt;&lt;/a&gt;</description>
         <guid isPermaLink="false">urn:lj:livejournal.com:atom1:skiminog:57073</guid>
         <pubDate>Thu, 12 Nov 2009 18:53:09 +0000</pubDate>
      </item>
      <item>
         <title>F# 1.9.7.8 aka October 2009 CTP</title>
         <link>http://ru-fsharp.livejournal.com/1712.html</link>
         <description>«The latest release of F# is now out! This is included in Visual Studio 2010 Beta2, released today for MSDN Subscribers, with the matching release of the F# CTP for Visual Studio 2008, and a compiler ZIP for Mono.» &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://blogs.msdn.com/dsyme/archive/2009/10/19/visual-studio-2010-beta2-with-f-is-now-available-plus-matching-f-ctp-update-for-vs2008.aspx&quot;&gt;©&lt;/a&gt; Don Syme&lt;br /&gt;&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://blogs.msdn.com/dsyme/archive/2009/10/19/release-notes-for-the-f-october-2009-release.aspx&quot;&gt;Release Notes&lt;/a&gt;&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.microsoft.com/downloads/details.aspx?FamilyID=b55f0532-ac3c-4106-918c-5586a953a7da&amp;amp;displaylang=en&quot;&gt;Download&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;(&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.rsdn.ru/forum/decl/3575701.aspx&quot;&gt;via&lt;/a&gt; RSDN)</description>
         <author>Qbit</author>
         <guid isPermaLink="false">urn:lj:livejournal.com:atom1:ru_fsharp:1712</guid>
         <pubDate>Tue, 20 Oct 2009 10:19:09 +0000</pubDate>
      </item>
      <item>
         <title>VSLab</title>
         <link>http://ru-fsharp.livejournal.com/1352.html</link>
         <description>&lt;p&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.codeplex.com/vslab&quot;&gt;VSLab&lt;/a&gt; — это попытка превратить связку Visual Studio + F# в MatLab:&lt;/p&gt;

  &lt;img src=&quot;http://i3.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=vslab&amp;amp;DownloadId=38307&quot; style=&quot;border-width:1px;border-style:solid;&quot; width=&quot;800&quot; height=&quot;483&quot;/&gt;

  &lt;p&gt;Справедливости ради надо отметить, что на картинках всё выглядит радужнее, чем в действительности :) Документации мало (зато открыты исходники), готовые viewlet'ы не так хорошо кастомизируются, как хотелось бы (зато можно писать свои). Если заинтересует, начните с &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://cvslab.di.unipi.it/vslab/blog/page/Visual-Tutorial.aspx&quot;&gt;туториала&lt;/a&gt; и пройдитесь по &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://cvslab.di.unipi.it/vslab/blog/&quot;&gt;официальному блогу&lt;/a&gt;.&lt;/p&gt;</description>
         <author>Qbit</author>
         <guid isPermaLink="false">urn:lj:livejournal.com:atom1:ru_fsharp:1352</guid>
         <pubDate>Sun, 11 Oct 2009 12:52:09 +0000</pubDate>
      </item>
      <item>
         <title>Создание DSL на языке F#</title>
         <link>https://nesteruk.wordpress.com/2009/08/29/dsl-fsharp/</link>
         <description>Хочу представить сообществу перевод моей статьи на CodeProject, в которой я описываю процесс создания DSLей с использованием языка F#. Введение Если честно, мне уже изрядно поднадоели разговоры о DSLях в чисто академическом ключе. Хочется увидеть конкретный пример того, как это счастье используется «в продакшн». Да и вообще, саму концепцию можно объяснить и реализовать намного более [&amp;#8230;]&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;https://pixel.wp.com/b.gif?host=nesteruk.wordpress.com&amp;#038;blog=373435&amp;#038;post=614&amp;#038;subd=nesteruk&amp;#038;ref=&amp;#038;feed=1&quot; width=&quot;1&quot; height=&quot;1&quot;/&gt;</description>
         <guid isPermaLink="false">http://nesteruk.wordpress.com/?p=614</guid>
         <pubDate>Sat, 29 Aug 2009 07:14:30 +0000</pubDate>
         <content:encoded><![CDATA[<p>Хочу представить сообществу перевод моей статьи на CodeProject, в которой я описываю процесс создания DSLей с использованием языка F#.</p>
<h3>Введение</h3>
<p>Если честно, мне уже изрядно поднадоели разговоры о DSLях в чисто академическом ключе. Хочется увидеть конкретный пример того, как это счастье используется «в продакшн». Да и вообще, саму концепцию можно объяснить и реализовать намного более доходчиво и прямолинейно чем делают авторы таких фреймворков как Oslo или MPS. Собственно тут я как раз и хочу показать решение которое вовсе не академическое а именно производственное, и служит конкретным целям.</p>
<p>Начнем с того, что обсудим что же такое DSL. DSL &ndash; доменно специфичный язык &ndash; то есть способ описания той или иной предметной специфики (которая часто связана с конкретной индустрией) с помощью такого языка, который могут понять не только разработчики, но и эксперты в предметной области. Важно в этом языке то, что те кто его используют не должны думать о фигурных скобочках, точках с запятой и прочих прелестях программирования. То есть у них должна быть возможность писать на «простом английском» (русском, японском, и т.д.)</p>
<p>В этом очерке мы будем использовать язык F# для написания DSLи которая помогает нам делать оценку трудоемкости проектов. Более заумная версия этой DSLины используется у нас на производстве. Сразу скажу, что тот код который я покажу далеко не идеальный пример использования F#, так что все «камни в огород» в плане стиля программирования буду игнорировать. Суть-то не в этом. Впрочем, если есть желание пооптимизировать &ndash; пожалуйста.</p>
<p>Ах да, и вот еще что &ndash; сразу дам ссылочки на <a rel="nofollow" target="_blank" href="http://www.codeproject.com/KB/dotnet/dslfsharp.aspx" title="http://www.codeproject.com/KB/dotnet/dslfsharp.aspx">оригинал статьи</a> и <a rel="nofollow" target="_blank" href="http://www.codeproject.com/KB/dotnet/dslfsharp/EstimationDSL.zip" title="http://www.codeproject.com/KB/dotnet/dslfsharp/EstimationDSL.zip">исходный код</a>. Код &ndash; это по сути дела один <code>.fs</code> файл. Надеюсь у вас получится его скомпилировать. Для того чтобы оценить то, как он работает, вам потребуется Project 2007. Если у вас его нет, спросите ближесидящего PMа.</p>
<p>Итак, в путь!</p>
<h3>Описание Проблемы</h3>
<p>Когда кому-то нужно заказное ПО, этот кто-то (обычно именуется «заказчик») шлет разным фирмам так называемый RFP (request for proposal), то есть по сути дела описание своего проекта. На этот запрос фирмы-разработчики делают проектный план (если инфы достаточно &ndash; если нет, то начинают общаться), пакуют его в красивый PDF и отсылают назад, причем естественно чем быстрее произведена оценка (эстимейт), чем она качественней и чем лучше преподнесена, тем больше вероятность что клиент будет с вами общаться. Получается что в интересах всей фирмы сделать этот эстимейт хорошо и быстро.</p>
<p>Кто-то должен делать этот эстимейт&hellip; обычно «крайним» является какой-нибудь релаксирующий под музыку PM, который достаточно знает технологический стек и имеет хоть чуть-чуть опыта чтобы прикинуть что и так (механизм peer review, если он налажен, все равно сгладит все его косяки). Так вот, наш РМ должен оценить этапы проекта и сделать красивый временной график (кажется это называется GANTT chart) чтобы наглядно показать на что пойдут усилия разработчиков, тестировщиков, и свои тоже. Тут возникает проблема.</p>
<p>Проблема в том что MS Project, та тулза которой создается это счастье, не очень то быстра на подъем когда нужно постоянно реструктурировать оценки, менять таски местами, корректировать ресурсы, оверхед, ну и т.д. Все становится слишком напряжно, особенно если вы придерживаетесь правила что «каждый клиент должен получить эстимейт в пределах одного дня своей временной зоны». Приходится изворачиваться, и наш DSL &ndash; это попытка упростить и ускорить оценочную деятельность для всех участников.</p>
<h3>Выбор Языка</h3>
<p>Проблему мы описали, теперь о решении. В принципе, для описания проекта можно сделать «свободную» DSL где можно использовать любой синтаксис и потом парсить его с помощью умных фреймворков, но это как-то скучно если учесть что эти фреймворки ничего не добавят в результат, зато наверняка принесут немного головной боли. Поэтому более простым подходом будет выбор языка (в нашем случае &ndash; языка в .Net стеке) который позволит писать на «почти Английском языке» и не будет сильно напрягать нетехнический персонал (хотя если РМ не умеет программировать, то это не к нам).</p>
<p>Из популярных языков для DSLей конечно нужно отметить Boo, который неплохо пропиарил Ayende в <a rel="nofollow" target="_blank" href="http://www.manning.com/rahien/" title="http://www.manning.com/rahien/">своей книге</a>. Boo &ndash; очень мощный язык, но в данном случае его метапрограммисткая мощь нам не потребуется. Еще есть язык Ruby который тоже популярен в плане DSLей но я к сожалению с ним не знаком (досадное упущение), поэтому не могу его порекоммендовать. Ну и последний выбор, на котором я и остановился, это F#.</p>
<p>Почему F# хорош для DSLей? Потому что его синтаксис не нагружает разум. Можно писать почти на чистом английском. DSL читаем кем угодно. Единственная проблема &ndash; это то, что F# ориентирован на неизменчивость переменных (immutability), поэтому в нашем контексте некоторые его конструкты будут выглядеть немного неестественно. Но, как я уже сказал, суть не в этом &ndash; ведь DSL это всего лишь трансформатор, «кондуит сознания».</p>
<h3>Первый Стейтмент</h3>
<p>Начнем с простого. Вот как выглядит первая строчка в описании проекта:</p>
<pre>
project &quot;Write F# DSL Article&quot; starts_on &quot;16/8/2009&quot;
</pre>
<p>То что вы видите выше &ndash; совершенно легальное выражение в F#. Мы просто вызываем метод <code>project</code> и передаем ему три параметра &ndash; имя проекта, некой токен (пустышку, которая служит англосинтактическим сахаром), и время начала проекта. Фактически мы делаем примерно то же, что делают с тестами в BDD &ndash; а именно, пытаются сделать их читабельными для нетехнарей.</p>
<p>DSLина которую мы пишем сама по себе основана на ООР. Наша цель &ndash; через DSL поддержать все те конструкции, к которым привыкли РМы. Одна из этих конструкций &ndash; проект, поэтому с него пожалуй и начнем:</p>
<pre>
type Project() =
  [&lt;DefaultValue&gt;] val mutable Name : string
  [&lt;DefaultValue&gt;] val mutable Resources : Resource list
  [&lt;DefaultValue&gt;] val mutable StartDate : DateTime
  [&lt;DefaultValue&gt;] val mutable Groups : Group list
</pre>
<p>Вот, я же предупреждал что F# не будет смотреться слишком шикарно если писать с поддержкой mutability. Странные конструкции выше &ndash; это публичные поля, которые можно изменять. В плане коллекций я воспользовался F#овским <code>list</code> вместо <code>List&lt;T&gt;</code> из <code>System.Collections.Generic</code>. Разницы особой нет.</p>
<p>В отличии от C#, в F# у нас есть нечто, что на первый взгляд можно именовать «global scope», то есть декларировать переменные и функции можно как бы «на верхнем уровне», без всяких явно описанных классов, модулей и пространств имен. Давайте этим незамедлительно воспользуемся:</p>
<pre>
/* Делаем проект. Переменная my_project будет в последствии переопределена. */
let mutable my_project = new Project()
</pre>
<p>Мы только что создали «переменную дефолтного проекта». Естественно что терминология в F# немного другая, но не суть. Имя мы выбрали такое, чтобы в конце можно было пафосно написать <code>prepare my_project</code> и запустить автогенерацию проектного плана. А пока давайте посмотрим на функцию <code>project</code>, с которой все и начинается.</p>
<pre>
/* Поддержка создания нового проекта.
Как и обещалось, переменная my_project переписывается.
Полезно если нужно делать несколько проектов подряд. */
let project name startskey start =
  my_project &lt;- new Project()
  my_project.Name &lt;- name
  my_project.Resources &lt;- []
  my_project.Groups &lt;- []
  my_project.StartDate &lt;- DateTime.Parse(start)
</pre>
<p>Ну вот. В принципе, на этом этапе можно смело бросать читать статью и идти экспериментировать &ndash; ведь всю суть создания DSLей на F# мы только что показали. Дальше будет разбор семантики и собственно демонстрация того, как разруливаются разные тонкости.</p>
<h3>Работа со Списками</h3>
<p>Работа в проекте выполняется ресурсами, то есть людьми. Вы ресурс, и я ресурс &ndash; не очень-то приятно, не так ли? Тем не менее, у каждого ресурса есть некий титул (к пр. «Junior Developer»), имя («John») а также рейт &ndash; сколько долларов в час фирма хочет получать в месяц за работу этого ресурса. Давайте сначала посмотрим на определение этого самого ресурса:</p>
<pre>
type Resource() =
  [&lt;DefaultValue&gt;] val mutable Name : string
  [&lt;DefaultValue&gt;] val mutable Position : string
  [&lt;DefaultValue&gt;] val mutable Rate : int
</pre>
<p>Теперь можно посмотреть на то, как будет выглядеть создание ресурса в нашей DSL:</p>
<pre>
resource &quot;John&quot; isa &quot;Junior Developer&quot; with_rate 55
</pre>
<p>Конечно же, для поддержки выражения выше мы используем то же шаманство что и для проектов, а именно:</p>
<pre>
let resource name isakey position ratekey rate =
  let r = new Resource()
  r.Name &lt;- name
  r.Position &lt;- position
  r.Rate &lt;- rate
  my_project.Resources &lt;- r :: my_project.Resources
</pre>
<p>Как вы уже наверное догадались, мы создаем ресурс и добавляем его в <em><font face="Trebuchet MS">начало</font></em> списка. Это значит что когда придет время «выстраивать» ресурсы и прочие элементы которые хранятся в списках, каждый список придется разворачивать задом на перед. Для меня это не проблема, но если вам не нравится &ndash; используйте <code>List&lt;T&gt;</code>.</p>
<h3>Строковые Ссылки</h3>
<p>Следующая концепция в нашей DSL &ndash; это группы заданий. Группу заданий в проекте обычно выполняет один человек, что способствует поддержанию «когнитивного фокуса». Группу мы определяем вот так:</p>
<pre>
group &quot;Project Coordination&quot; done_by &quot;Dmitri&quot;
</pre>
<p>А вот как выглядит объект, который содержит данные о группе:</p>
<pre>
type Group() =
  [&lt;DefaultValue&gt;] val mutable Name : string
  [&lt;DefaultValue&gt;] val mutable Person : Resource
  [&lt;DefaultValue&gt;] val mutable Tasks : Task list
</pre>
<p>Видите &ndash; группы ссылается на <em><font face="Trebuchet MS">объект</font></em> типа <code>Resource</code>, а мы передаем имя (строку). Но это не проблема, так как поиск в списках никто не отменял:</p>
<pre>
let group name donebytoken resource =
  let g = new Group()
  g.Name &lt;- name
  g.Person &lt;- my_project.Resources |&gt; List.find(fun f -&gt; f.Name = resource)
  /* Ищем тот ресурс что нам нужен. */
  my_project.Groups &lt;- g :: my_project.Groups
</pre>
<p>В отличии от LINQ, не надо вызывать <code>Single()</code> чтобы получить результат поиска.</p>
<h3>Побольше Гибкости</h3>
<p>Группы тасков (заданий) состоят из, эммм, заданий. А задание неплохо определять вот так:</p>
<pre>
task &quot;PayPal Integration&quot; takes 2 weeks
</pre>
<p>Это тоже реально в F#! Для начала, мы делаем так, чтобы те токены которые мы обычно используем для «сахара» содержали внятные значения:</p>
<pre>
let hours = 1
let hour = 1
let days = 2
let day = 2
let weeks = 3
let week = 3
let months = 4
let month = 4
</pre>
<p>Теперь мы можем определить наш <code>Task</code>:</p>
<pre>
type Task() =
  [&lt;DefaultValue&gt;] val mutable Name : string
  [&lt;DefaultValue&gt;] val mutable Duration : string
</pre>
<p>А добавление таска в группу выглядит вот так:</p>
<pre>
let task name takestoken count timeunit =
  let t = new Task()
  t.Name &lt;- name
  let dummy = 1 + count
  /* Это хак. Суть в том, чтобы заставить компилятор думать что count - это int.
     Иначе банально не сработает угадываение типов, ведь в качестве подсказок есть 
     только String.Format ниже. */
  match timeunit with
  | 1 -&gt; t.Duration &lt;- String.Format(&quot;{0}h&quot;, count)
  | 2 -&gt; t.Duration &lt;- String.Format(&quot;{0}d&quot;, count)
  | 3 -&gt; t.Duration &lt;- String.Format(&quot;{0}wk&quot;, count)
  | 4 -&gt; t.Duration &lt;- String.Format(&quot;{0}mon&quot;, count)
  | _ -&gt; raise(ArgumentException(&quot;only spans of hour(s), day(s), week(s) and month(s) are supported&quot;))
  /* А вот тут мы сохраняем продолжительность таска как строковый литерал,
который угоден Project'у. */
  let g = List.hd my_project.Groups
  g.Tasks &lt;- t :: g.Tasks
</pre>
<p>В коде выше мы в зависимости от временной константы подстраиваем продолжительность таска. Для того чтобы найти ту группу, в которую нужно добавить таск, мы используем <code>List.hd</code> &ndash; ведь группы тоже задом наперед.</p>
<h3>Автогенерация Проекта</h3>
<p>Ну вот и все! Теперь мы можем вызвать одну помпезную комманду чтобы сгенерировать наш проектный план:</p>
<pre>
prepare my_project
</pre>
<p>Далее идет самый сложный кусочек &ndash; использование Office Automation и F# в тандеме для генерации плана из нашей DSLки. Я постарался прокомментировать код чтобы было понятно что к чему.</p>
<pre>
let prepare (proj:Project) =
  let app = new ApplicationClass()
  app.Visible &lt;- true
  let p = app.Projects.Add()
  p.Name &lt;- proj.Name
  /* Добавляем в проект ресурсы.
     Стоимость ресурса в овертайм считаем как полтора рейта. */
  proj.Resources |&gt; List.iter(fun r -&gt;
    let r2 = p.Resources.Add()
    r2.Name &lt;- r.Position // position, not name :)
    let tables = r2.CostRateTables
    let table = tables.[1]
    table.PayRates.[1].StandardRate &lt;- r.Rate
    table.PayRates.[1].OvertimeRate &lt;- (r.Rate + (r.Rate &gt;&gt;&gt; 1)))
  /* Делаем корневой таск с именем проекта. */
  let root = p.Tasks.Add()
  root.Name &lt;- proj.Name
  /* Добавляем группы. */
  proj.Groups |&gt; List.rev |&gt; List.iter(fun g -&gt; 
    let t = p.Tasks.Add()
    t.Name &lt;- g.Name
    t.OutlineLevel &lt;- 2s
    /* Кто отвечает за группу? */
    t.ResourceNames &lt;- g.Person.Position
    /* Добавляем задания. */
    let tasksInOrder = g.Tasks |&gt; List.rev
    tasksInOrder |&gt; List.iter(fun t2 -&gt;
        let t3 = p.Tasks.Add(t2.Name)
        t3.Duration &lt;- t2.Duration
        t3.OutlineLevel &lt;- 3s
        /* Ищем предыдущий таск. Если такой имеется, делаем связку
           между этим таском и предыдушим. Предполагается что все такси следуют один за другим. */
        let idx = tasksInOrder |&gt; List.findIndex(fun f -&gt; f.Equals(t2))
        if (idx &gt; 0) then 
          t3.Predecessors &lt;- Convert.ToString(t3.Index - 1)
      )
    )
</pre>
<p>Ну вот мы и «развернули» списки с помощью <code>List.rev</code> &ndash; не самая быстрая операция, конечно, но это не важно. Главное, что скрипт работает и генерит проекты &ndash; определяет ресурсы, группы тасков и сами таски. А что еще РМу надо? (На самом деле много чего :)</p>
<p>А вот как может выглядеть полное описание проекта с использованием нашей DSL:</p>
<pre>
project &quot;F# DSL Article&quot; starts &quot;01/01/2009&quot;
resource &quot;Dmitri&quot; isa &quot;Writer&quot; with_rate 140
resource &quot;Computer&quot; isa &quot;Dumb Machine&quot; with_rate 0
group &quot;DSL Popularization&quot; done_by &quot;Dmitri&quot;
task &quot;Create basic estimation DSL&quot; takes 1 day
task &quot;Write article&quot; takes 1 day
task &quot;Post article and wait for comments&quot; takes 1 week
group &quot;Infrastructure Support&quot; done_by &quot;Computer&quot;
task &quot;Provide VS2010 and MS Project&quot; takes 1 day
task &quot;Download and deploy TypograFix&quot; takes 1 day
task &quot;Sit idly while owner waits for comments&quot; takes 1 week
prepare my_project
</pre>
<h3>Заключение</h3>
<p>Надеюсь этот очерк показал вам, что делать DSL в F# &ndash; это просто. Конечно, тот пример что я привел выше упрощен по сравнению с тем что мы реально испольуем. Но это, как говорится, секреты фирмы. До новых встреч!</p><br />Рубрика:.NET, dsl, f#  <a rel="nofollow" target="_blank" href="http://feeds.wordpress.com/1.0/gocomments/nesteruk.wordpress.com/614/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/nesteruk.wordpress.com/614/"/></a> <img alt="" border="0" src="https://pixel.wp.com/b.gif?host=nesteruk.wordpress.com&#038;blog=373435&#038;post=614&#038;subd=nesteruk&#038;ref=&#038;feed=1" width="1" height="1"/>]]></content:encoded>
         <media:content medium="image" url="https://0.gravatar.com/avatar/f01cbd2238e2a78e4c43fa596f51d6a1?s=96&amp;amp;d=https%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&amp;amp;r=PG">
            <media:title type="html">nesteruk</media:title>
         </media:content>
      </item>
      <item>
         <title>F# 1.9.6.16</title>
         <link>http://ru-fsharp.livejournal.com/1131.html</link>
         <description>2009-05-20 стала доступна для скачивания Visual Sudio 2010 beta 1. Одновременно с ней вышел F# May 2009 CTP, который зафиксировал ту версию компилятора, которая вошла в бету Студии.&lt;br /&gt;&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://msdn.microsoft.com/en-us/fsharp/default.aspx&quot;&gt;Microsoft F# Developer Center&lt;/a&gt;&lt;br /&gt;&lt;tt&gt;├──&lt;/tt&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.microsoft.com/downloads/details.aspx?FamilyID=7bb32f32-9fac-4f34-ad56-b0bda130cf00&amp;amp;displaylang=en&quot;&gt;Скачать F# May 2009 CTP&lt;/a&gt;&lt;br /&gt;&lt;tt&gt;└──&lt;/tt&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://blogs.msdn.com/dsyme/archive/2009/05/20/visual-studio-2010-beta1-with-f-is-now-available-plus-matching-f-ctp-update-for-vs2008.aspx&quot;&gt;Дон Сайм о новых фичах&lt;/a&gt;&lt;br /&gt;&lt;tt&gt;   └──&lt;/tt&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://msdn.microsoft.com/en-us/library/dd233154(VS.100).aspx&quot;&gt;Предварительная документация в MSDN&lt;/a&gt;</description>
         <author>Qbit</author>
         <guid isPermaLink="false">urn:lj:livejournal.com:atom1:ru_fsharp:1131</guid>
         <pubDate>Sat, 23 May 2009 12:55:13 +0000</pubDate>
      </item>
      <item>
         <title>F# в блогах</title>
         <link>http://ru-fsharp.livejournal.com/945.html</link>
         <description>The Hub:&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://cs.hubfs.net/blogs/default.aspx&quot;&gt;http://cs.hubfs.net/blogs/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Tomas Petricek, автор книжки «&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.functional-programming.net/&quot;&gt;Functional Programming for the Real World&lt;/a&gt;»:&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://tomasp.net/blog/&quot;&gt;http://tomasp.net/blog/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Luca Bolognese, автор &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://channel9.msdn.com/pdc2008/TL11/&quot;&gt;отличной презентации&lt;/a&gt; на PDC 2008:&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://blogs.msdn.com/lucabol/&quot;&gt;http://blogs.msdn.com/lucabol/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Don Syme, создатель языка F#, автор книжки «&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.amazon.com/Expert-F-Experts-Voice-Net/dp/1590598504&quot;&gt;Expert F#&lt;/a&gt;»:&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://blogs.msdn.com/dsyme/&quot;&gt;http://blogs.msdn.com/dsyme/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Chris Smith, автор книжки «&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://oreilly.com/catalog/9780596801359/&quot;&gt;Programming F#&lt;/a&gt;»:&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://blogs.msdn.com/chrsmith/default.aspx&quot;&gt;http://blogs.msdn.com/chrsmith/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Strange Lights, Robert Pickering, автор книжки «&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.amazon.com/Foundations-F-Experts-Voice-Net/dp/1590597575/ref=ntt_at_ep_dpi_1&quot;&gt;Foundations of F#&lt;/a&gt;»:&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://strangelights.com/blog/default.aspx&quot;&gt;http://strangelights.com/blog/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;F# News, Jon Harrop, автор книжки «&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.amazon.com/F-Scientists-Jon-Harrop/dp/0470242116&quot;&gt;F# for Scientists&lt;/a&gt;»:&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://fsharpnews.blogspot.com/&quot;&gt;http://fsharpnews.blogspot.com/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Did it with .NET, Dustin Campbell:&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://diditwith.net/&quot;&gt;http://diditwith.net/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Luke Hoban:&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://blogs.msdn.com/lukeh/&quot;&gt;http://blogs.msdn.com/lukeh/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Brian McNamara:&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://lorgonblog.spaces.live.com/default.aspx&quot;&gt;http://lorgonblog.spaces.live.com/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Kean Walmsley, сотрудник Autodesk:&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://through-the-interface.typepad.com/through_the_interface/f/index.html&quot;&gt;http://through-the-interface.typepad.com/through_the_interface/f/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Jomo Fisher:&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://blogs.msdn.com/jomo_fisher/&quot;&gt;http://blogs.msdn.com/jomo_fisher/&lt;/a&gt;</description>
         <author>Qbit</author>
         <guid isPermaLink="false">urn:lj:livejournal.com:atom1:ru_fsharp:945</guid>
         <pubDate>Sun, 12 Apr 2009 22:04:40 +0000</pubDate>
      </item>
      <item>
         <title>Интервью с Доном Саймом</title>
         <link>http://ru-fsharp.livejournal.com/671.html</link>
         <description>На RSDN &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.rsdn.ru/forum/message/3348820.1.aspx&quot;&gt;дали ссылку&lt;/a&gt; на интересное интервью с разработчиком F#:&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.infoq.com/interviews/F-Sharp-Don-Syme&quot;&gt;http://www.infoq.com/interviews/F-Sharp-Don-Syme&lt;/a&gt;&lt;br /&gt;Интервью свёрстано довольно удобно — можно одновременно смотреть интервью и читать стенограмму, весьма упрощает восприятие речи на слух.&lt;br /&gt;&lt;img src=&quot;http://i41.tinypic.com/15ogcud.jpg&quot;/&gt;</description>
         <author>Qbit</author>
         <guid isPermaLink="false">urn:lj:livejournal.com:atom1:ru_fsharp:671</guid>
         <pubDate>Tue, 31 Mar 2009 21:50:47 +0000</pubDate>
      </item>
      <item>
         <title>Реальное приложение на F#</title>
         <link>http://dimandnk.blogspot.com/2009/03/f.html</link>
         <description>В своём прошлом посте я вскользь  упомянул новый функциональный язык программирования от Microsoft - F#. Он вызвал достаточно сильный интерес с моей стороны и сегодня попробую показать вам что-нибудь относительно полезное, написанное на нём. Но надо заметить, что я не знаю ни F#, ни C#, да и чего там скрывать... вообще не знаком с платформой .Net. Этот пример я взял с &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://channel9.msdn.com/pdc2008/TL11/&quot;&gt;презентации&lt;/a&gt; этого языка на &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.microsoftpdc.com/&quot;&gt;PDC2008&lt;/a&gt; и . Несколько примеров также можно найти &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://habrahabr.ru/blogs/starting_programming/51607/&quot;&gt;тут&lt;/a&gt; и тут. Для реализации нам понабятся Visual Studio 2008 и &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.microsoft.com/downloads/details.aspx?FamilyID=61ad6924-93ad-48dc-8c67-60f7e7803d3c&amp;amp;displaylang=en&quot;&gt;Microsoft F# CTP 1.9.6.2&lt;/a&gt;. Чтобы интегрировать F# в VS придётся проделать &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://habrahabr.ru/blogs/starting_programming/51350/&quot;&gt;несложные манипуляции&lt;/a&gt;.  В некоторых местах я буду приводить для сравнения участки кода, написанного на C#.&lt;br /&gt;&lt;br /&gt;Ну чтож... начнём) Наша задача: получить данные с &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://finance.yahoo.com/q/hp?s=MSFT&amp;amp;a=2&amp;amp;b=13&amp;amp;c=1986&amp;amp;d=2&amp;amp;e=9&amp;amp;f=2009&amp;amp;g=d&amp;amp;z=66&amp;amp;y=0&quot;&gt;сайта&lt;/a&gt; и обработать их (например отобразим первый и последний столбец).&lt;br /&gt;&lt;br /&gt;Первым делом подключим необходимые библиотеки:&lt;br /&gt;&lt;br /&gt;open System&lt;br /&gt;open System.Windows.Forms&lt;br /&gt;open System.Net&lt;br /&gt;open System.IO&lt;br /&gt;&lt;br /&gt;Далее нам нужна ссылка на файл данных. Поэтому перейдём на &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://finance.yahoo.com/q/hp?s=MSFT&amp;amp;a=2&amp;amp;b=13&amp;amp;c=1986&amp;amp;d=2&amp;amp;e=9&amp;amp;f=2009&amp;amp;g=d&amp;amp;z=66&amp;amp;y=0&quot;&gt;сайт&lt;/a&gt;, спустимся вниз и найдём кнопку Download To Spreadsheet. Кликнем по ней правой клавишей и скопируем ссылку.&lt;br /&gt;&lt;br /&gt;let url = &quot;http://ichart.finance.yahoo.com/table.csv?s=MSFT&amp;amp;d=2&amp;amp;e=9&amp;amp;f=2009&amp;amp;g=d&amp;amp;a=2&amp;amp;b=13&amp;amp;c=1986&amp;amp;ignore=.csv&quot;&lt;br /&gt;&lt;br /&gt;- это следущая строчка, после поключения библиотек, где let фактически создаёт псевдоним выражения. Кстати тип url задавать не нужно, F# сам определяет его. В С# это будет выглять так: string url = &quot;ссылка';&lt;br /&gt;&lt;br /&gt;Следующим этапом будет создание веб-запроса, потока обмена данными и чтением их в строку:&lt;br /&gt;&lt;br /&gt;let req = WebRequest.Create(url)&lt;br /&gt;let resp = req.GetResponse()&lt;br /&gt;let stream = resp.GetResponseStream()&lt;br /&gt;let reader = new StreamReader(stream)&lt;br /&gt;let csv = reader.ReadToEnd()&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Аналогичные действия на С#:&lt;br /&gt;&lt;br /&gt;WebRequest request = WebRequest.Create(url);&lt;br /&gt;WebResponse response = request.GetResponse();&lt;br /&gt;StreamReader reader = new StreamReader(response.GetResponseStream());&lt;br /&gt;csv = reader.ReadToEnd();&lt;br /&gt;&lt;br /&gt;Итак у нас есть последовательность с записей и нам их нужно разделить. Для этого используем функции Split, но пропустим первую строчку, т.к. там в исходном файле имена столбцов:&lt;br /&gt;&lt;br /&gt;let prices =&lt;br /&gt;       csv.Split([|'&amp;#92;n'|])&lt;br /&gt;       |&amp;gt; Seq.skip 1&lt;br /&gt;       |&amp;gt; Seq.map (fun line -&amp;gt; line.Split([|','|]))&lt;br /&gt;       |&amp;gt; Seq.filter (fun values -&amp;gt; values |&amp;gt; Seq.length = 7)&lt;br /&gt;       |&amp;gt; Seq.map (fun values -&amp;gt;&lt;br /&gt;           System.DateTime.Parse(values.[0]),&lt;br /&gt;           float values.[6])&lt;br /&gt;&lt;br /&gt;Здесь мы сталкиваемся с ещё 2-мя очень важными элементами F# - это fun (как можно догаться из названия задаёт функцию) и символ |&amp;gt; , который берёт входные данные слева от себя, производит действия и возвращает полученный результат, который может использоватться в следующей строчке с |&amp;gt;.&lt;br /&gt;&lt;br /&gt;Мне удалось сделать это на C# в таком виде:&lt;br /&gt;&lt;br /&gt;csv.Split('&amp;#92;n');&lt;br /&gt;           string [] line = str.Split('&amp;#92;n');&lt;br /&gt;           string[] elements;&lt;br /&gt;           for (int i = 1; i &amp;lt;= line.Length; i++)&lt;br /&gt; {                 elements = line[i].Split(',');                 ichTextBox1.Text = richTextBox1.Text + i + &quot;   &quot; + elements[0] + &quot;   &quot; + elements[5]+&quot;&amp;#92;n&quot;;&lt;br /&gt; }&lt;br /&gt; И если мы, выделив всё написанное выше, запустим на выполнение и в F#Interactive введём prices;; , то всё будет неплохо работать, но вывод данных неочень приятен и понятен, поэтому добавим форму и таблицу: &lt;br /&gt;let grid (prices:seq )=&lt;br /&gt;       let form = new Form(Width = 400, Height = 500, Visible = true, Text = &quot;Prices&quot;)&lt;br /&gt;       let grid = new DataGridView(Width = 282, Height = 374, Visible = true)&lt;br /&gt;       form.Controls.Add(grid)&lt;br /&gt;       grid.DataSource &amp;lt;- prices |&amp;gt; Seq.to_array&lt;br /&gt;&lt;br /&gt; Вот и всё. У меня получилась вот такая штука:&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://2.bp.blogspot.com/_jtJw2L283Bk/SbgPFF27CdI/AAAAAAAAABY/gDlxkZf-vZc/s1600-h/Example.JPG&quot;&gt;&lt;img style=&quot;margin:0pt 10px 10px 0pt;float:left;cursor:pointer;width:258px;height:320px;&quot; src=&quot;http://2.bp.blogspot.com/_jtJw2L283Bk/SbgPFF27CdI/AAAAAAAAABY/gDlxkZf-vZc/s320/Example.JPG&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5312012340629801426&quot; border=&quot;0&quot;/&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;На сегодня на этом и закончим. Если у вас есть идеи как изменить код к лучшему, то с удовольствием вас выслушаю.&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://ichart.finance.yahoo.com/table.csv?s=MSFT&amp;amp;a=2&amp;amp;b=13&amp;amp;c=1986&amp;amp;d=2&amp;amp;e=9&amp;amp;f=2009&amp;amp;g=d&amp;amp;ignore=.csv&quot;&gt;&lt;/a&gt;</description>
         <author>diman_dnk</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-2856148827732770010.post-3194071818210394387</guid>
         <pubDate>Wed, 11 Mar 2009 21:17:00 +0000</pubDate>
         <media:thumbnail height="72" url="http://2.bp.blogspot.com/_jtJw2L283Bk/SbgPFF27CdI/AAAAAAAAABY/gDlxkZf-vZc/s72-c/Example.JPG" width="72" xmlns:media="http://search.yahoo.com/mrss/"/>
      </item>
      <item>
         <title>Microsoft, Microsoft и ещё раз Microsoft</title>
         <link>http://dimandnk.blogspot.com/2009/03/microsoft-microsoft-microsoft.html</link>
         <description>Сегодня я хочу рассказать вам про Microsoft, а именно про моё посещения тренинга для студентов-партнёров в этой корпорации. Он проходил в офисе Microsoft в Москве на Крылатских Холмах 6 марта.&lt;br /&gt;Программа была очень насыщенной и включала 5 различных технологий, которые редмондская компания пытается привнести в наш с вами мир. Трениг проходил в ОС Windows 7, которая произвела на меня очень хорошее впечтление.&lt;br /&gt;Всё началось с F# - нового функционального языка программирования, который должен войти в состав Visual Studio 2010. Что же такое функциональные языки программирования?  Это языки, основным  конструктивным элементом является математическое &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://ru.wikipedia.org/wiki/%D0%9C%D0%B0%D1%82%D0%B5%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B0&quot; title=&quot;&amp;#x00041c;&amp;#x000430;&amp;#x000442;&amp;#x000435;&amp;#x00043c;&amp;#x000430;&amp;#x000442;&amp;#x000438;&amp;#x00043a;&amp;#x000430;&quot;&gt;&lt;/a&gt;понятие функции. Существует различия в понимании функции в математике и функции в программировании. Функция в математике не может изменить вызывающее её окружение и запомнить результаты своей работы, а только предоставляет результат вычисления функции. Также тексты программ на функциональных языках программирования описывают «как решить задачу», но не  предписывают последовательность действий для решения. Зачем Microsoft ставить его &quot;на одну доску&quot; с тем же C#? Я процитирую &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://blogs.msdn.com/sos/&quot;&gt;блог Дмитрия Сошникова&lt;/a&gt;, чтобы ответить на это вопрос. Одна из основных причин – функциональное программирование позволяет проще писать многопоточные приложения для многоядерных процессоров. Почему это так – мы рассмотрим в следующем уроке, где будем говорить о том, что же такое функциональное программирование. Кроме того, функциональные программы не допускают или минимизируют побочные эффекты, что увеличивает надежность программ и упрощает отладку. &quot;В целом можно сказать, что &lt;strong&gt;функциональное программирование позволяет нам писать в несколько раз меньше кода, но при этом заставляет больше думать&lt;/strong&gt;. Если Вы любите работать головой, а не пальцами – обратите внимание на F# и на функциональное программирование. А я постараюсь вам помочь сделать это безболезненно, на русском языке.&quot; Но не попробуешь - не поймёшь, поэтому нам предложили решить пару достаточно простых задачек на F#, которым я скорее всего посвящу свой следующий пост (для этого уже поставил Visual Studio 2008, распространяемую бесплатно среди аспирантов и студентов для некоммерческого использования).&lt;br /&gt;Потом перед нами выступал &lt;span lang=&quot;EN-US&quot;&gt;Дмитрий Мартынов с докладом о &lt;/span&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.microsoft.com/azure/default.mspx&quot;&gt;Windows &lt;/a&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.microsoft.com/azure/default.mspx&quot;&gt;Azure&lt;/a&gt;. Он объяснял, как это всё устроено, на чём можно писать приложения под эту платформу, как происходит идентификация пользователя и как это выгодно - хранить все данные out. Сейчас &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;&lt;/span&gt;Windows &lt;span lang=&quot;EN-US&quot;&gt;Azure находится в стадии beta-тестирования и потому доступ к ней может получить практически любой желающий и совершенно бесплатно. Если я ничего этим не нарушу, то попытаюсь подробно рассказать что да как, но в другой раз, сегодня же моя задача ввести вас в курс самых акуальных и передовых технологий Microsoft.&lt;br /&gt;Следующим этапом тренинга стал &lt;/span&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://silverlight.net/&quot;&gt;Silverlight&lt;/a&gt; &lt;span lang=&quot;EN-US&quot;&gt;2, работать с которым учил нас Михаил Черномордиков, который является одним из ведущих небезизвестного Podcast9. Примеры были очень хороши, но времени как всегда было мало, а хотелось бы узнать значительно больше (те кто смотрел инаугурацию Барака Обама знайте - именно технология Silverlight &lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt;дала вам эту возможность). Если вам хочется познакомиться с ней поближе, то вот вам ссылка на &lt;a rel=&quot;nofollow&quot;&gt;русскоязычное сообщество.&lt;/a&gt;&lt;br /&gt;После почти 4 часов непрерывного впитывания знаний нас ждал обед, талоны на который нам было любезно выданы. Надо сказать, что атмосфера царящая в Microsoft просто непередаема словами, это надо видеть и самому почувствовать на себе. Обеденный час подошёл к концу и мы опять отправились в тренниг класс, чтобы погрузиться в новые технологии.&lt;br /&gt;А там нас ждал &lt;/span&gt;Гайдар Магдануров, очень позитивный человк, который нёс в наши головы доброе и вечтное о ASP.&lt;span lang=&quot;EN-US&quot;&gt;NET MVC. Это фреймворк, работающий по принципу &lt;/span&gt;Model-view-controller - архитектуре программного обеспечения, когда приложения делится на 3 отдельных компонента: модель данных, т пользовательский интерфейс и управляющая логика. Мы на примере смогли убедиться в эффективности такого подхода, написав под чутким руководством простенькое приложение, тащащее информацию из базы данных.&lt;br /&gt;Заключительным этапом был &lt;span lang=&quot;EN-US&quot;&gt;SQL Server Data Services. Нам попытались объяснить что да как, но мозг к тому времени уже плохо цеплялся за информацию да и попробовать самим что-либо сделать нам не дали.&lt;br /&gt;На этом мой день в Microsoft закончился, но этим точно не закончатся мои посты о технологиях этой компании и в ближайщее время напишу что-нибудь про F#.&lt;br /&gt;&lt;br /&gt;Выражаю огромную благодарность Дмитрию Сошникову за возможность посмотреть на всё изнутри и за отличную организацию тренинга.&lt;br /&gt;&lt;/span&gt;</description>
         <author>diman_dnk</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-2856148827732770010.post-2396409210008068850</guid>
         <pubDate>Sat, 07 Mar 2009 18:41:00 +0000</pubDate>
      </item>
      <item>
         <title>F# presentations</title>
         <link>http://ru-fsharp.livejournal.com/456.html</link>
         <description>&lt;table&gt;
  &lt;tr&gt;
    &lt;td&gt;
      &lt;p&gt;
      &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://channel9.msdn.com/pdc2008/TL11/&quot;&gt;&lt;img src=&quot;http://mschnlnine.vo.llnwd.net/d1/pdc08/THUMBNAILS/TL11.jpg&quot; align=&quot;left&quot; hspace=&quot;4px&quot;/&gt;&lt;/a&gt;
      По ссылке — отличное введение в F#. Даже если вы далеки от ML-подобного синтаксиса, освоите 2/3 языка уже через 20 минут ;) Настоятельно советую посмотреть презентацию хотя бы потому, что &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://blogs.msdn.com/lucabol/&quot;&gt;докладчик&lt;/a&gt; — уж больно харизматичный персонаж, по всей видимости, итальянец. («Игрек» он называет «ипсилоном», что куда приятнее дурацкого английского «вай».) Характерный говоррр напомнил Анну Наваррро из «Deus Ex» и Infected Mushrooms в «Converting Vegetarians». А ещё вспомнились уроки английского в младшей школе, с безобразным коверканьем языка для воспроизведения тошнотворной английской фонетики. Зачем нас так мучали, если можно вполне прилично изъясняться как Люка без насилия над дикцией?
      &lt;/p&gt;

      &lt;p&gt;
      Отмечу катастрофически удобный вид майкрософтовских презентаций, на них совмещены сам докладчик, слайды и скринкаст. Хотелось бы, чтобы все организаторы конференций брали на вооружение такой подход.
      &lt;/p&gt;    
    &lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;
      &lt;p&gt;
&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://platforma2009.ru/materials/showitem.aspx?MID=77110d82-f458-4231-a6ba-441b0dac6478&quot;&gt;&lt;img src=&quot;http://i42.tinypic.com/wlyohz.jpg&quot; border=&quot;0&quot; alt=&quot;Image and video hosting by TinyPic&quot; align=&quot;right&quot; hspace=&quot;4px&quot;/&gt;&lt;/a&gt;
      По F# были доклады и на Платформе 2009. Правда, для скачивания надо залогиниться по Windows Live ID или Open ID. Если вам понравились какие-то презентации с этих или других конференций — давайте ссылки, желательно с небольшой аннотаций. (Всё ведь не пересмотришь, хотелось бы какое-то обоснование целесообразности траты времени.)
      &lt;/p&gt;    
    &lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;
X-posted from &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://bik-top.livejournal.com/31688.html&quot;&gt;http://bik-top.livejournal.com/31688.html&lt;/a&gt;
&lt;/p&gt;</description>
         <author>Qbit</author>
         <guid isPermaLink="false">urn:lj:livejournal.com:atom1:ru_fsharp:456</guid>
         <pubDate>Tue, 27 Jan 2009 02:27:08 +0000</pubDate>
      </item>
   </channel>
</rss>
<!-- fe4.yql.bf1.yahoo.com compressed/chunked Thu Oct  1 23:05:22 UTC 2015 -->
