Все потоки
Поиск
Написать публикацию
Обновить
14.29

Функциональное программирование *

От Lisp до Haskell

Сначала показывать
Порог рейтинга
Уровень сложности

Современный код для выполнения HTTP запросов в Swift 5 с помощью Combine и применение их в SwiftUI. Часть 2. Hacker News

Время на прочтение15 мин
Количество просмотров6.6K


Hacker News, чей API мы собираемся использовать в этой статье, является социальным сайтом, сфокусированным на компьютерах и предпринимательстве. Если вы с ним ещё не знакомы, вы найдёте там много интересного.



В предыдущих статьях  на примере базы данных фильмов TMDb и агрегатора новостей NewsAPI.org была представлена стратегия применения Combine для формирования HTTP запросов и использования их во View Model для управления UI, спроектированного с помощью SwiftUI. В этой статье мы в точности воспроизведем ту же самую стратегию для разработки приложения, взаимодействующего с агрегатором новостей Hacker News, но добавим работу с «внешним» издателем Timer и для простоты исключим обработку ошибок.

Надо сказать, что выборка статей на ресурсе Hacker News имеет совершенно другую логику, чем в новостном агрегаторе NewsAPI.org, но технология, основанная на выполнении HTTP запросов с помощью Combine, прекрасно показывает свою гибкость и в этой ситуации. Кроме того, информация на сайте Hacker News очень часто обновляется и использование внешнего «издателя» Timer позволит автоматически отслеживать поступающие на сайт новые истории (Story), именно так их называют на этом ресурсе.

API агрегатора новостей Hacker News можно использовать совершенно свободно и не требуется никакой регистрации для аккаунта разработчика. Это здорово, потому что вы можете сразу начать работать над кодом без длительной регистрации, как мы делали это с другими public APIs.
Читать дальше →

Как разобраться новичку, какой язык выбрать для желаемой профессии?

Время на прочтение4 мин
Количество просмотров5.3K
Дисклеймер: данный текст не рекомендован к прочтению детям до 13 лет (для них нужно устанавливать отдельную политику конфиденциальности), сеньорам, мидлам, людям со слабой психикой, любителям VBA и языка АЛГОЛ, а также беременным женщинам. Все изложенное является личным мнением неадекватного автора и не изложено здесь с целью посеять рознь среди адептов статической и динамической типизации. Поехали: new Thread().start()


Читать дальше →

Монады как паттерн переиспользования кода

Время на прочтение24 мин
Количество просмотров76K


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


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


Но ведь в интернете буквально сотни статей про ФП и монады, зачем писать еще одну?


Дело в том, что все их (по крайней мере те что я читал) можно поделить условно на две категории: с одной стороны это статьи где вам объяснят что монада это моноид в категории эндофункторов, и что если монада T над неким топосом имеет правый сопряжённый, то категория T-алгебр над этой монадой — топос. На другой стороне располагаются статьи, где вам рассказывают, что монады — это коробки, в которых живут собачки, кошечки, и вот они из одних коробок перепрыгивают в другие, размножаются, исчезают… В итоге за горой аналогий понять что-то содержательное решительно невозможно.


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


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

Читать дальше →

Функциональный подход к транзакциям на Scala или пишем свою полезную монаду

Время на прочтение8 мин
Количество просмотров4.5K

Если вы работаете с одной базой данных которая поддерживает транзакции вы даже не задумываетесь о консистентности — база все делает за вас. Если же у вас несколько баз, распределенная система или даже к примеру MongoDB до 4 версии — все не так радужно.


Рассмотрим пример — мы хотим сохранить файл в хранилище и добавить ссылку на него в два документа. Конечно же мы хотим атомарности — либо файл сохранен и добавлен в документы либо ни то ни другое (тут и далее используется cats-effects IO):


saveDataToFile(data) // (1)
  .flatMap { file =>
    addFileRef(documentId, file) // (2)
      .flatMap { result =>
        addFileRef(fileRegistry, file) // (3)
          .flatMap { result =>
            ??? // (4, 5, ...)
          }
          .handleErrorWith { error =>
            // revert (2)
            removeFileRef(documentId, file).attempt >> IO.raiseError(error)
          }
      }
      .handleErrorWith { error =>
        // revert (1)
        removeFile(file).attempt >> IO.raiseError(error)
      }
  }

Уже непросто? Легко представить как количество операций растет и образуется Pyramid of doom.


Но мы же программисты! Давайте обобщим проблему и напишем код, который позволит избежать ненужной сложности и возможных ошибок.

Читать дальше →

wc на D: 712 символов без единого ветвления

Время на прочтение7 мин
Количество просмотров6K
После прочтения "Побиваем С программой в 80 строк на Хаскеле", которую я нашел на ХакерНьюс, я решил, что D может и лучше. И я написал wc на D.

Прим.пер. Я предложил вышеупомянутую статью перевести 0xd34df00d, но он предпочел сделать по мотивам свою «Побеждая C двадцатью строками Haskell: пишем свой wc». И теперь статьи множатся как перепевы «чеканной монетой».

Программа


Состоит из одного файла — 34 строки и 712 символов.

Исходник
import std.stdio : writefln, File;
import std.algorithm : map, fold, splitter;
import std.range : walkLength;
import std.typecons : Yes;
import std.uni : byCodePoint;

struct Line {
	size_t chars;
	size_t words;
}

struct Output {
	size_t lines;
	size_t words;
	size_t chars;
}

Output combine(Output a, Line b) pure nothrow {
	return Output(a.lines + 1, a.words + b.words, a.chars + b.chars);
}

Line toLine(char[] l) pure {
	return Line(l.byCodePoint.walkLength, l.splitter.walkLength);
}

void main(string[] args) {
	auto f = File(args[1]);
	Output o = f
		.byLine(Yes.keepTerminator)
		.map!(l => toLine(l))
		.fold!(combine)(Output(0, 0, 0));

	writefln!"%u %u %u %s"(o.lines, o.words, o.chars, args[1]);
}

Читать дальше →

Современный код для выполнения HTTP запросов в Swift 5 с помощью Combine и применение их в SwiftUI. Часть 1

Время на прочтение27 мин
Количество просмотров21K


Выполнение HTTP запросов — это один из самых важных навыков, которые необходимо получить при разработке iOS приложений. В более ранних версиях Swift (до версии 5) вне зависимости от того, формировали ли вы эти запросы «с нуля» или с использование известного фреймворка Alamofire,  вы в конечном итоге получали сложный и запутанный код с callback типа completionHandler: @escaping(Result<T, APIError>) -> Void.

Появление в Swift 5 нового фреймворка функционального реактивного программирования Combine в сочетании с уже существующими URLSession и Codable предоставляет вам все необходимые инструменты для самостоятельного написания очень компактного кода для выборки данных из интернета.

В этой статье в соответствии с концепцией Combine мы будем создавать «издателей» Publisher для выборки данных из интернета, на которые в дальнейшем сможем легко «подписаться» и использовать при проектировании UI как с помощью UIKit, так и с помощью SwiftUI.

В SwiftUI это выглядит более лаконично и более эффектно, так как действие «издателей» Publisher не ограничивается просто выборкой данных, а простирается дальше, вплоть до управления пользовательским интерфейсом (UI). Дело в том, что в SwiftUI разделение данных и View осуществляется с помощью ObservableObject классов с @Published свойствами, изменения которых SwiftUI АВТОМАТИЧЕСКИ отслеживает и полностью «перерисовывает» свои View.

В эти ObservableObject классы можно очень просто заложить определенную бизнес-логику приложения, если некоторые из этих @Published свойств являются результатом синхронных и/ или асинхронных преобразований других @Published  свойств, которые можно напрямую менять такими «активными» элементами пользовательского интерфейса (UI) как текстовые поля TextField, Picker, Stepper, Toggle и т.д.
Читать дальше →

Примерно 20 строк, примерно такие же результаты: wc на Elixir

Время на прочтение6 мин
Количество просмотров7.9K

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


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

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


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

Пройдем след в след на Эликсире

GSoC 2019: Проверка графов на двудольность и трансформеры монад

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

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

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


Читать дальше →

Пытаясь композировать некомпозируемое: поднимаем всё

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

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

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

На пути к функциональной СУБД и NoSQL ERP: хранение остатков и расчет себестоимости

Время на прочтение10 мин
Количество просмотров4.8K
Привет, Хабр!

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

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

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

Время на прочтение15 мин
Количество просмотров16K


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


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

Читать дальше →

Функциональный Powershell с классами — не оксюморон, я гарантирую это

Время на прочтение6 мин
Количество просмотров6.5K

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


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


Магия кастов


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

Читать дальше →

Управление состоянием приложения с RxJS/Immer как простая альтернатива Redux/MobX

Время на прочтение6 мин
Количество просмотров6K
"Вы поймете, когда вам нужен Flux. Если вы не уверены, что вам это нужно, вам это не нужно." Пит Хант


Для управления состоянием приложения я как правило применяю Redux. Но не всегда есть необходимость в использовании модели Action\Reducer, хотя бы из-за трудозатратности ее применения для написания простейшего функционала. Возьмем в качестве примера обычный счетчик. На выходе хотелось получить простое и практичное решение, которое позволит описать модель состояния и пару методов его меняющие, наподобие такого:


state = {value: 0} 
increase() { 
  state.value += 1 
} 
decrease() {
  state.value -= 1
}

Сходу кажется, что такое решение может обеспечить MobX, так почему бы им и не воспользоваться? Поработав с MobX некоторое время, для себя пришел к выводу, что лично мне проще оперировать последовательностью иммутабельных состояний (наподобие Redux), чем логикой мутабельного состояния (наподобие MobX), да и его внутреннюю кухню я бы не назвал простой.


В общем, захотелось найти простое решение для управления состоянием, в основе которого лежала бы иммутабельность, с возможностью применять его в Angular\React и реализованное на TypeScript. Беглый обзор на просторах github подходящего решения не выдал, поэтому возьмем RxJS/Immer и попробуем сделать свое.

Читать дальше →

Ближайшие события

Применение принципов функционального программирования при проектировании ERP

Время на прочтение13 мин
Количество просмотров12K
Привет, Хабр!

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

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

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


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

Почему Rust должен стать функциональным языком программирования

Время на прочтение5 мин
Количество просмотров15K
Привет, Хабр!

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

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

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

Функциональное программирование с точки зрения EcmaScript. Рекурсия и её виды

Время на прочтение4 мин
Количество просмотров12K
Привет, Хабр!

Сегодня мы продолжим наши изыскания на тему функционального программирования в разрезе EcmaScript, на спецификации которого основан JavaScript. В предыдущих статьях цикла были рассмотрены следующие темы:

  1. Чистые функции, лямбды, имутабельность
  2. Композиция, каррирование, частичное применение
Читать дальше →

Ненормальное реактивное программирование

Время на прочтение9 мин
Количество просмотров9.8K

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


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


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

Читать дальше →

Эксперимент VonmoTrade. Часть 1: Биржи и современные технологии

Время на прочтение4 мин
Количество просмотров3K

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


Цели эксперимента:


  • Более глубокое понимание предметной области и улучшение технической экспертизы
  • Выявление сильных и слабых сторон использования функциональных языков и проектов с открытым исходным кодом при разработке торговых систем
    В этой статье представлена мотивационная часть проекта и декомпозиция задачи.
Читать дальше →

Еще один DSL для валидаций

Время на прочтение5 мин
Количество просмотров1.8K

Недавно я написал небольшой гем для валидаций и хотел бы поделиться с вами его реализацией.


Идеи, которые преследовались при создании библиотеки:


  • Простота
  • Отсутствие магии
  • Легкость в освоении
  • Возможность кастомизации и минимум ограничений.

Почти все эти пункты завязаны на первом — простоте. Итоговая реализация невероятно маленькая, поэтому я не отниму у вас много времени.


С исходным кодом можно ознакомиться здесь.

Читать дальше →

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

Время на прочтение17 мин
Количество просмотров129K

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



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


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;
}

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


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

Читать дальше →