Монада является моноидом, если заменить декартово произведение множеств
композицией функторов (монада является функтором), умножение — функцией join,
а единицу — pure. Законы моноида при этом выполняются.
Mac Lane S. Categories for the Working Mathematician. — Springer, 1998:
A monad T = < T, η, μ > in a category X consists of a functor T: X → X and two natural transformations η: I_X → T, μ: T^2 → T, which make the following diagrams commute <…>*.
Formally, the definition of a monad is like that of a monoid M in sets <…>. The set M of elements of the monoid is replaced by the endofunctor T: X → X, while the cartesian product ⨯ of two sets is replaced by composite of two functors, the binary operation μ: M ⨯ M → M of multiplication by the transformation μ: T^2 → T and the unit (identity) element η: 1 → M by η: I_X → T. We shall thus call η the unit and μ the multiplication of the monad T; the first commutative diagram <…> is then the associative law for the monad, while the second and third diagrams express the left and right unit laws, respectively. All told, a monad in X is just a monoid in the category of endofunctors of X, with product ⨯ replaced by composition of endofunctors and unit set by the identity endofunctor.
* Диаграммы, на которые ссылается текст, описывают известные законы монад.
Свяжем это с монадами в Haskell. T — это Monad m ⇒ m a, η — это pure ::
Monad m ⇒ a → m a, а μ — join :: Monad m ⇒ m (m a) → m a.
Напомню, что эта категория называется Hask. В ней объектами являются типы
Haskell, а морфизмами — функции. Композиция морфизмов — это (.), единичный
морфизм — id.
Функторы Haskell Functor являются функторами из Hask в подкатегорию
Hask, состоящую из типов, образованных приписыванием конструктора. То есть
типу a ставится в соответствие тип m a, а функции a → b — функция m a → m
b.
f x = x. I don’t do very much but at least I’m unique."James Chapman (via annayudi)
Есть известные правила программирования в Unix. Мы решили обратить внимание на схожие правила, помогающие создавать краткий программный код:
Я выступлю с докладом об использовании внешних языков DSL и моей библиотеке funcparserlib на DevConf в секции Python. Конференция пройдёт в Москве 2010-05-17.
Перед конференцией организаторы взяли у меня небольшое интервью. В нём я упоминаю мои текущие проекты, рассказываю о теме предстоящего доклада.
Сейчас многие интересуются языками, поддерживающими несколько взаимодействующих потоков управления (Erlang, Clojure, Go). В них зелёные нити используются, в основном, для организации многозадачности (concurrency). В качестве моделей многозадачности используются CSP или Actor model. То есть программа строится из объектов-акторов, имеющих свою зелёную нить и обменивающихся сообщениями (синхронно или асинхронно).
Конечно хорошо, когда объекты перестают быть просто процедурами, связанными одной нитью и одним стеком вызовов. Это полезно, например, для серверов с множеством объектов-соединений и общими ресурсами. Однако подобное многозадачное ООП — не единственный способ занять процессоры. К тому же существуют и другие задачи.
Многие задачи по своей природе не объектные, а функциональные. Для них модели типа CSP или Actor model — не более, чем возможный способ ускорения обработки. Вместо многозадачности (concurrency) здесь на первый план выступает параллельность (parallel programming). Достаточно большое число реальных задач хорошо ложится именно в этот класс. В предметной области таких задач нет ни слова про объекты и сообщения, но есть чисто техническая (ладно, математическая) возможность произвести часть вычислений параллельно.
Средства параллельности можно реализовывать поверх средств многозадачности, но можно и иметь их встроенными в язык, хотя бы в виде библиотек. Иначе получается, что для решения функциональной задачи приходится писать объектно-ориентированный код.
Некоторые известные типы параллельной обработки:
В Unix приветствуется создание небольших взаимодействующих программ, каждая из которых решает одну задачу. В частности, именно за счёт процессов ОС решаются проблемы параллелизации и многозадачности. Поэтому важно, чтобы программа стартовала быстро и не выполняла того, о чём её не просит программист.
Недавно я заинтересовался языком Clojure, который исповедует монолитный подход к параллельности. Я решил провести небольшое сравнение скорости выполнения крошечных программ “Hello World” на разных языках. Вот результаты сравнения:
Недавно натолкнулся на пост Actor Thinking об использовании акторов в стиле Erlang для «естественной» реализации параллельности. В посте поясняются уже знакомые слова Joe Armstrong об аналогии между акторами и объектами ООП.
Мне кажется, в этих рассуждениях в очередной раз допускается ошибка классического объектно-ориентированного подхода, будто почти все задачи естественно решать в стиле взаимодействующих объектов с локальным изменяемым состоянием. Наиболее ярко преимущества ООП выражаются как раз на системах без общей памяти, т. е. на взаимодействующих процессах. Тогда действительно люди при разработке думают об интерфейсах, инкапсуляции и пр.
При решении задач не нужно придумывать объекты. Сама задача уже говорит о том, какие есть объекты, если они вообще есть. Мелкие многочисленные объекты, как и мелкие параллельные процессы — это скорее недостаток, от которого следует избавляться, а не расхваливать.
Here you can find markdown vim syntax file made by Ben Williams. Put it to the ~/vim/syntax/ folder.
To add syntax...
“This image was taken on September 15, 2006 and received on Earth September 20, 2006. The camera was pointing toward Saturn at approximately 2M...
Well, it looks like GCC 4.3.2 does not comply to C99 specification. It clearly states that:
6.8.6.4.1 ... A...