Привет!

Продолжаем говорить про Haskell со спикерами FPConf 2017.

Павел Аргентов задал несколько вопросов Senior Software Engeneer в Tweag I/O Александру Вершилову, программисту, который уже 10 лет продвигает Haskell в индустрии.


— Над каким проектом ты сейчас работаешь? В чем его особенность.

— Это веб-сервис, который можно по-простому описать как “Эксель на стероидах”. Он позволяет использовать при вычислениях произвольные языки — Python, R и еще некоторые.

— На этих языках создаются доступные юзеру процедурные объекты?

— Юзер может использовать свои библиотеки; в формулах внутри ячеек можно помещать, например, код на Питоне: объекты, реализованные таким образом, могут использоваться прямо в “экселевской” таблице. Также к ним можно получить доступ из процедур на другом языке — например, R.

— Ты — Haskell-разработчик. Каково место Haskell во всей этой истории?

— Центральное :). На Haskell написан сам сервер. На него приходится вся промышленная нагрузка, связанная с запросами, вся логика графов зависимостей и выполнения. Остальные языки представлены пользовательскими процедурами, которые делают локальные вычисления и возвращают результат.

— Раскроешь какие-нибудь особенности реализации серверной части?

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

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

— В Haskell сейчас сложилась несколько парадоксальная ситуация, когда, с одной стороны, уже есть отличная runtime система, подходящая для решения практических задач, с другой же стороны видны проблемы вроде идиотских дефолтных настроек GC — их нужно переписывать всякий раз, когда надо сделать что-то работающее. Есть хорошие библиотеки, но стандартная библиотека ужасна. Нет общего понимания о стиле написания кода. Есть множество библиотек и множество методик, которые не доведены до такого состояния, чтобы можно было сказать: “Вот это — лучшее!” Или: “Вот два хороших варианта, выберем наиболее подходящий.” Часто получается, что если делается проект, в котором не нужна максимальная эффективность, то все хорошо. Однако, как только начинаются моменты где нужно выжать из кода наибольшую производительность, начинаются проблемы. Часто приходится что-то доделывать, переписывать. Экосистема в целом движется в нужном направлении, но на мой взгляд, недостаточно быстро. В попытках решения проблем есть конкурирующие варианты, но нет приемлемого общего решения.

Есть проблемы “стандартные языковые”, например, с ленивостью. Честно говоря, я бы даже не назвал это проблемой. До определенного момента можно писать и не задумываться о ленивости — обычно все работает. Иногда, когда что-то ломается, приходится сесть, отладить, разобраться, но это уже проблема несколько иного рода, она подразумевает более глубокое знакомство с языком и его инструментами. Есть проблема с GC: в его механике много такого, что приводит к лишним задержкам при выполнении кода…

— То есть он делает “stop the world” и…?

— Да, он делает “stop the world” — и собирает все что можно. Тогда, если задача состоит в том чтобы вернуть ответ за минимальный промежуток времени, могут начаться проблемы. Насколько я помню, в компании Pusher (Pusher.com) даже ушли с Haskell, потому что не смогли решить эту проблему. Им было нужно очень малое время ответа. В итоге, они решили что проще взять другой язык, который предоставит то, что им нужно, по умолчанию.

— А что они взяли, если не секрет?

— По-моему, Go.

— В последние годы Haskell довольно активно “выстрелил”, став внезапно из сугубо академического — вполне рабочим инструментом. Естественным образом интерес к нему выразился в том, что люди стали писать библиотеки. Каковы особенности библиотечного мира Haskell?

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

— Что в Haskell с системами управления библиотеками?

— Есть Cabal и Stack. Подозреваю что сейчас баланс популярности сдвинулся в сторону Stack, по разным причинам. Он гораздо быстрее развивался, у него проще интерфейс, и, в общем-то, когда работает — он работает. Механика такова, что если проект описан через stack-файл, то с очень большой вероятностью человек, который его запустит, получит что-то работающее.

— То есть, реализуется изоляция зависимостей в лучшем виде, создается “песочница”, в которую можно подключить нужные библиотеки и собрать приложение?

— Да. В принципе, “cabal install” тоже все это умел. Но нужно было делать больше движений. И вообще, всё было сложнее. Новичка гораздо проще научить двум командам stack, чем объяснять, как работает “cabal install”. Большой плюс stack состоит в том, что он работает поверх Stackage — своеобразных “срезов” Hackage, в в пределах которых зависимости — программы и библиотеки — гарантированно совместимы между собой.

Если человек добавляет пакет на Stackage, он, как минимум, гарантирует собираемость её с другими компонентами текущего стека. Иначе пакет будет из Stackage исключен. Всегда подразумевается, что если пакет есть на Stackage, то его поддерживают.

— Есть ли в Haskell-среде проблемы с документацией? Какая документация встречается чаще — хорошая или посредственная?

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

— А если обращать внимание на количество звездочек у проекта на гитхабе?

— Не обращал внимания… Я не замечал четкой корреляции между звездочками и качеством кода. Далеко не все в коммьюнити любят поставить звездочку, если считают пакет хорошим. Лично я так никогда не делаю. Почему-то. Для меня звездочка — это отметка библиотеки как просто интересной.

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

— Я вошел в Haskell, имея нулевое знание в теории категорий, какие-то знания в программировании и опыт работы на PHP. То есть, в принципе, если не бояться и понять несколько простых вещей — зачем нужен тайп-чекер, почему он друг, а не враг, и так далее — многие “ужасы” исчезают сами собой. Особенно продвинутых знаний в области математики не нужно, хотя они и помогают читать документацию некоторых пакетов.

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

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

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

— Это как бы принуждает программиста думать как следует, я правильно полагаю?

— С одной стороны да, заставляет думать как следует. А с другой… Я бы просто не смог написать такие же сложные программы на многих других языках.

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

— Несмотря на стройность и строгость языка, опытный разработчик всегда, если постарается, сможет “выстрелить себе в ногу”. Что бы ты отметил как проблемы Haskell для опытных разработчиков?

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

— Насколько хорош Haskell в параллельных или конкурентных решениях?

— С моей точки зрения, тут все прекрасно. Все проекты, которые мы ведем, используют concurrency. Имеющаяся РТС просто превосходна. Есть разные библиотеки, которые позволяют распараллелить вычисления. Даже в обычном коде можно распараллеливать выполнение очень дешево — буквально в один комбинатор один эффект.

— На конференции будут присутствовать люди, которые не только кодят, но и нанимают кодеров. Они планируют проекты, они бизнесмены. Они будут оценивать риски…

— Риски есть. Большие риски — если набрать команду новых людей, которые вчера программировали на императивном языке — и вдруг им дают Haskell. Тогда возникнут проблемы. Но если в команде есть несколько человек с опытом — например, на пять человек двое опытных хаскеллистов — то ситуация кардинально меняется. Исчезают все проблемы поиска библиотек, потому что опытные разработчики знают риски использования разных библиотек. Более того, существует множество фирм, которые могу консультировать, делать аудит кода и “proof of concept”, либо же просто подсказать как решать архитектурные проблемы. Такие обстоятельства могут существенно облегчить работу на начальном этапе.

— Для каких бизнес-решений Haskell наиболее подходит а для каких — не очень?

— Есть задачи, в которых нужны дополнительные гарантии корректности кода, потому что неправильный код выражается в конкретных денежных убытках. В этих случаях за счет Haskell можно получить существенный выигрыш. Есть много примеров фирм, которые работали с финансами и понимали, что им хочется больше гарантий эффективности разработки. В таких случаях Haskell и имеет смысл. Далее, существуют различные инфраструктурные решения. Например, нужно запустить на Amazon много сервисов, настроить их зависимости, одно, другое. Очень часто проще написать лаконичный DSL на Haskell, чем писать много кода на языке, который совсем не поможет.

— Такой DSL будет читаем для человека, который ставил задачу?

— Да, плюс типы.

Ещё Haskell полезен там, где нужна генерация кода, написание DSL, своих компиляторов. На Haskell можно генерить C, Python, Java для использования в сложных многоязыковых решениях.
А вот куда не стоить идти фирме, которая не Haskell-oriented, так это туда, где есть уже готовые большие решения на других языках. Переписывать заново на Haskell систему на Erlang или Spark — не самая лучшая затея.

— Какие требования предъявляет Haskell к грамотности менеджмента?

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

Интересно? Узнать у Александра больше можно будет 2 декабря на FPConf, приходите!

Комментарии (0)