Приготовимся

Мы не можем начать изучение языка без испытательного полигона. Установим 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, это:

  1. Разворачивать инфраструктуру.
  2. Собирать проекты.
  3. Устанавливать библиотеки.

Haskell-инфраструктура — экосистема, краеугольным камнем которой является ранее упомянутый компилятор GHC. Haskell является компилируемым языком: приложение представляет собой обыкновенный исполняемый (англ. executable) файл.

Haskell-проект — среда для создания приложений и библиотек.

Haskell-библиотеки — кем-то написанные решения, спасающие нас от изобретения велосипедов.

Разворачиваем инфраструктуру

Делаем:

$ stack setup

В результате на ваш компьютер будет установлена инфраструктура последней стабильной версии. Жить всё это хозяйство будет в только что созданном каталоге ~/.stack/. Именно поэтому устанавливать инфраструктуру для последующих Haskell-проектов вам уже не придётся: единожды развернули, используем всегда. Пока вам не нужно знать об устройстве этой инфраструктуры, воспринимайте её как данность: теперь на вашем компьютере живёт Haskell.

Hi World

Создадим наш первый 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

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