Сборка проектов на Haskell при помощи Stack
Прошло некоторое время с тех пор, как я последний раз писал в этом блоге что-то про Haskell. И вот, мне стало интересно, что успело измениться в мире этого языка. Изменилось, насколько я понимаю, не так уж и много, но вот вместо Cabal для сборки своих проектов теперь все используют какой-то Stack. Давайте же попробуем разобраться, что это за Stack такой.
В чем заключается идея
По большому счету, Stack сильно похож на утилиту cabal-install и, более того, обратно совместим с ней и использует внутри ту же самую библиотеку Cabal. Главное нововведение заключается в объединении определенного подмножества пакетов в так называемые LTS'ы (Long-Term Support, вы правильно поняли), которые публикуются на Stackage (Stable Hackage). Гарантируется, что пакеты, вошедшие в очередной LTS, хорошо работают друг с другом.
Дело в том, что при использовании большого количества зависимостей в проекте cabal-install и Hackage довольно часто создают проблемы. Например, зависимость А попросила, чтобы зависимость B была посвежее, но в этой версии посвежее сломано что-то, от чего зависила другая зависимость C. В результате проект не собирается. LTS'ы реже обновляются и содержат в себе не все пакеты (на момент написания этих строк – «лишь» ~1700 основных), но зато все работает. Кроме того, при сильном желании все также можно использовать пакеты, не входящие в LTS.
Установка и настройка
Допустим, у нас совершенно новая система, без GHC, Haskell Platform и так далее.
Для Ubuntu 14.04 просто говорим:
$ sudo apt-key adv --keyserver keyserver.ubuntu.com \
--recv-keys 575159689BEFB442
$ echo 'deb http://download.fpcomplete.com/ubuntu trusty main' | \
sudo tee /etc/apt/sources.list.d/fpco.list
$ sudo apt-get update
$ sudo apt-get install stack
На FreeBSD установить Stack проще всего так:
$ sudo pkg install hs-cabal-install
$ cabal update
$ cabal install stack
# у меня ~/bin уже прописан в $PATH
$ cp ~/.cabal/bin/stack ~/bin/stack
# cabal-install, ghc и так далее больше не нужны
$ rm -rf ~/.cabal ~/.ghc
$ sudo pkg remove hs-cabal-install
$ sudo pkg autoremove
Установка для других систем или версий Убунты описана здесь.
Теперь в ~/.stack/config.yaml пишем что-то в стиле:
templates:
params:
author-email: mail@eax.me
author-name: Aleksander Alekseev
category: Web
copyright: Copyright (c) Aleksander Alekseev
github-username: afiskon
Чтобы команды Stack'а автодополнялись в bash, в ~/.bashrc пишем:
eval "$(stack --bash-completion-script stack)"
Теперь установку и настройку можно считать завершенной.
Использование
Попробуем создать при помощи Stack новый проект.
Stack знает множество шаблонов проектов:
$ stack templates
Но мы пока что воспользуемся самым простым шаблоном по умолчанию:
$ stack new dummy-app
$ cd dummy-app
Лично у меня структура проекта получилась такой:
.
+-- app
| +-- Main.hs
+-- dummy-app.cabal
+-- LICENSE
+-- Setup.hs
+-- src
| +-- Lib.hs
+-- stack.yaml
+-- test
+-- Spec.hs
Наличие .cabal файла как бы намекает нам, что проект можно собрать обычным cabal-install, а также что зависимости и прочие свойства указываются, как обычно. В stack.yaml наибольший интерес представляет версия LTS. По умолчанию используется наиболее актуальная версия.
Следующая команда загружает версию GHC, соответствующую выбранному LTS:
$ stack setup
Да-да, компилятор тоже входит в LTS. Самим ничего устанавливать не нужно. И, что намного важнее, разные проекты могут использовать разные версии GHC.
Теперь можно работать с проектом как обычно. Единственное отличие заключается в том, что запуск REPL, сборка проекта, прогон тестов и запуск приложения выполняются командами:
$ stack ghci
$ stack build
$ stack test
$ stack exec dummy-app-exe
Ну и так далее. В случае чего, см. stack --help.
Также при помощи stack можно поставить обычных приложений:
$ stack install hlint hasktags hoogle
$ stack exec hlint ./
$ stack exec hasktags ./
$ stack exec hoogle data
$ stack exec hoogle search 'm a -> (a -> m b) -> m b'
Ждали чего-то более сложного? Жаль вас разочаровывать :)
Заключение
Больше информации о Stack и Stackage вы найдете по следующим ссылкам:
- https://www.stackage.org/;
- https://github.com/fpco/stackage;
- https://github.com/commercialhaskell/stack;
Лично у меня впечатления от Stack исключительно положительные. Идея очень интересная, вроде работает, и не припомню, чтобы я раньше видел что-то подобное в других языках.