Как стать автором
Обновить

Комментарии 62

НЛО прилетело и опубликовало эту надпись здесь
>F# победил с большим отрывом от всех.
а можно краткое пояснение причин? Чем он лучше haskell, scala? Вы пишите на F# промышленный код? Интересно узнать именно с точки зрения готовности для прода.
Интересный язык Haskell, на этом сайте есть десятки статей, в которых обьясняется почему это самый лучший язык программирования и почему фенкциональное программирование лучше чем ооп, но нет ни одной статьи в которой бы разбиралось создание хоть чего то что используется в реальном мире.

Я когда-то писала небольшой туториал по парсерам (https://habr.com/ru/post/436234/), вполне себе прикладная задача. Да и по запросу "haskell туториал" тут находятся посты. Но русскоязычных материалов в целом мало, это факт.

Есть все-таки. Когда-то (в 2011?) я описывал, как применял Хаскель для обработки телефонного трафика. Были еще и другие статьи про опыт использования его в проде. Конечно же, полно и других статей разного толка.

Но на Хабр уже почти нет смысла писать. Я, например, пишу сразу на английском, потому что основная аудитория там. Я даже книгу написал про «building real world applications in Haskell»: Functional Design and Architecture. Причем подходы из книги я применил на практике аж несколько раз и с большим успехом. Так что мы про все это пишем, просто не на Хабр.
Большое спасибо за книгу! Приобрел себе на leanpub больше полугода назад. Всячески рекомендую книгу по архитектуре — т.к. содержит конкретные и емкие примеры без лишнего словоблудия.
Мне разве что местами не хватало последовательных шагов. В целом превосходная книга и своих денег стоит. Стоит поддержать автора рублем.

Скажу честно дал паре человек почитать и они потом купили свои экземпляры книги.
Здорово! Спасибо за добрые слова!

Давать друзьям — это нормально, я не против. Я вам больше скажу, она и на торрентах уже тоже есть, и я не собираюсь как-либо это ограничивать. На книгах все равно не заработать, так что пусть люди читают хотя бы так.
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
>Статьей о том, как ФП поможет мне заработать на BMW 7 серии я не видел еще ни одной.
Есть классическая статья Пола, о том как они создали viaweb, которая потом была продана Yahoo за что-то типа $50 миллионов. Вся эта статья просто пропитана духом того, как именно Lisp позволил им этого добиться. Старая статья, очень старая…

Сколько там BMW 7 серии можно было купить за $50 миллионов, не подскажете?
НЛО прилетело и опубликовало эту надпись здесь
>сошлось очень много звезд, в том числе ФП, и теперь он миллионер
Э, ну как только покажете аналог на ООП — так сразу и сравним. А по-моему так программированием вообще очень редко зарабатывают достаточно большие деньги. И еще это обычно бывает не потому, что вы очень хорошо кодируете, или там ФП применили, а скорее потому, что попали в ожидания пользователей. А иначе компании типа ФБ с их откровенным говнокодом вообще бы все разорялись.
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь

По 33 000 за штуку? Таких цен уже 20 лет как нет

НЛО прилетело и опубликовало эту надпись здесь
No offence, просто в статье про «сильные стороны» неплохо было бы перечислить и слабые. Топ-3, на мой взгляд:
1. Тезис Чёрча является доказанно-недоказуемым. Т.е. нам предлагается поверить, что произвольную ФП-программу в принципе можно скомпилировать в нечто более-менее выполняющееся на реальном железе. Дать оценку времени выполнения ФП-программы хотя бы в О-нотации в общем случае нельзя.
2. На практике, в мейнстримные языки действительно завезли элементы ФП, только вот банальный немодный явный цикл for выполняется в разы и на порядки быстрее, чем аналогичный map-reduce. Возможно, это недоработка компиляторов, но что есть то есть.
3. Лямбда-исчисление (все эти ваши монады с каррингом) требует нетривиальной математической подготовки, которой у обычных инженеров, как правило, нет. И, в отличие от конечных автоматов или там реляционной алгебры, «просто почитать книжку» не получится. А без этого код на ФП предвращается в шаманство и магию (ну, примерно как паттерны проектирования:). Это значит, что хороших ФП-программистов тупо мало (ну, в разы меньше, чем хороших «императивщиков»). А это приговор с точки зрения бизнеса.
НЛО прилетело и опубликовало эту надпись здесь
А то, что машин Тьюринга на практике не существует и не может существовать, вас не смущает?

Нет, не смущает, потому что единственное невыполнимое ограничение — бесконечная память. Сейчас у каждого в кармане ~1012 этой самой памяти, не бесконечность, но достаточно близко. Самое главное, что мы знаем, какие алгоритмы относятся к неполиномиальным (коммивояжер, SAT — печально, но некритично), а всё остальное без проблем реализуется.
Какой язык? Какой компилятор?

Да любой из мейнстримных, от плюсов до js. Для функционального кода они сегодня в лучшем случае умеют хвостовую рекурсию (но это неточно), тогда как для императивного фигачат векторные инструкции только в путь.
Блин, а у меня получилось. ЧЯДНТ?

Мы это года три как поняли, предлагаю не переходить на личности). Списки вакансий по языкам вполне однозначны.
НЛО прилетело и опубликовало эту надпись здесь
Первая ссылка в гугле, тыц: habr.com/ru/post/516034
брать языки, не заточенные под задачу

Языки сегодня берут не под задачу, а под команду.
И да, именно из-за незаточенности я написал дисклеймер:
Возможно, это недоработка компиляторов, но что есть то есть

Ну, к примеру, Rust (пусть он далеко не функциональный) может оптимизировать и ераторы, все эти map и reduce до уровня zero-cost abstraction, не такая в производитеьбности (не всегда). Был где-то хороший пример с обработкой звука, но сейчас не смог найти.

ФП может и вправду так хорошо, но…
Мне пока хватило видео Соера «Как функциональное программирование портит программистов на JavaScript», хоть и не JS-программист, но понимаю о чём он говорит.
НЛО прилетело и опубликовало эту надпись здесь

Видео не смотрел, но JS не очень-то ООП-ный язык. Я бы сказал он к функциональщине ближе.

Тем что нет тех же железобетонных правил и ограничений «чистых ФП-языков», когда шаг вправо-влево, расстрел компилятором на месте.
И соответственно разработчик волен либо сам костылить монады/каррирование и прочее, либо брать библиотеку и полагаться на «стороннее видение»*. А потом приходит js-джуниор и «пишет как умеет».

И по итогу у большинства там будет не «надежное ФП», а «функциональный цирк».

*тут из личного опыта могу вспомнить милые попытки скрестить lodash с TypeScript и «радости» от того что какой-нибудь compose с огромным удовольствием терял типы где-то внутри себя, порождая на выходе any.
Я могу понять как какая-то Джава работает в энтерпрайзе: всевозможные варианты «провалидировать форму, положить в базу» настолько там проработаны, все шишки сообществом уже набиты и искать что-то другое для решения задачи смысла нет.

Из ФП я вижу как Эрланг работает для телефонии и всего, где надо обмениваться сообщениями — действительно очень практичный язык под конкретную проблему. Когда есть свободное время, стараюсь чуть-чуть читать из учебника, просто для расширения кругозора.

С Хаскеллем у меня ощущение, что это «от идеалистов и для идеалистов». Все статьи о том, как на Хаскелле удобно работать, демонстрируют решение каких то абстрактных задач в вакууме. Из моего опыта с Хаскеллем — я пытался написать raytracing на этом ЯП, убил вечер, и даже запустил. Но когда я попытался ускорить то узнал что либа, которую я взял для рендеринга изображений, не поддерживает параллелизацию — так что весь смысл чистоты ФП оказался спущенным в мусорку самими разработчиками либы (которая всплывает в верхних результатах выдачи гугла). А переписать под другую либу оказалось сложно, потому что, внезапно, ей требуются совершенно другие данные, в другом формате, и весь процесс рендеринга у неё выглядит по-другому.

При этом, да, у меня есть знакомый со своей фирмой, где все запросы клиентов решают только на Хаскелле. Бизнес-модель работает: этот код никто больше кроме них не может понять или отредактировать, таким образом получается vendor-lock совершенно минимальными ресурсами, а рекламу им делают, в том числе и такие стати о преимуществах и крутости Хаскелля над другими языками, особенно которые ОО.

Но я это пишу к тому, что если уж и учить что-то новое, то для себя я лучше разберусь в том, как кешируются данные в Hibernate, поковыряю документацию и внутренности PostgreeSQL или разберусь с OpenShift'ом, вместо того что бы разбирать что такое монада и зачем нужен функтор. А за других могу только порадоваться — если вам платят за работу на Хаскелле, то я только за, я вообще за то, что бы все могли заниматься тем, что любят, и получать за это достойную оплату.
Но я это пишу к тому, что если уж и учить что-то новое, то для себя я лучше разберусь в том, как кешируются данные в Hibernate
я занимаюсь проектом на java, немного знаю haskell. С уверенностью могу сказать, что мне проще разобраться как работает какой-нибудь persistent или slick, чем hibernate.
Многие требуют какой-то невероятной подготовленности к production для новых/непривычных инструментов. При это на сырость привычных инструментов закрывают глаза.
Будь моя воля, как разработчика на java — я бы никогда hibernate в production не пропустил. Т.к. это библиотека, как не парадоксально, для него не готова. И, судя по всему, не будет готова никогда =)
Играл немного с F#, любопытная штука. Пара мелких заметок по ходу, положу комментарием.

Функциональное программирование требует отсутствия побочных эффектов (side effects). Собственно, это не является корневым требованием, корневое это ссылочная прозрачность (referential transparency). Но отсутствие побочных эффектов является необходимым следствием. Возможно даже, необходимым и достаточным, тут нужно подумать-почитать. Разумеется, полностью избавиться от побочных эффектов невозможно. Потому что побочные эффекты это то, ради чего мы программируем. Изображение на дисплее, звук, запись в файл, передача данных по сети — всё это побочные эффекты. Программа без них была бы вещью в себе, не взаимодействующей с внешним миром. И в этом, как мне представляется, проблема функционального программирования. Оно требует извращённого выверта мозга, при котором ты перестаёшь видеть свою цель и считать её целью. А в самом конце приходится идти на лицемерный финт, нарушая красоту и благолепие, потому что мы, святые люди, всё ещё не вполне в нирване и не можем отринуть до конца потребности грешного тела. Альбигойская ересь какая-то: это ведь они считали, что духовный мир создан Богом, а материальный — Сатаной.

***

Очень хвалят F#, функциональный язык программирования под .NET Framework. Начал про него почитывать. Нужно сказать, что в родном объектно-ориентированном C# уже давно появились кое-какие функциональные элементы: LINQ, лямбды. Что там, лямбды уже и в C++ есть. Поэтому F# не шокирует с первого взгляда. Да, и так можно. Так короче, возможно — надёжнее. Чуть медленнее работает, но нам не привыкать платить производительностью. Нам есть чем платить, современные компьютеры на редкость мощные дуры. Не понятно для бизнеса, вот это уже серьёзнее. Идея «код должен быть понятен бизнес-аналитику» встречается всё чаще. Собственно, это частный случай более общей проблемы: ООП разрабатывалось как средство моделирования реального мира. Функциональное программирование реализует абстрактное «хорошо» не привязанное ни к чему. Эта концепция рискует оказаться чем-то вроде эсперанто: всё вроде бы правильно, а культурного багажа нет, говорят редкие энтузиасты.
Впрочем, это моё незрелое мнение. Продолжаем погружение.
Собственно, это частный случай более общей проблемы: ООП разрабатывалось как средство моделирования реального мира.

Где вы в реальном мире видели фабрики фабрик?

Несомненно, что сейчас ООП используется не только для моделирования объектов реального мира. Но фабрики фабрик как паттерн появились много позже ООП. В оригинале же, на всяких старых курсах, ООП учили именно на объектах реального мира.
Функциональное программирование требует отсутствия побочных эффектов (side effects)… побочные эффекты это то, ради чего мы программируем.

Вы, конечно, правы, но на самом деле всё наоборот.

Это популярное заблуждение, что в чистых языках или в ФП нет побочных эффектов.

В «грязных» языках побочные эффекты разрешены в любом месте и ими нельзя управлять. В чистых языках побочные эффекты живут только в специальных объектах-загончиках, только там, где они нужны, и ими можно управлять.

А "объекты-загончики" - это монады?

Тип оператора >=>, который иногда называют "fish", показывает суть монад: это способ композиции обогащённых функций. Побочные эффекты, работа с состоянием, исключения — всё это лишь частные случаи, они не определяют, что такое монады, но являются хорошими примерами их использования. Writer — тоже монада, определённая нами функция compose — это композиция морфизмов >=>, а функция writerId — тождественный морфизм return.

Т.е. это не монады?

А "объекты-загончики" - это монады?

Нет. Монадой может быть тип такого объекта (например, Writer). А может и не быть (например, ввод-вывод в старом Хаскеле был просто списком действий).

К чему именно относится второй вопрос, я не понял. Переформулируйте, пожалуйста.

Ну тогда ладно "объекты-загончики" - это не монады, а собственно монады - это (цитата из статьи авторки(ши)) "это способ композиции обогащённых функций" (что бы это не значило) . Что это за обогощённые функции такие и что преставляют сами "объекты-загончики" ?

Принцип монад — это способ композиции.

А сами монады — это типы, объекты которых можно монадически соединять.

Например, в Хаскеле есть объект getLine :: IO String, кодирующий ввод строки из потока ввода. Это операция ввода-вывода, как можно предположить по типу IO. Изнутри языка нельзя посмотреть, что там внутри (если интересно, внутри там вызов сишных примитивов, но это не важно). Но можно передать эту операцию на исполнение вместе с какой-то функцией-продолжением, операция исполнится, и в вашу функцию придёт строка из потока ввода.

Или вот есть функция putStr :: String -> IO (), она сама ничего не печатает, она только по строке вычисляет операцию вывода. Эту операцию можно исполнить или передать кому-то, кто умеет принимать операции ввода-вывода.

Здесь тип IO — монада, потому что можно операции соединять между собой, например,

getOncePutTwice =
  getLine >>=
    (\s ->
      putStr s >> putStr s)

при этом при соединении не производится ввод или вывод, а только вычисляется новая операция.

Или взять вот такую штуку (по мотивам библиотеки wreq):

get :: String -> IO Response

Формально, это функция, принимающая строку (урл) и вычисляющая операцию ввода-вывода, которая, будучи исполнена, сходит в сеть по заданному урлу и принесёт какие-то данные.

Можно ровно то же самое сказать иными словами: это операция ввода-вывода (сходить в сеть и принести ответ), параметризованная строкой (урлом). Тоже формально.

Неформально на эту функцию с операцией можно посмотреть как на «функцию, обогащённую вводом-выводом», у которой на входе строка (урл), на выходе ответ (от сервера), а в побочных эффектах операции ввода-вывода (хождение по сети и возможное исключение, если не удастся достучаться до сервера).

Принцип монад — это способ композиции.

А разве композиция (функций) не лежит в основе самой парадигмы ФП? Чем тогда монады отличаются от других "структур"-если этот термин можно применить к монадам- и можно ли все грязные побочные действия самому выполнять в виде вызовов сишных примитивов?

Здесь тип IO — монада

То, что IO является грязным/побочным (грязным или побочным?) действием, мы знаем по определению операции IO. Как тогда самому определить, какое действие является побочным? Можно ли по формальным признакам отделить монаду от чистого типа, например, от типа

plus :: Int -> Int

А разве композиция (функций) не лежит в основе самой парадигмы ФП?

Да, а монадная композиция позволяет соединять не только обычные функции-вычисления, но и «обогащённые», то есть разнообразные действия, например, ввод-вывод.

Есть ещё много других видов композиции для разных видов сущностей.

Чем тогда монады отличаются от других "структур"?

Именно этим и отличается. Монады — это такие "структуры", которые можно связывать, выход одного со входом другого. Ну и там несколько математических требований к этому связыванию. Грубо говоря, оно должно вести себя предсказуемо.

можно ли все грязные побочные действия самому выполнять в виде вызовов сишных примитивов?

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

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

Да, это строгий термин с формальными признаками. Они хорошо описаны в документации и разжёваны в учебниках вроде этого.

Грубо говоря, это должен быть тип с параметром, должна быть функция для связывания, и связывание должно вести себя предсказуемо, по правилам.

Интересно, что тип чистой функции вроде Int -> Int (точнее, Int -> a) с формальной точки зрения тоже будет монадой, но это математический трюк, это знание не особо часто может пригодиться в работе.

разжёваны в учебниках вроде этого

Там что-то про функторы

это должен быть тип с параметром

А что такое "тип с параметром"?

Там что-то про функторы

Да, именно так, через функторы разжёвано. Это ссылка на середину книги, её надо читать с начала.

А можно ничего не читать, можно просто пользоваться монадами как flatMap, большинство программистов так делают. Это менее интересно, но тоже достаточно продуктивно.

А что такое "тип с параметром"?

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

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

Ок, спасибо ))

Подскажите, какие паттерны вы используете для коммуникации между слоями в коде и внедрения зависимостей?

Из моего опыта — стек mtl-трансформеров и Service Handle паттерн, который пробуем сейчас на проекте.

НЛО прилетело и опубликовало эту надпись здесь

А-а-а, у монад есть и обобщения? Ну класс...

Haskell, конечно, крут. Я его практически не знаю (только начал изучать), но он мне уже нравится. Но проблемка одна есть — ни разу не видел вакансии типа "junior haskeller". Везде либо требуется опыт 100500 лет, либо "мы тут пишем на всяком г… не, но будет бонусом, если вы вдруг знаете Haskell зачем-то".

Большинство опытных хаскелистов получились как раз на таких местах, где надо совмещать г и Хаскель.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий