Мы не можем начать изучение языка без испытательного полигона. Установим Haskell.
Сделать это можно несколькими способами, мы выберем самый удобный. Называется он The Haskell Tool Stack. Эта маленькая утилита — всё, что вам понадобится для работы с Haskell.
Haskell — кроссплатформенный язык, работающий и в Linux, и в macOS OS X, и даже в Windows. Однако в 2008 году я навсегда покинул мир Windows, поэтому все последующие примеры взаимодействия с командной строкой подразумевают Unix-way. Впрочем, если вы всё-таки используете Windows, будьте уверены — всё описанное ниже заработает и у вас.
Вся конфигурация и примеры кода опробованы мною на Ubuntu 16.04.1.
Идём сюда и забираем нужную нам версию. Общий Unix-вариант установки предельно прост:
$ curl -sSL https://get.haskellstack.org/ | sh
Готово. После установки нам будет доступна команда stack
, и она — наше всё.
На момент написания книги я использовал stack
версии 1.4.0. Если у вас более старая версия — непременно обновитесь. Если же более новая — у вас что-нибудь может работать не совсем так, как описано ниже, поскольку stack
всё ещё активно развивается.
Главное (но не единственное), что умеет делать stack
, это:
Haskell-инфраструктура — экосистема, краеугольным камнем которой является ранее упомянутый компилятор GHC. Haskell является компилируемым языком: приложение представляет собой обыкновенный исполняемый (англ. executable) файл.
Haskell-проект — среда для создания приложений и библиотек.
Haskell-библиотеки — кем-то написанные решения, спасающие нас от изобретения велосипедов.
Делаем:
$ stack setup
В результате на ваш компьютер будет установлена инфраструктура последней стабильной версии. Жить всё это хозяйство будет в только что созданном каталоге ~/.stack/
. Именно поэтому устанавливать инфраструктуру для последующих Haskell-проектов вам уже не придётся: единожды развернули, используем всегда. Пока вам не нужно знать об устройстве этой инфраструктуры, воспринимайте её как данность: теперь на вашем компьютере живёт Haskell.
Создадим наш первый Haskell-проект:
$ stack new real
Здесь real
— название проекта. В результате будет создан каталог real
, внутри которого мы увидим это:
.
├── app
│ └── Main.hs <- Главный модуль программы
├── LICENSE
├── README.md
├── real.cabal <- Сборочный конфиг проекта
├── Setup.hs
├── src
│ └── Lib.hs <- Ещё один модуль
├── stack.yaml <- Конфиг Stack
└── test
└── Spec.hs <- Тесты, они нам пока не нужны
Теперь переходим в каталог real
и собираем проект командой:
$ stack build
Запомните эту команду, мы будем использовать её постоянно. В результате сборки появится файл real-exe
. Располагается он внутри скрытого каталога .stack-work
в корне проекта. Чтобы сразу его запустить, не копаясь во внутренностях этого скрытого каталога, используем команду:
$ stack exec real-exe
someFunc
Команда stack exec
запускает программу (в данном случае real-exe
) внутри stack
-окружения. В одной из последующих глав я подробнее расскажу об этом окружении. Впрочем, мы можем запустить нашу программу и напрямую, без stack
. Исполняемый файл real-exe
находится внутри скрытого каталога .stack-work
в корне проекта. Например, на моём компьютере путь к исполняемому файлу такой:
.stack-work/dist/x86_64-linux/Cabal-1.24.2.0/build/real-exe/real-exe
Но можно и упростить себе жизнь, выполнив команду:
$ stack install
В результате исполняемый файл будет скопирован в каталог ~/.local/bin
(подразумевается, что такой каталог у вас уже имеется). Кстати, полезно добавить ~/.local/bin
в PATH
, что позволит вам тут же запускать программу:
$ real-exe
someFunc
Вот мы и создали Haskell-проект и запустили нашу первую программу, выведшую строку someFunc
. Но как же это работает? Пришла пора познакомиться с фундаментальной единицей проекта — модулем.
Haskell-проект состоит из модулей. Модулем называется файл, содержащий исходный Haskell-код. Один файл — один модуль. Расширение .hs
— стандартное расширения для модулей. В Haskell нет понятия «заголовочный файл»: каждый из модулей рассматривается как самостоятельная единица проекта, содержащая в себе разные полезные вещи. А чтобы воспользоваться этими вещами, необходимо один модуль импортировать в другой.
Откроем модуль src/Lib.hs
:
module Lib -- Имя модуля
( someFunc -- Интерфейс модуля
) where
-- Всё содержимое модуля - эта функция.
someFunc :: IO ()
someFunc = putStrLn "someFunc"
В первой строке объявлено, что имя этого модуля — Lib
. Далее в круглых скобках указан интерфейс данного модуля, то есть та его часть, которая видна всему миру. В данном случае это единственная функция someFunc
, объявление и определение которой идёт далее, вслед за ключевым словом where
. Пока вам не нужно знать о синтаксисе объявления и определений функции, в следующих главах мы разберём его тщательнейшим образом.
Теперь откроем модуль app/Main.hs
:
module Main where
import Lib -- Импортируем модуль Lib...
main :: IO ()
main = someFunc -- Используем его содержимое...
Это модуль Main
, главный модуль нашего приложения, ведь именно здесь определена функция main
. С помощью директивы import
мы включаем сюда модуль Lib
и можем работать с содержимым этого модуля.
Запомните модуль Main
, с ним мы будем работать чаще всего. Все примеры исходного кода, которые вы увидите на страницах этой книги, живут именно в модуле Main
, если не оговорено иное.
Все модули в наших проектах можно разделить на две части: те, которые мы берём из библиотек и те, которые мы создали сами. Библиотеки — это уже кем-то написанные решения, в последующих главах мы познакомимся со многими из них. Среди библиотек следует выделить одну, так называемую стандартную библиотеку. Модули из стандартной библиотеки мы начнём использовать уже в ближайших главах. А одна из глав будет полностью посвящена рассказу о библиотеках: из неё мы подробно узнаем, откуда берутся библиотеки и как их можно использовать.
До появления stack
основным способом установки Haskell была так называемая Haskell Platform. Однако именно stack
, несмотря на свою молодость (вышел в свет летом 2015 года), является предпочтительным путём в мир Haskell, особенно для новичков. Его настолько полюбили, что последние версии Haskell Platform включают в себя stack
по умолчанию!
Как вы заметили, имена файлов с исходным кодом начинаются с большой буквы: app/Main.hs
и src/Lib.hs
. Строго говоря, это необязательно, можно и с маленькой буквы, однако для гармонии с именем модуля лучше придерживаться общепринятой практики и называть файл модуля по имени самого модуля:
app/Main.hs -> module Main ...
src/Lib.hs -> module Lib ...
И ещё. При создании проекта мы могли бы использовать схему simple
вместо предлагаемой по умолчанию. Для этого проект нужно было создать командой:
$ stack new real simple
где simple
— имя схемы проекта. Дело в том, что команда stack new
может создавать заготовки проектов для разных нужд. Простейшая из заготовок называется simple
. В этом случае в проекте отсутствует модуль src/Lib.hs
, а есть лишь src/Main.hs
:
.
├── LICENSE
├── Setup.hs
├── real.cabal
├── src
│ └── Main.hs <- Единственный модуль
└── stack.yaml
Да, мы могли бы воспользоваться данной схемой, однако в этом случае мы не увидели бы механизма импорта одного модуля в другой. Я рад, что вы познакомились с импортом уже сейчас, ведь в последующих главах мы будем постоянно использовать различные модули из многих библиотек.