Вступление


Haskell это чистый функциональный язык программирования общего назначения со статической типизацией и ленивыми вычислениями. Появился в 1990 году и был назван в честь Хаскелла Карри. На данный момент основной реализацией является компилятор GHC.


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



Полезные инструменты на Haskell


1. Xmonad


Xmonad — тайловый оконный менеджер для X Window System, написанный на Haskell. Отличительной особенностью этого тайлового менеджера является то, что он конфигурируется также на языке Haskell, что позволяет нам использовать все возможности языка. Таким образом, настраивая наш оконный менеджер, можно подтянуть данные о погоде, замерять состояние системы и т.п.


Пример настроенной системы (by erikbackman)
Xmonad example


Для дальнейшего изучения можно пройти на сайт xmonad.


2. ShellCheck


ShellCheck — это утилита для анализа скриптов, написанных на bash. Она позволяет новичкам ловить частые ошибки, когда они только начинают изучать этот скриптовый язык, а более опытным пользователям помогает не пропустить мелкие ошибки в больших и сложных скриптах. Проект постоянно расширяется, а большое коммьюнити добавляет новые правила. ShellCheck можно посмотреть и попробовать на https://www.shellcheck.net/


Для примера будем использовать вот такой скрипт (попробуйте найти в нём ошибки, не заглядывая в результат проверки):


#!/bin/bash
## Example: ShellCheck can detect some higher level semantic problems

while getopts "nf:" param
do
    case "$param" in
        f) file="$OPTARG" ;;
        v) set -x ;;
    esac
done

case "$file" in
    *.gz) gzip -d "$file" ;;
    *.zip) unzip "$file" ;;
    *.tar.gz) tar xzf "$file" ;;
    *) echo "Unknown filetype" ;;
esac

if [[ "$$(uname)" == "Linux" ]]
then
    echo "Using Linux"
fi

Проверить файл очень просто: shellcheck example.bash.


В результате нам скажут о всех потенциально ошибочных местах в скрипте:
Shellcheck example


3. PureScript


На Haskell написано несколько популярных компилируемых функциональных языков для фронтенд-разработки, которые в итоге транспилируются в JavaScript. Сегодня мы поговорим о PureScript. У этого языка строгая система типов, которая поддерживает алгебраические типы данных, HKT (Higher-Kinded Types), тайпклассы с функциональными зависимостями. Также поддерживаются несколько необходимых и приятных фич, например FFI (Foreign Function Interface) с JS, а JS который получается на выходе выглядит очень даже читаемым. Язык уже оброс своей экосистемой в виде пакетного менеджера spago и IDE на основе своего собственного language server'а.


Для дальнейшего изучения можно пойти на официальный сайт https://www.purescript.org/


4. Agda


Haskell действительно хорошо подходит для создания языков программирования! Ещё один пример — Agda. Это язык с зависимыми типами, похожий по синтаксису на Haskell и имеющий серьёзную теоретическую основу. Но это ещё и система автоматического доказательства теорем: логические высказывания соответствуют типам, а доказательством правильности является успешный тайпчекинг.


Зачем всё это нужно? В первую очередь это позволяет избежать огромного количества ошибок времени выполнения и до какой-то степени не позволяет программисту написать неправильный код, как бы утопично это ни звучало. Рассмотрим классический пример: нам хотелось бы написать функцию head, которая берёт голову списка, но мы хотим быть уверены, что не передаём этой функции пустой список нигде в нашей программе.


-- Натуральные числа в виде чисел Пеано и их сложение
data Nat : Set where
  zero : Nat
  suc  : Nat -> Nat

_+_ : Nat -> Nat -> Nat
 zero  + m = m
 suc n + m = suc (n + m)

-- Вектор, зависимый тип, у которого длина хранится в типе
data Vec (A : Set) : Nat -> Set where
  []   : Vec A zero
  _::_ : {n : Nat} -> A -> Vec A n -> Vec A (suc n)

-- head, который нельзя применить к пустому вектору
head : {A : Set}{n : Nat} -> Vec A (suc n) -> A
head (x :: xs) = x

5. PostgREST


PostgREST это самостоятельный веб-сервер, который превратит схему вашей базы данных прямо в RESTful API. Такой подход позволяет не писать бойлерплейт, связанный с CRUD, а сосредоточиться на важных деталях бизнес-логики. Из плюсов можно выделить использование бинарного протокола postgresql, сериализацию JSON напрямую в SQL, для повышения производительности.


Для пример возьмем простую схему городов и стран:


Database schema
В итоге для такой схемы мы получаем следующий API:


Swager


Документация: https://postgrest.org/en/v8.0/index.html


6. Octopod


Octopod — разработанный нами в Typeable сервис (да-да, бессовестный самопиар!), который дает вашей команде возможность использовать всю мощь Helm без необходимости в технических знаниях. Наше решение позволяет упростить управление динамическими окружениями для всей команды: DevOps, разработчиков, тестировщиков и менеджеров проектов. Все, что вам нужно, это просто указать URL до Helm репозитория, а Октопод дальше автоматически достанет необходимые конфигурации.



Про этот сервис мы писали ранее, а дополнительную информацию можно найти на странице Octopod на нашем сайте и в репозитории на GitHub.


7. Pandoc


Pandoc это такой швейцарский нож, который позволяет из одного текстового формата перегнать данные в совершенно другой формат. Утилита понимает множество полезных синтаксических расширений, включая метаданные документа: автор, заголовок, даты, cноски, таблицы, подсветка снипетов кода, вставки LaTex с формаулами и т.д… Из поддерживаемых форматов документов можно перечислить Markdown, epub, docs, RTF, ODT, HTML, LaTeX, различные форматы wiki-разметки и библиографии.


Скачать и посмотреть все поддерживаемые форматы можно тут: https://pandoc.org/


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


Заключение


В этом списке я перечислил open-source проекты, которые показались мне наиболее интересны и полезны для широкого круга людей. Этот список можно использовать как ответ на вопрос "А чего полезного написали на Haskell за пределами науки?".


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


Вам также может понравиться:


  1. Как мы выбираем языки программирования в Typeable
  2. А вы знаете, где сейчас используется Лисп?
  3. Сильные стороны функционального программирования
  4. Haskell – хороший выбор с точки зрения безопасности ПО?

Версия на английском языке: https://typeable.io/blog/2021-10-18-haskell-tools.html

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


  1. csl
    19.10.2021 16:02
    +2

    https://github.com/0xd34df00d/refinedt ещё

    Proof-of-Concept языка с усовершенствованными типами, компилирующимся в Idris (частично написан на Haskell).


    1. 0xd34df00d
      19.10.2021 17:08
      +4

      Мам, я в телевизоре!


      Полезным инструментом я бы это не называл, это сильно одноразовый код ради разведки боем. Основное мясо там на агде как раз.


      1. csl
        19.10.2021 17:10
        +1

        А Plutus полезный?


        1. 0xd34df00d
          19.10.2021 17:34
          +1

          Plutus, кстати, полезный, да. Cardano-экосистему в этот список имеет смысл добавить.


          1. csl
            19.10.2021 17:47

            A sized-типы в Cardano-экосистеме есть?


            1. 0xd34df00d
              20.10.2021 19:45
              +1

              Нет, но они там не очень нужны.


      1. csl
        20.10.2021 04:16

        Кстати, используете Vim с Pathogen для Idris 2?


        1. csl
          21.10.2021 11:10

          И есть ли по Idris 2, Agda 2 что-нибудь вроде https://habr.com/ru/post/472780/comments/#comment_20807772 ?


          1. 0xd34df00d
            21.10.2021 19:52
            +1

            Пока не натыкался.


            Плагин для idris 2, кстати, через патоген прикручивается, но я как-то совсем перестал пользоваться идрисом последнее время, так что не знаю, как оно там сейчас.


      1. csl
        21.10.2021 12:45

        А в Agda гетерогенное неравенство?


        1. 0xd34df00d
          21.10.2021 19:51
          +1

          По умолчанию — нет, но соответствующий модуль, конечно, есть.


  1. DarthVictor
    19.10.2021 17:14
    +1

    PostgREST

    Тогда наверное надо и Hasura добавить.


  1. uoak
    19.10.2021 18:15
    +4

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


    1. qrKot
      20.10.2021 06:56
      +1

      Как вариант, использовать устоявшееся "академический язык", чисто семантически, вроде, подходит.


    1. fierce-katie
      25.10.2021 17:04

      Спасибо за замечание! Поменяли формулировку.


  1. vba
    20.10.2021 10:52
    +1

    Не забываем про змеиную среду - https://pyos.github.io/dg/


  1. vba
    20.10.2021 10:54

    PostgREST

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


  1. WASD1
    21.10.2021 22:22
    +2

    Ребят, а как вам пишется на Хаскеле и что пишите?

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



    ПС
    Прочитав название статьи - подумал было, что это будет про инструменты для разработчика на Хаскеле (типа "лучший плагин для IDE", "как проводить отладку", "как делать GUI"....) - нет в планах такой статьи?


    1. 0xd34df00d
      22.10.2021 00:39
      +1

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

      Писал разные вещи, от компиляторов (но там всё очень приятно) до перекладывающих жсончики из сокета в БД микросервисов. Сейчас один из проектов — плагин для поддержки агды для neovim'а (под него можно писать на хаскеле) — вполне приятно, и уж точно куда приятнее, чем было бы на условных python или lua или тем более vimscript.


      1. WASD1
        22.10.2021 15:21

        *) манимально представимых в виде алгоритмов -> максимально представимых в виде алгоритмов (извините ошибся).

        Компилятор (фронтэнд - мы с вами вроде общались по этому поводу) и стэйтлесс-сервер понятно. Но обычно (мне) нужно немного не это: ДСЛ имеет смысл только вместе с его исполнением, а сервис хочет быть более или менее мутабельным.

        А вот про плагин интересно.
        Спасибо посмотрю.


      1. csl
        24.10.2021 19:43

        @WASD1

        "[...]инструменты для разработчика[...]"

        Neovim для fullstack программиста

        https://habr.com/ru/post/585222/


    1. csl
      22.10.2021 11:25

      "[...]инструменты для разработчика на Хаскеле[...]

      Для начала Vim в терминале Kitty. Затем плагины к нему. Потом Неовим.


      1. WASD1
        22.10.2021 16:38

        Ну дебажить хаскель как (а то у меня был момент - когда хвалёные хаскелевские типы не спасли меня от алгоритмической ошибки и.... дебажился я долгим пристальным взглядом в код)?


        ПС
        И всё-таки без обид но gvim это прошлый век (буквально да) тем более для современных языков.

        Мне очень нравится gvim (vim в терминале отвязанном от bash - в итоге не перектываются некоторые клавиши) для работы на C.
        Но под любым более современным языком (с активным использованием разделения имён в namespace \ объектах) tabs + mkid уже не хватает для адекватной по проекту.
        А хаскелевский доступ к полям чеерз оператор & вообще с синтаксическим навигатором несовместим.

        Рефакторинг - вообще молчу.


        1. 0xd34df00d
          22.10.2021 18:35
          +1

          И всё-таки без обид но gvim это прошлый век (буквально да)

          Ну хз, мне норм. По сравнению с опытом для условного C++ в clion или некоторых коллег с питоном в pycharm — вполне себе, не хватает только семантической раскраски байндингов во все цвета радуги.


          А хаскелевский доступ к полям чеерз оператор & вообще с синтаксическим навигатором несовместим.

          Не понял, почему? Точно так же наводите курсор и точно так же жмёте «go to definition».


          Рефакторинг — вообще молчу.

          Единственное, что относительно нужно и что не работает — вынос локальных байндингов на топ-левел-уровень.


          1. csl
            22.10.2021 18:54

            А кто-нибудь из ветки получает уведомления на почту? Ничего не получил именно по поводу коммента, на который сейчас отвечаю. Отправил запрос в поддержку.


          1. WASD1
            22.10.2021 22:28

            Спасибо.

            Собственно то, что надо давать ссылку скорее доказывает мою позицию.
            Потому, что чтобы найти вот такой инструмент по vim нужно спрашивать на хабре, а чтобы найти IntellyJ-Haskell - надо зайти в плагины (тут ведь вопрос не в просто нагуглить, а найти сразу боле-менее стоящее, работоспособное, сопровождаемое или в сопровождении не нуждающееся......).
            То есть если рассматривать время потраченное на знание (->умение -> навык) в инструментах как "налог", то IDE всё-таки удобнее.

            Про & - я вот думаю правильно ли я выразился (не уверен, что "синтаксический навигатор" вообще чёткий термин) - но имел в виду, что вам надо знать контекст, не только чтобы найти правильный defenition, но и чтобы понять это функция из Control.Type.Operator или это Data.Function.
            Хотя вроде это задача того же уровня сложности, что найти defenition (ну т.е. 3-строчным скриптом на tags && id она нормально не решается, плагином, с полноценной серверной частью - решается и то и то).


            ПС
            К сожалению про debug ответа так и не получил.
            Правильно я понимаю, что ответ "никак"?


            1. 0xd34df00d
              22.10.2021 22:52
              +1

              То есть если рассматривать время потраченное на знание (->умение -> навык) в инструментах как "налог", то IDE всё-таки удобнее.

              Я там в посте написал в конце про intellij-haskell, но когда я пишу на английском, то я надеваю характерную англоязычную шляпу вежливости. Если говорить по-русски, то intellij-haskell работает отвратительно на проектах больше пары сот строк. Тормозит, жрёт память, ломает опции сборки, простейшие действия вроде go to definition работают через раз — и непонятно, то ли идея опять тормозит, и вот ща уже всё откроется, то ли не сработало, и надо глазками искать где-то там слева или справа снизу уведомление о том, что ничего не найдено.


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


              Хотя вроде это задача того же уровня сложности, что найти defenition (ну т.е. 3-строчным скриптом на tags && id она нормально не решается, плагином, с полноценной серверной частью — решается и то и то).

              Ну да, и HLS её вполне решает.


              К сожалению про debug ответа так и не получил.
              Правильно я понимаю, что ответ "никак"?

              ХЗ, мне как-то не особо приходится прям дебажить код, поэтому не могу ничего умного сказать.


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


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


              1. WASD1
                22.10.2021 22:58

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

                Спасибо, убедили попробовать.


                1. csl
                  21.11.2021 04:01

          1. Ddnn
            23.10.2021 20:13

            Ну хз, мне норм.

            Оффтоп - фоллбек-гифки в h264 лучше делать h264/yuv420p, а не h264/yuv444. h264/yuv444 каким-то рандомным образом не поддерживается (у меня только десктопный Brave ее смог осилить - в Firefox не работает, на android-телефоне ни Chrome, ни Firefox не справились, вот тут чуть больше проверили - https://bugzilla.mozilla.org/show_bug.cgi?id=1368063#c16).


            1. 0xd34df00d
              23.10.2021 20:18
              +1

              У меня тогда такой тупой вопрос — а как это делать? Я-то в этом не шарю и все команды на вики ffmpeg'а нагуглил, и для записи использую


              ffmpeg -video_size 780x500 -framerate 30 -f x11grab -i :0.0+2872,955 -c:v libx264 -crf 0 -preset veryslow $FILE.source.mp4

              а для перекодирования в h264


              ffmpeg -y -i $FILE.source.mp4 -c:v libx264 -preset veryslow $FILE.h264.mp4

              (дефолтный crf вроде норм)


              1. Ddnn
                23.10.2021 20:35

                Я так понимаю, вы хотите lossless-видео записать, и затем сжать гифку в h264?

                Тогда во вторую команду будет достаточно добавить -pix_fmt yuv420p:

                ffmpeg -y -i $FILE.source.mp4 -c:v libx264 -preset veryslow -pix_fmt yuv420p $FILE.h264.mp4


                1. 0xd34df00d
                  23.10.2021 20:41
                  +2

                  Я так понимаю, вы хотите lossless-видео записать, и затем сжать гифку в h264?

                  Ага. Жать сразу в av1 моя машина не потянет, а пережимать из h264 в av1 — ну такое.


                  Тогда во вторую команду будет достаточно добавить -pix_fmt yuv420p

                  Спасибо, сегодня-завтра переконвертирую. Благо, h264 конвертируется очень быстро.


    1. fierce-katie
      25.10.2021 17:23
      +2

      Пишем всякие B2B приложения в разных индустриальных областях (финтех, путешествия, биотех), в том числе фронтенд (https://habr.com/ru/company/typeable/blog/548574/). Я всю свою хаскельную карьеру (в сумме 4 года) в основном пишу бэкенды серверов: сходить во внешнюю систему, обработать данные из запроса и полученные из систем, вынуть/сохранить в БД, сформировать и отдать ответ клиенту. Т.е. по большей части как раз взаимодействие с внешним миром. Но на Хаскеле его можно явно отделить от "чистой" логики преобразования данных.

      А "как пишется" -- тут ответ будет очень субъективный :) Не нравилось бы, перешла бы на что-то другое, такое уже было: между двумя работами на Хаскеле писала под железо на чистом С, но не зашло.

      Прочитав название статьи - подумал было, что это будет про инструменты для разработчика на Хаскеле (типа "лучший плагин для IDE", "как проводить отладку", "как делать GUI"....) - нет в планах такой статьи?

      Именно такой в планах нет на данный момент, но будем писать про индустриальное использование Хаскеля в различных областях (по формату будет что-то нашей недавней статьи про использование Лиспа: https://habr.com/ru/company/typeable/blog/581488/)