Хабрахабр

Говорят, Haskell — язык для гениев и академиков. Правда?

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

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

Чтобы узнать хаскелистов получше, я пришел с расспросами к ним в телеграм-чат. Все, что я слышал про Хаскель со стороны с тех пор, сводилось к одному — «с ним шутки плохи». Было довольно страшно, и как оказалось, не зря.

Уж если говорить — то с максимальной полнотой и объективностью. О Хаскеле не стремятся говорить популярно, и на такие затеи, кажется, поглядывают с презрением. Вместо этого выстраивали логичный principled путь решения реальных проблем, а не быстрого проникновения в сердце прохожего интересующегося» — написали мне там. «Одно из характерных качеств Хаскеля как языка и сообщества в том, что они вместе не стремились стать популярными, дав простой ответ на популярные вопросы.

Потом ещё был курс функционального программирования, на котором проходили Хаскель. Тем не менее, несколько человек рассказали о своем опыте, и я собрал их мнения здесь.
Денис Мирзоев (nolane): В университете по предмету «Языки программирования» мне предложили пройти курс на Coursera по Хаскелю за один дополнительный балл из ста. Нашёл работу в качестве Хаскель-программиста. Написал курсовую и выпускную работу бакалавра по GHC.

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

Возможно поэтому изучение Хаскеля даётся так тяжело. Многим сейчас будет трудно вспомнить, как они начинали свой путь в программировании, как трудно было понять, что такое «указатель», что такое «функция», что такое «класс». С возрастом становится труднее усваивать новое.

Сначала применял изученные практики в JavaScript, но потом узнал о Haskell, который считается истинным функциональным языком. Doctor_Ryner: Однажды на испытательном сроке я завалился на Redux, поэтому, смотря уроки от его создателя, решил поближе с этим всем познакомится. Меня сразу привлекла его элегантность и куча новых неизвестных мне концепций.

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

Юрий Сыровецкий (cblp): Сложнее всего изучать Хаскель вторым, когда не прошёл синдром утёнка к первому языку.

Чем хорош и чем плох язык?

Doctor_Ryner: Язык очень краткий, элегантный и гибкий, не зря на нем половина библиотек — это EDSL (как минимум такое впечатление).

Легко строить абстракции над данными и алгоритмами, что позволяет думать о задаче, не отвлекаясь на несвязанные мелочи. Юрий Сыровецкий (cblp): Высокая выразительность, легко переносить предметную область в код, оптимальное сочетание императивной и функциональной парадигм.

Джон Доу: Строгая сильная (я бы сказал, фашистская) типизация.

Не настолько мощная, как у Idris или Agda, но достигает той золотой середины, когда выразить можно почти всё, и при этом вывод типов работает нормально. Игорь Шевнин (interphx): Очень выразительная система типов. Не надо везде помечать их вручную.

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

Тут нет null, сама функциональная парадигма очень строга и принуждает тебя следовать определенным правилам, которые в большинстве случаев ведут к лучшему дизайну. Doctor_Ryner: Изучая Haskell, ты скорее всего наткнешься на высказывание «if it compiles, it is probably correct».

Тебе не приходится следить за тем, что и где ты присваиваешь. Например, в языке нет переменных — только константы. Функциональный дизайн просто заставляет программу работать как одно целое, в противовес ООП, где в мир выброшена куча объектов и объекты пытаются общаться друг с другом путем побочных эффектов, превращая приложение в непредсказуемое месиво. Haskell поощряет использование чистых функций, что ведет к отсутствию побочных эффектов. На работе достаточно страдаем от такого с C# в Unity.

Многие алгоритмы становятся проще. Денис Мирзоев: Встроенная ленивость повышает выразительность языка. (К примеру `head. Она может увеличить производительность, если результаты промежуточных вычислений не будут использоваться. sort` работает за линейное время).

Игорь Шевнин: Ленивая модель вычислений обычно помогает, но когда порядок вызова функций важен, может быть трудно разобраться, что происходит.

Doctor_Ryner: Он компилируемый, что сразу же дает огромный прирост в скорости.

Денис Мирзоев: По скорости сравним с Java, но не такой быстрый как C.

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

Поэтому приходится использовать альтернативы или писать свои реализации. Doctor_Ryner: В стандартной библиотеке Prelude есть очень плохие функции наподобие read, head, readFile, которые могут выкинуть Exception и положить программу, вместо того, чтобы возвращать Maybe.

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

Денис Мирзоев: Не хватает тулов: нет полноценной IDE, очень мало средств для замеров производительности, нет отладки «по шагам» — это вообще говоря фундаментальная проблема.

Для каких проектов Haskell подходит лучше всего?

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

Сильно удивлен, что Haskell менее популярен в Data Science, чем Python. Doctor_Ryner: Для всего, где нужно проводить вычисления, преобразование и анализ данных.

Также надо понимать, что найти разработчиков в команду намного сложнее, чем для мейнстримных языков. Игорь Шевнин: Я бы не рискнул использовать его для встраиваемых систем (производительность неплоха, но всё же есть значительный оверхэд по потреблению памяти из-за ленивых вычислений) и мелких скриптов (там эта строгость просто не нужна).

Такую мало кому удалось собрать. Джон Доу: Чтобы писать промышленный код, который будут читать другие — вам нужна будет целая команда хаскеллистов.

Игорь Шевнин: Но благодаря краткости и строгости Haskell подходит почти для любых задач.

Начинать изучать разработку с Haskell — хорошая идея?

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

Языки не из семейства ML — а такие из промышленных вообще все — потом будут для вас шоком. Джон Доу: Плохая, плохая идея!

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

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

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

Haskell — достаточно старый язык. Это хорошо или плохо?

Юрий Сыровецкий: Развивается язык очень активно, груз совместимости только ради совместимости не тянет.

Джон Доу: Стандарт принят в 1998-ом, но это не заметно: до сих пор новые версии компилятора, потенциально ломающие обратную совместимость, выходят примерно раз в полгода.

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

Про Haskell говорят, что это один самых сложных языков. Это так?

Doctor_Ryner: Как сам язык — нет. Сложны скорее абстракции, которые в нем используются. Человек, который никогда не видел кода на Haskell, может просто сойти с ума от потока новой информации и разных непривычных конструкций.

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

Правда скомпилировавшись, проект сразу заработал и фигачил под полной нагрузкой (6k rps с пиками до 15) полгода, без изменений вообще. Джон Доу: Чтобы первый элементарный проект хотя бы просто скомпилировался, ушло почти два месяца курения учебников, мануалов и туториалов по вечерам.

Денис Мирзоев: Готов поспорить, что если школьник начнёт изучать программирование с Хаскеля и продвинется достаточно далеко, то императивное программирование ему покажется более сложным и менее интуитивным.

Из мейнстримных языков я всё ещё считаю C++ самым сложным. Игорь Шевнин: Сложность относительна. Haskell — несложный язык, но его паттерны и библиотеки — стандартные и сторонние — выучить удастся далеко не сразу. Языки для доказательства теорем (Agda, Coq) будут посложнее Хаскелля в концептуальном смысле.

Всегда ли его сложность оправдана?

Игорь Шевнин: Паттерны и высокий уровень абстракции оправданы, так как делают код надёжнее и короче. Но думаю, что операторы, имена функций и многие другие вещи могли бы быть понятнее.

Doctor_Ryner: Зачастую сложные конструкции Haskell позволяют создавать очень короткие решения, которые еще и оказываются очень гибкими и модульными.

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

Для людей, которые изначально не интересовались теорией категорий, добиться результатов с абсолютного нуля — очень тяжело. Джон Доу: Язык для привыкших к обычным python/php/whatever вообще производит впечатление ортогонального к реальности.

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

Haskell видится языком как будто для математиков, а не для разработчиков. Как думаете, он не распространен широко из-за этого?

Денис Мирзоев: Это демонстрация принципа, которому следуют главные разработчики Хаскеля — «avoid success at all costs». Смысл, конечно, не в том, что нужно избегать успеха, а в том, что нужно избегать успеха, цена которого слишком высока.

Есть, к примеру, поддержка этого языка со стороны Microsoft. Можно было сделать Хаскель популярным. Можно было использовать много грязных приёмов, но благодаря такой правильной позиции главных разработчиков ничего подобного не было. Можно было сделать язык более императивным, принимать какие-то быстрые и непродуманные решения, чтобы завоевать популярность.

Мне очевидны преимущества Хаскеля по отношению к императивным языкам, большинство его проблем разрешимы, поэтому я уверен, что большая популярность ещё придёт по мере его развития. Да, популярность языка не очень высока, но зато не страдает его качество.

В
«реальной» разработке Хаскель применяется давно, примеры легко найти в
вашей любимой поисковой системе. Юрий Сыровецкий: Таким он видится только людям, ничего про него не знающим. В частности, мы в ЛК использованием
Хаскеля довольны, и ничего другого на его месте не видим.

Это либо R/MatLab/Mathematica для расчётов и статистики, либо Python, потому что он простой и требует меньше инженерного бэкграунда. Игорь Шевнин: Что такое «язык для математиков» я толком не знаю. Алгебраические понятия типа моноидов используются в нём из практических соображений, а не только для дополнительной строгости. Но не Haskell.

Но сейчас многие компании начинают использовать Haskell и другие функциональные языки. Основную роль в популярности сыграла историческая распространённость C/C++/Java/C# в энтерпрайзе, они заняли нишу.

С каким япом ты бы сравнил Haskell и в чью пользу?

Джон Доу: Из более или менее распространенных — с Erlang. Но на Erlang все же проще писать и его проще выучить, как мне кажется.

C++ даже сравнивать ни с чем не надо, язык ужасен. Денис Мирзоев: Я хорошо знаю C, С++, Java и Haskell. В этой нише он будет лучше. Си — хороший язык для низкоуровневой разработки. В остальном я бы предпочёл Haskell.

Под андроид на Haskell будет скорее всего трудно писать, в этом случае лучше Java. Выбор между Java и Haskell уже труднее, но тут тоже нужно смотреть на конкретную задачу. Если окружение позволяет — тулинг, доступность библиотек, — то я обычно выбираю Haskell. А вот сервера писать на Haskell почти также удобно как и на Java.

Очень странно, что диктаторский чисто функциональный Haskell чувствуется гораздо более гибким и свободным. Doctor_Ryner: С C#, достаточно погуглить, как реализовать Maybe на C# и на Haskell. На самом деле это две крайности.

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

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

Что думаете про сообщество хаскелистов?

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

Не зря ходят локальные мемы про PhD, теорию категорий и академиков. Doctor_Ryner: Haskell сообщества зачастую содержат в себе пугающе умных людей, которые всегда готовы помочь. В чате по Haskell перед тобой сразу выскакивают монады, лемма Йонеды, аппликативные функторы, написание безумных типов и прочее-прочее. Если заходя в чат по другим языкам, ты видишь, что люди обсуждают обычные production-проблемы и структуры данных.

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

Говорят, хаскелисты высокомерные. Правда?

Денис Мирзоев: Да. Мне кажется высокомерность связана с тем, что они очень любят свой язык и расстроены его недооценённостью.

Джон Доу: Нифига подобного.

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

Тут скорее дело в том, что ФП, ООП, различие ООП-классов и union types, extension problem и много других понятий однажды складываются в очень чёткую картинку, и после этого становится трудно воспринимать людей, которые пытаются противопоставить ООП и ФП или другим образом представить широкую проблему в узкой перспективе. Игорь Шевнин: Высокомерие — слишком сильное слово.

Почему ФП-языки до сих пор нишевые?

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

Игорь Шевнин: Нишевость постепенно проходит, а функциональные концепции подтягиваются в другие языки.

Даже для шарпов есть Linq и некоторые другие библиотеки. Doctor_Ryner: Сами функциональные принципы и языки, что их поддерживают, уже повсеместны. Нишевые скорее чисто функциональные языки, так как в них используются нестандартные концепции.

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

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть