Рубрика «функциональное программирование» - 6

Полгода назад Крис Пеннер опубликовал Beating C With 80 Lines Of Haskell: Wc. В предисловии говорится:

Задача состоит в том, чтобы построить более шустрый клон оптимизированной вручную реализации утилиты wc на C в нашем любимом высокоуровневом языке программирования со сборкой мусора — на Haskell! Звучит достаточно просто, не так ли?

Крис прошел весь путь от простой реализации при помощи ByteStrings, через моноиды, встроенные моноиды и, наконец, пришел к параллельной многоядерной версии вышеописанного, которой и удалось немного побить чистый C-код во время выполнения на четырех ядрах.

Несколько дней назад на Хабре была размещена еще одна заметка на ту же тему от 0xd34df00d Побеждая C двадцатью строками Haskell: пишем свой wc. Автор доказал возможность пользования идиоматического хаскеля и в 20 (двадцати) строках кода реализовал алгоритм, который почти в десять раз быстрее, чем идиоматическая реализация на C.

Читать полностью »

Привет.

На днях Siemargl предложил мне перевести любопытную статью о победе над юниксовым wc при помощи хаскеля. Переводить её я, конечно же, не буду, и по нескольким причинам:

  • автор выжал из однопоточной версии далеко не всё, и однопоточная версия была существенно медленнее wc,
  • в той статье для победы потребовалось воспользоваться многопоточностью (что само по себе немного читерство и победа скорее над здравым смыслом, а не над wc),
  • для этого автору пришлось углубляться в трихомонады и моноиды — не, это отличная иллюстрация прелестей моноидального мышления, но ИМХО немного перебор для такой задачи, тем более, что из-за этого
  • код получился излишне объёмным,
  • да и вообще, соревноваться с wc, которая имеет кучу опций и фич, реализуя её ну очень игрушечный аналог, вообще как-то странно и даже немного глуповато.

Тем не менее, заниматься странными делами — дело хорошее, поэтому сегодня мы попробуем исправить первый из пунктов выше и улучшим результат Криса (так звать автора исходной статьи).

Опять же, как мы выяснили в прошлый раз, код на C я писать не умею, так что писать его и не буду, а в качестве конкурента хаскель-реализации у меня (как и у Криса) выступает сишный wc из GNU Coreutils. Те чуваки уж точно на C писать умеют, коду этому не один десяток лет, да и о производительности они позаботились, судя по таким кусочкам:

/* If the average line length in the block is >= 15, then use
   memchr for the next block, where system specific optimizations
   may outweigh function call overhead.
   FIXME: This line length was determined in 2015, on both
   x86_64 and ppc64, but it's worth re-evaluating in future with
   newer compilers, CPUs, or memchr() implementations etc.  */

Спойлер: мы обгоним сишный wc примерно на порядок без всяких проблем, получив вполне идиоматичный код и потратив менее получаса на изменения и оптимизацию оригинального кода.

Читать полностью »

В декабре Scala-комьюнити опубликовало пресс-релиз о том, что Scala 2.14 никогда не выйдет. Мартин Одерски и Ко приняли решение, что необходимо сконцентрироваться на работе над Dotty/Scala3.

Сообщество Scala программистов (в моем лице в том числе) безмерно этому радо, т.к., честно говоря, давно пора было. Scala застыло в прорывном развитии на несколько лет, что на фоне стремительного роста популярности better-java-kotlin приводило к оттоку разработчиков и даже целых компаний.

Scala3 должна стать тем самым большим скачком вперед, который вернет интерес нынешним и будущим энтузиастам ФП на JVM.

Мы получим больше всего того, что мы так любим: еще больше типобезопасности и метапрограммирования на стероидахбазе полностью нового компилятора с инкрементальным режимом. Еще более краткий синтаксис.

Статус прогресса в списке вкусностей застыл в неизменном состоянии на долгое время, что должно измениться в ближайшее время, если команда Scala3 выполнит свое обещание, данное в пресс-релизе. Пока же они нам советуют рассчитывать на...Читать полностью »

Привет.

Прошло довольно много времени с публикации предыдущей статьи об обобщённой реализации паттерна Has, где мы успешно победили скуку и однообразный код при написании инстансов соответствующего класса, заодно поигравшись с дженериками и семействами типов одновременно, но давайте всё же добьём цикл и заодно лишний раз посмотрим, зачем программисту математика.

Итак, с обобщённой реализацией паттерна Has мы разобрались. Какой следующий интересный вопрос можно задать? Ну, например, можем ли мы обобщить наше решение, которое, к слову, является обобщением (Has Foo) обобщения (HasFoo) обобщения (MonadReader Foo) обобщения (Reader Foo) понятия параметра функции (Foo ->)? И, оказывается, что да, можем, и аж в двух ортогональных измерениях!

В частности, мы придумаем аж два паттерна имени нас, причём один из них — бесплатно, совершенно не включая мозг, а лишь основываясь на алгебре.

Читать полностью »

Прошлым летом я участвовал в Google Summer of Code — программе для студентов от компании Google. Ежегодно организаторы отбирают несколько Open Source-проектов, в том числе от таких известных организаций, как Boost.org и The Linux Foundation. Для работы над этими проектами Google приглашает студентов со всего мира. 

Как участник Google Summer of Code 2019 я делал проект в рамках библиотеки Alga с организацией Haskell.org, занимающейся развитием языка Хаскелль — одного из самых известных функциональных языков программирования. Alga — библиотека, представляющая типобезопасное представление для графов в Хаскелле. Она используется, например, в semantic — библиотеке компании Github, строящей по коду семантические деревья, графы вызовов и зависимостей и умеющей их сравнивать. Мой проект состоял в добавлении туда типобезопасного представления для двудольных графов и алгоритмов для этого представления. 

В посте я расскажу про свою реализацию алгоритма проверки графа на двудольность на Хаскелле. Несмотря на то, что алгоритм является одним из самых базовых, его красивая реализация в функциональном стиле заняла у меня несколько итераций и потребовала довольно много работы. В результате я остановился на реализации с трансформерами монад. 

GSoC 2019: Проверка графов на двудольность и трансформеры монад - 1
Читать полностью »

Рекомендуется прочитать первую статью, если вы еще этого не сделали. Эта статья будет покороче, меньше сконцентрирована на деталях и больше — на возможностях.

Согласно Стивену Дилю, наряду с зависимыми типами, ускорением компиляции и уменьшением порогом вхождения; алгебраические эффекты являются одной из самых главных задач, которые будут решены в будущем для Haskell.

Будущее не за горами, поэтому приступать нужно уже сейчас.
Читать полностью »

Привет!

Продолжаем исследовать применимость принципов функционального программирования при проектировании ERP. В предыдущей статье мы рассказали зачем это нужно, заложили основы архитектуры, и продемонстрировали построение простых сверток на примере оборотной ведомости. По сути, предлагается подход event sourcing, но за счет разделения БД на иммутабельную и мутабельную часть, мы получаем в одной системе комбинацию преимуществ map / reduce-хранилища и in-memory СУБД, что решает как проблему производительности, так и проблему масштабируемости. В этой статье я расскажу (и покажу прототип на TypeScript и рантайме Deno), как в такой системе хранить регистры мгновенных остатков и рассчитывать себестоимость. Для тех, кто не читал 1-ю статью — краткое резюме:

1. Журнал документов. ERP, построенная на базе РСУБД представляет собой огромный мутабельный стейт с конкурентным доступом, поэтому не масштабируется, слабо-аудируема, и ненадежна в эксплуатации (допускает рассогласование данных). В функциональной ERP все данные организованы в виде хронологически-упорядоченного журнала иммутабельных первичных документов, и в ней нет ничего кроме этих документов. Связи разрешаются от новых документов к старым по полному ID (и никогда наоборот), а все остальные данные (остатки, регистры, сопоставления) являются вычисляемыми свертками, то есть кэшируемыми результами работы чистых функций на потоке документов. Отсутствие стейта + аудируемость функций дает нам повышенную надежность (блокчейн на эту схему прекрасно ложится), а бонусом мы получаем упрощение схемы хранения + адаптивный кэш вместо жесткого (организованного на базе таблиц).
Читать полностью »

Зависимые типы в Haskell: почему это будущее разработки программного обеспечения - 1

В Serokell мы занимаемся не только коммерческими проектами, но стараемся изменить мир к лучшему. Например, работаем над улучшением главного инструмента всех хаскелистов – Glasgow Haskell Compiler (GHC). Мы сосредоточились на расширении системы типов под впечатлением от работы Ричарда Айзенберга "Зависимые типы в Haskell: теория и практика".

В нашем блоге Владислав уже рассказывал о том, почему в Haskell не хватает зависимых типов и как мы планируем их добавить. Мы решили перевести этот пост на русский, чтобы как можно больше разработчиков могло использовать зависимые типы и сделать дальнейший вклад в развитие Haskell как языка.

Читать полностью »

Привет! Представляю вашему вниманию перевод статьи "Functional PowerShell with Classes.
I promise it’s not an oxymoron"
автора Christopher Kuech.

Объектно-ориентированная и функциональная парадигмы программирования могут казаться не в ладах друг с другом, но обе в равной мере поддерживаются в Powershell. Практически все программные языки, функциональные и нет, имеют средства расширенного связывания имён и значений; Классы, подобно struct-ам и record-ам, это всего лишь один подход. Если мы ограничим использование Классов связыванием имён и значений и станем избегать таких "тяжёлых" объектно-ориентированных программных концепций, как наследование, полиморфизм, или изменяемость (mutability), мы сможем использовать их преимущества, не усложняя наш код. Далее, добавляя неизменяемые (immutable) методы преобразования типов, мы можем обогатить Классами наш функциональный код.

Магия кастов

Касты одна из самых мощных фич в Powershell. Когда вы подвергаете значение касту, вы полагаетесь на добавляемую средой в ваше приложение возможность неявных инициализации и валидации. Например, простой каст строки в [xml] прогонит её через код парсера и сгенерирует полное дерево xml. Мы можем в своём коде использовать Классы с той же целью.

Читать полностью »

Привет.

У меня тут случайно код на хаскеле получился быстрее аналогичного кода на C++. Иногда — на 40%.

Быстрее, чем C++; медленнее, чем PHP - 1
(время работы, меньше — лучше, C++ снизу)

Что самое смешное — я собирал хаскель-код через LLVM-бекенд, но при этом сравнивал с GCC. Если сравнивать с clang (что вроде как логичнее), то всё становится ещё хуже для плюсов: почему-то на этой задаче clang проигрывает GCC в пару раз, и разница становится не 40%, а этак раза три. Впрочем, одна маленькая модификация C++-кода это поменяет.

Началось всё с того, что для одного моего проекта (который, естественно, делается на хаскеле, и о котором я тоже скоро напишу) нужно было быстро и эффективно считать расстояние Левенштейна между двумя строками. Расстояние Левенштейна — это такая метрика, которая говорит, сколько символов нужно удалить, добавить или заменить в одной строке, чтобы она стала равна другой строке. Я считал расстояния между довольно большими строками (масштаба десятков тысяч символов), поэтому эффективность была действительно важна.

А потом мне стало интересно, насколько быстро я вообще могу это расстояние считать (потратив разумное время на оптимизацию, конечно), так что я набросал вариант на С++ и взял его время работы за этакий идеал, к которому стоит стремиться. Впрочем, как уже понятно, идеал оказался превзойдён.

Посмотрим, как этого можно достичь?

Быстрее, чем C++; медленнее, чем PHP - 2

В качестве бонуса — сравнение с некоторыми другими языками. Спойлеры:

  • Nim медленнее компилятора C двадцатилетней давности.
  • C# в пять раз медленнее Java, которая оказывается вполне на уровне Rust.
  • Go вровень с C.
  • PHP быстрее питона (что оправдывает вторую часть заголовка).

Читать полностью »


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js