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

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

Согласно Стивену Дилю, наряду с зависимыми типами, ускорением компиляции и уменьшением порогом вхождения; алгебраические эффекты являются одной из самых главных задач, которые будут решены в будущем для 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 быстрее питона (что оправдывает вторую часть заголовка).

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

Привет!

В этой статье мы попробуем взглянуть на архитектуру учетных систем (ERP, CRM, WMS, MES, B2B, ...) с позиций функционального программирования. Существующие системы сложны. Они базируются на реляционной схеме данных, и имеют огромный мутабельный стейт в виде сотен связаных таблиц. При этом единственным «источником правды» в таких системах является хронологически-упорядоченный журнал первичных документов (отпечатков событий реального мира), которые, очевидно, должны быть иммутабельными (и это правило соблюдается в аудируемых системах, где корректировки «задним числом» запрещены). Журнал документов составляет от силы 20% объема БД, а все остальное — промежуточные абстракции и агрегаты, с которыми удобно работать на языке SQL, но которые требуют постоянной синхронизации с документами, и между собой.

Если вернуться к истокам (устранить избыточность данных и отказаться от хранения агрегатов), а все бизнес-алгоритмы реализовать в виде функций, применяемых непосредственно к потоку первичных документов — мы получим функциональную СУБД, и построенную на ней функциональную ERP. Проблема производительности решается благодаря мемоизации, а объем функционального кода будет вполне соизмерим с объемом декларативного SQL, и не сложнее для понимания. В данной статье мы продемонстрируем подход, разработав простейшую файловую СУБД на языке TypeScript и рантайме Deno (аналог Node.js), а также протестируем производительность сверток на примере типичных бизнес-задач.

Почему это актуально

1) Мутабельный стейт + избыточность данных — это плохо, особенно когда необходимо обеспечивать его постоянную синхронизацию с потоком документов. Это источник потенциальных расхождений учетных данных (баланс не сходится) и трудно обнаруживаемых побочных эффектов.
Читать полностью »

Привет!

Начав изучение Scala, я сразу столкнулся с тем, что функциональная реализация простейшего алгоритма быстрой сортировки работает радикально медленней и потребляет существенно больше памяти, чем аналогичная императивная реализация. При этом никто не спорит, что функциональный код более краток, выразителен, и устойчив к ошибкам. Переписав оба примера на Rust, я обнаружил несколько важных вещей, которыми и хочу поделиться. Подробности под катом, а здесь приведу лишь краткие выводы:

  1. Для императивной реализации — выигрыш от Rust получился всего 20 %. Это означает, что JVM вплотную приблизилась к нативной производительности, и тут уже нечего улучшать.
  2. Для функциональной реализации — Rust оказался быстрее в 4.5 раза, потребление памяти снизилось в 5.5 раза, а отсутствие сборщика мусора сделало программу более стабильной (меньше разброс показателей). Это интересно для тех, кто хочет писать быстрые функциональные программы.
  3. Концепция единственного владельца данных (и единственной мутабельной ссылки), принятая в Rust, очень близка концепции иммутабельности, в результате чего функциональные алгоритмы, основанные на неизменяемости, рекурсии и копировании, легко ложатся на Rust практически без переписывания, тогда как императивные алгоритмы заставляют редизайнить код, учитывать мутабельность ссылок, времена жизни, и т.д.

Вывод — Rust как будто специально создан для ФП, хотя возможности его синтаксиса пока не дотягивают до Scala.
Читать полностью »

Еще одна статья про реактивное программирование. И только не надо на этой строчке закатывать глаза и томным голосом говорить вслух — "Ну что еще ты можешь мне рассказать про реактивное программирование… а?". Она немного отличается от кучи других, написаных словно под копирку, поэтому некоторые вещи в ней могут показаться… странными или даже совершенно неуместными, как сортирный юмор.

Совершенно не важно, знаешь ли ты наизусть reactive manifesto, присутствует ли в твоем утреннем кофе бекпрешур, трогаешь ли ты вот этими вот своими ручками всякие паблишеры и сабскрайберы или пишешь старый добрый синхронный, блокирующийся код. А может быть только недавно, кто-то своим откровенно рекламным докладом про светлое будущее и потоковый оргазм (ну или струйный, тут тонкости перевода решают все), от использования одной из реактивных библиотек конечно-же, зажег в твоих глазах интерес к новой технологии.

Будет интересно.

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

Функциональное программирование — это очень забавная парадигма. С одной стороны, про неё все знают, и все любят пользоваться всякими паттерн матчингами и лямбдами, с другой на чистом ФП языке обычно мало кто пишет. Поэтому понимание о том, что же это такое восходит больше к мифам и городским легендам, которые весьма далеко ушли от истины, а у людей складывается мнение, что "ФП подходит для всяких оторванных от жизни программок расчетов фракталов, а для настоящих задач есть зарекомендовавший себя в бою проверенный временем ООП".

Функциональное программирование — это не то, что нам рассказывают - 1

Хотя люди обычно признают удобства ФП фич, ведь намного приятнее писать:

int Factorial(int n)
{
    Log.Info($"Computing factorial of {n}");
    return Enumerable.Range(1, n).Aggregate((x, y) => x * y);
}

чем ужасные императивные программы вроде

int Factorial(int n)
{
    int result = 1;
    for (int i = 2; i <= n; i++)
    {
        result *= i;
    }
    return result;
}

Так ведь? С одной стороны да. А с другой именно вторая программа в отличие от первой является функциональной.

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

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

Всем привет!

Для тех, кто мечтает стать Senior Developer и готов присоединиться к крутой команде Scala-разработчиков, с 1 по 15 декабря 2019 года мы запускаем отбор на бесплатный курс по обучению Scala. По окончании обучения пятеро лучших стажеров смогут присоединиться к самой солнечной в мире команде.

image

Подробности — под катом.
Читать полностью »


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