|
|
iamjaph

| Дек. 26, 2011 10:37 am Ищется Дед Мороз со знанием Haskell Не принес мне Haskell под новый год подарок :-(
После успешного проекта под названием RedisSharding, решил я сделать второй также на Haskell, а не на Perl.
Задача: как можно быстрей загрузить и распарсить множество HTML страниц - Web Shpider.
Как раз задача для Haskell, поскольку у него самые легкие потоки, а задача легко параллелиться. ( Читать дальше... )
Наверно, придется взять Perl, Coro, и сделать просто и эффективно! Тем более, что Marc Lehmann этим летом пофиксил один нехороший момент в связке Coro и AnyEvent.
Или может подоспеет "помощь зала"? 16 комментариев - Оставить комментарий | |

| Июн. 29, 2011 10:03 am Почему Haskell Haskell - простой и мощный язык, позволяющий с легкостью описывать высокоуровневые абстракции.
Простота языка, ленивость и легковесные потоки позволяют без труда использовать data flow execution стиль.
А data flow execution стиль настолько удобен по сравнению с message passing cтилем, насколько последней удобен по сравнению с голым event-driving programming.
Яркие представители стилей: * data flow execution - Mozart-OZ * message passing - Erlang * event-driving programming - все, с нормальной лямбдой (без нее можно, но не совсем удобно). Оставить комментарий | |

| Июн. 1, 2011 11:08 am Как говориться, с почином Можете поздравить меня с почином. Даже с двойным. 1. Написал свое первое приложение на haskell. 2. Оно (приложение-сервер) уже 3 дня работает на боевых серверах.
P.S. Тьфу, тьфу, тьфу, чтобы не сглазить. 1 комментарий - Оставить комментарий | |

| Май. 13, 2011 12:00 pm Знакомство с Haskell на практике - развеивая мифы и заблуждения Немного о себе --------------
Никогда не думал, что стану программистом. Я химик по образованию. Но вот уже лет 11 как профессионально занимаюcь программированием на Perl (сайты НЕ делаю).
Мотивация ---------
Как-то подумалось, если я часто использую лишь функциональное подмножество языка языка Perl, то почему бы не взять для этих задач Haskell?
Аргумента "за":
- скорость программ; - легковесные потоки, масштабируемые на множество CPU; - автоматическая оптимизация хвостовой рекурсии (в Perl 5 делается руками, будет в Perl 6); - COW (будет в Perl 6); - автоматический карринг; - не нужно писать лишние закорючки при работе с функциями, как с сущностями высшего порядка; - тотальная ленивость.
Да, кстати, с выходом GHC 7 мы получили интеграцию легковесных потоков в kqueue и epoll.
Аргумент против один: страшные и ужасные загадочные монады. Пытался читать о них 3 года назад. Какие-то космонавтики в скафандриках. Корзинки и ящички с яблоками и ягодами. Мир, разделенный на два части: чистых и не-чистых. Ничего не понял.
Не так страшен черт, как его малюют -----------------------------------
После очередной неудачной попытки разобраться с монадами, почему они так нужны для IO в Haskell, плюнул на все это.
А в голове крутилась одна мысль. Я начал использовать ленивость на Perl этак лет 8-9 назад (тогда я не знал о Haskell). Почему у меня не возникало проблем с IO? Ведь порядок общения с внешним миром легко определятся при помощи продолжений!
Стал сам разрабатывать простой ленивый язык и компилятор для него. Да что там разрабатывал - просто все, что делал на Perl вручную, делегировалась компилятору. На удивление система получалась простая.
Почему же в Haskell все так сложно?! Спасибо умные люди подкинули ссылки на пару статей, среди них "Call-by-need and Continuation-passing Style". После прочтения которых в голове все прояснилось. В Haskell тоже все просто! Читать надо первоисточники, а не перепевы.
Проверка в реальном деле ------------------------
Есть у меня мультиплексирующий прокси-сервер "Redis Sharding" (http://github.com/kni/redis-sharding). Написан он на Perl, с использованием замыканий. Попробую я переписать его на Haskell.
Этот код состоит из двух частей. Одна часть занимается управлением сокетами, приемом и отправкой данных. Вторая часть - это анализ и преобразование данных. Это части достаточно не зависимы и связаны между собой колбеками, вызовы которых приводят к изменению данных в замыканиях.
Сначала взялся как обычно за самую трудную часть: управление соединениями и потоками данных.
Код на Haskell показал производительность выше в 2 раза, но вот объем кода в строках был в 1.5 раза больше, а в словах в 2 раза. Что для мене не приемлемо. Да и выглядело это вся ужасно.
После чего решил вместо изменяемых замыканий использовать легковесных потоки. Сделал такой себе маленьких Erlang на Haskell (слава Богу подобных опыт на Perl был). Клод стал чище, а количество срок стало таким как у Perl варианта, но не слов. Но если управление дочерними потоками вынести в отдельную библиотеку, а я ведь буду часто его использовать, то объем кода можно считать одинаковым (в словах 7% не в пользу Haskell). Да, код стал чище, но появилось много потоков, я чтобы не запутаться пришлось даже написать описание взаимодействия между ними. Кстати скорость выполнения немного повысилась, так как библиотека для работы с сокетами заточена под многопоточность, что приводили в мультиплексирующем варианта к дублированию проверок на возможность читать-писать.
Теперь возьмемся за вторую часть: анализ и преобразование данных.
Мы работаем с непрерывным потоком данных, разбитым на логически завершенные куски (команды и ответы). Поэтому, когда в распоряжении парсера нет всего необходимого объема данных для анализа текущего фрагмента, он в случае изменяемых замыканий сохраняет свое состоянии и ждет следующего своего вызова с порцией новых данных. В случай легковесных потоков, парсер засыпает на ожидании приема сообщения с новой порцией данных. Да второй вариант кажется проще, но это если не делать защиту от перегрузки данными в случае медленного чтения с сокетов на другой стороне. Надо контролировать размеры очередей с сообщениями. Не нравиться вся это. Но это пустяки по сравнением с тем, что в парсеры с новой порцией данных проникает IO.
И вот тут на помощь приходит ленивость и Network.Socket.ByteString.Lazy. Теперь парсер работает с данными, так как будто они уже все есть в наличие. Размер фрагмента второй части стал до безобразия маленьким. Даже не удобно сравнивать с энергичными языками. Разве что можно сравнивать с Mozart-OZ, в котором используется data-flow execution, но в нет пока нет поддержки ByteString.Lazy и kqueue/epoll. Благодаря этой части удалось догнать Perl вариант по выразительности и краткости кода.
Вывод -----
Если использовать ленивый язык, то использовать ленивость по полной!
Не надо использовать изменяемые замыканий, когда есть легковесный потоки.
Не надо использовать напрямую System.Event - ведь есть легковесный потоки.
При соблюдении этих условий, на Haskell можно достигнуть выразительности и краткости кода не уступающей Perl.
Развеивая мифы и заблуждения ----------------------------
О Haskell существует множество мифов, о нем рассказывают множество небылиц. Попробуем разобраться где истина, а где заблуждения.
1. Необходимость ученой степени в области Computer science. Это не правда. Достаточно просто ученой степени. :-)
2. Сложность. Это тоже не правда. Haskell - простой и красивый язык. На столько простой, что на нем очень легко и удобно создавать высокоуровневые абстракции, простые и сложные. Последние, разумеется, затуманивают разум новичков и вводят в заблуждения о простоте и сложности самого языка.
3. Ужас монад... Даже и не хочется касаться этой темы. Скажу только одно: не читайте всякую фигню, читайте первоисточники.
Влияние же остальных мифов не так пагубно для присматривающихся к Haskell, поэтому их рассматривать не буду.
Какова же причина появления этих мифов и заблуждений? На ум приходит только одно: Haskell настолько прост, что многим трудно это осознать. Оставить комментарий | |

| Фев. 18, 2011 04:04 pm Расправил крылья Расправил крылья. Около месяца понадобилось, чтобы разобраться с Haskell. Львиная часть этого времени пошла чтобы расставаться с заблуждениями, полученными ранее от эпизодического чтения всякой фигни про монады.
Как это удалось сделать? Во первых, заставил себя забыть о Haskell и монадах. Во вторых, представил реализацию ленивого языка и способы задания порядка обмена информацией с внешним миром.
Когда вспомнил вновь о Haskell - первая мысль была: "зачем же в Haskell это сделано так сложно"? Спасибо http://nponeccop.livejournal.com за ссылки на первоисточники, которые помогли понять, что не так то и сложно это сделано, как кажется при чтении руководств, пытающихся объяснить все по простому.
Замечание. Ленивость может быть реализована при помощи санок или продолжение. В Haskell используются санки. Санки - это функция, которая возвращается вместо результата ленивой функции. Оставить комментарий | |

| Янв. 12, 2011 09:36 am Redis Sharding Redis Sharding is a multiplexed proxy-server, designed to work with the database divided to several servers. It's a temporary substitution of Redis Cluster (http://redis.io) that is under development.
https://github.com/kni/redis-sharding Оставить комментарий | |

| Дек. 3, 2010 08:06 am О чистоте и лени После N-ной провальной попытки изучить Haskell и понять суть религии под названием "монадический фетишизм", решил изобрести свой "велосипед", то есть чистый и ленивый язык программирования.
Для любой открытой системы важным моментов является взаимодействие с внешним миром. В данном случаем - порядок обмена информацией.
У энергичных языков порядок определяется непосредственно самой последовательностью инструкций в программе. Напротив, для ленивых языков последовательность выполнения инструкций неопределена, а значения вычисляются по мере необходимости. Поэтому для осуществления взаимодействия с внешним миром в ленивые языки порядок вводиться искусственно.
Одним из способов упорядочивания вычислений является ввод дополнительных переменных-маркеров, при помощи которых указываются дополнительные зависимости между подпрограммами. Например, подпрограмма "C" зависит от переменной "b", которая определяется в подпрограмме "B", в свою очередь подпрограмма "B" зависит от переменной "a", значение которой определяется в подпрограмме "A", что приводит к выполнению сначала подпрограммы "A", затем "B" и лишь затем "C". Эти переменные маркеры в Mozart-OZ получили название свободные (unbound) переменные, а в Clean - уникальные типы.
Другим способом упорядочивание вычислений является использование стиля передачи продолжений. Однако этот стиль труден для использования им требует модификации подпрограмм. К счастью последнего можно избежать при помощи подпрограммы-обертки. В Haskell этой оберткой является оператор bind, а монады по сути не что иное, как своеобразный "концептуальный сахар" над стилем передачи продолжений. В свою очередь Haskell оператор do является "синтаксическим сахаром" вокруг монад, создающих иллюзию того, что переменные меняют свое значение.
Так что на самом деле Haskell, как и Clean, - абсолютно чистый язык, а религия "монадический фетишизм" - удел тех, кто на видеть разницы между иллюзией и реальностью.
P.S. Во загнул! С другой стороны, что взять с простого физ-химика, волей случая написавшего несколько маленьких программ на Perl. 54 комментария - Оставить комментарий | |

| Ноя. 24, 2010 12:40 pm IPC::MPS Обновил модуль perl IPC::MPS, в котором содержится реализация межпроцессного взаимодействия посредством передачи сообщений. Краткое описание на русском находиться здесь. Оставить комментарий | |


| Май. 22, 2006 09:46 am День святого Николай Пришел на работу и там мне сообщили, что сегодня оказывается день святого Николай. А я, Николай, и не знал! А общем с праздником меня и всех других Николаев! :-) Николай. Оставить комментарий | |

|
|