Как начать писать на Haskell: опыт Python-программиста

Рассказывает автор блога Mechanical Elephant, Мэтью Гриффин


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

И хотя я иногда прибегаю к помощи Python, большую часть работы в вебе я теперь делаю на Haskell.

В первую очередь — данные

Я думал о переходе от динамического языка к статическому, а в Haskell’e структура данных, с которыми вы работаете, четко описывается при объявлении. В Python в большинстве случаев эту задачу выполняет код.

Когда я впервые увидел функции в Haskell, я задался вопросом: «Что представляют собой данные? Эта функция что-то берет на вход и выдает что-то на выходе?» А при работе с Python у меня возникал вопрос: «WHAT DOES THE CODE SAY?»

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

Читаемость кода

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

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

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

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

А более мощные абстракции в Haskell и вовсе напоминают некую магию, которой я пытался избегать при работе с Python.

Про читаемость я говорю серьезно

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

Комментарии. Они занимают верхнюю строчку в одной из глав нашей «книги».

Эта глава описывает то, как Томми пошел в магазин и купил утку.

chapter :: Tommy -> Market -> Duck

Функции из другой, уменьшенной функции, в общей картине сокращают код по максимуму.

Краткость. Вам не потребуется тонна кода для воплощения ваших идей.

Вставные символы

Я также хотел упомянуть о вставных функциях, которые распространены в языке Haskell. Вставные функции (или операторы) — это те функции, которые используют between для двух аргументов вместо before. Простым примером является «+».

В языке Haskell мы имеем несколько вставных символов, которые используются по умолчанию: $, <$>, <-, ->, др. Они могут вас немного смутить на начале пути.

Не переживайте! Как только вы научитесь применять их, вы поймете, как они полезны и просты. Я насчитал около 5 символов, которые я использую регулярно.

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

Нужно полностью обновить знания

При изучении Haskell вы будете попутно сталкиваться с новыми терминами, например, функтор или монада.

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

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

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

Например, функтор.

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

map (+1) [1,2,3,4]

-- results in [2,3,4,5]

Так я дал название этому — мапа. Слово «мапа» является очень простым для запоминания. Список — это функтор. Список — это мапа.

Моя система проверки ошибок

Когда я писал на Python, моим инструментом отладки были операторы печати.

В Haskell я пользовался систематическими инструментами.

Но! Вы можете применить Debug.Trace. Данный прием схож с тем, как в Python функция печати не зависит от Haskell IO. И данный модуль может вначале принести пользу . Когда вы только начинали работать с Haskell, вы думали о том, как много вы будете его использовать?

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

Лучший учебник по монадам

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

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

Окей, сейчас я расскажу подробнее. Я буду объяснять на Haskell.

Я нашел видео на YouTube, «Parsing Stuff in Haskell», в котором описывалось, как сделать JSON анализ в Haskell, используя при этом библиотеку Parsec.

Это видео помогло мне ненароком понять, как можно, используя монады и аппликативные функторы, создать то, что мне требовалось. Я понял, как их функции (har, har) соединяются друг с другом.

После написания синтаксического анализа при помощи видео, я начал понимать весь код. Я также начал понимать всю его «природу». Но на начальном этапе это не пригодится.

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

Польза от ваших знаний

Haskell является моим основным языком по нескольким причинам:

  1. Выбор технологий, которыми я буду пользоваться.
  2. Я могу писать свои программы быстрее, и чаще всего эти программы я и продаю.
  3. Не приходится иметь дело с мелкими багами.
  4. Даже сталкиваясь с несколькими ошибками, я быстро решаю их, так как они более-менее понятны.
  5. Python не делал акцент на скорости работы. Haskell делает то же самое, но выбор все же за мной.
  6. Рефакторинг, по сути, достаточно «ветреный». В Python я иногда сильно ругал себя, когда забывал править небольшие ошибки в коде, которые позже вызывали огромные затруднения.
  7. Замечательные библиотеки. Основная особенность Haskell заключается в высоком качестве библиотек.
  8. Сообщество, всегда готовое помочь.
  9. Простота масштабирования кода до нужного ядра.
  10. Haskell часто обновляется. В прошлом году, когда GHC (компилятор для Haskell) был обновлен до версии 7.8, делая при этом написание кода в два раза удобнее, были ускорены многие веб-сервера.

И в заключение хочу сказать, что Haskell доставил мне уйму удовольствия. Это был лучший опыт за всю мою жизнь.

С чего можно начать?

Я постарался и нашел много «отправных точек» для начала вашего знакомства с Haskell.

Здесь я продемонстрирую то, как бы я начинал, если бы был не знаком с Haskell.

Для начала, прочитайте статью «Learn you a Haskell for Great Good».

Отлично! Теперь выполните следующие пункты:

  1. Напишите маленький модуль, при этом не используя IO. Что-то на примере судоку, в котором происходит генерация пазлов. Используйте рандомные числа для начала. Используйте Debug. Используйте оператор печати, чтобы видеть каждый ваш шаг. Сделайте генерацию пазлов и Debug’а. Отправьте все на экран. Создайте свой собственный тип файлов и используйте функции.
  2. Закиньте все на сайт. Для этого используйте Scotty или Spock. Вот и все, ваш URL готов. Затем, URL, создающий JSON в вашем пазле.
  3. Повозитесь с IO. Попробуйте написать пазл в терминале, не пользуясь Debug.Trace.
  4. Находите новые варианты. Измените формат файла для пазла судоку и напишите синтаксический анализ Parsec для него! Не делайте формат JSON — попробуйте что-то новое.

Удачи!

Оригинал: Mechanical Elephant