denisshevchenko/ohaskell.guide

View on GitHub
chapters/04-setup.md

Summary

Maintainability
Test Coverage
# Приготовимся

Мы не можем начать изучение языка без испытательного полигона. Установим Haskell.

Сделать это можно несколькими способами, мы выберем самый удобный. Называется он [The Haskell Tool Stack](http://haskellstack.org/). Эта маленькая утилита — всё, что вам понадобится для работы с Haskell.

Haskell — кроссплатформенный язык, работающий и в Linux, и в macOS OS X, и даже в Windows. Однако в 2008 году я навсегда покинул мир Windows, поэтому все последующие примеры взаимодействия с командной строкой подразумевают Unix-way. Впрочем, если вы всё-таки используете Windows, будьте уверены — всё описанное ниже заработает и у вас.

Вся конфигурация и примеры кода опробованы мною на Ubuntu 16.04.1.

## Устанавливаем

Идём [сюда](https://docs.haskellstack.org/en/stable/install_and_upgrade/) и забираем нужную нам версию. Общий Unix-вариант установки предельно прост:

```bash
$ curl -sSL https://get.haskellstack.org/ | sh
```

Готово. После установки нам будет доступна команда `stack`, и она — наше всё.

На момент написания книги я использовал `stack` версии 1.4.0. Если у вас более старая версия — непременно обновитесь. Если же более новая — у вас что-нибудь может работать не совсем так, как описано ниже, поскольку `stack` всё ещё активно развивается.

Главное (но не единственное), что умеет делать `stack`, это:

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

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

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

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

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

Делаем:

```bash
$ stack setup
```

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

## Hi World

Создадим наш первый Haskell-проект:

```bash
$ stack new real
```

Здесь `real` — название проекта. В результате будет создан каталог `real`, внутри которого мы увидим это:

```bash
.
├── app
│   └── Main.hs <- Главный модуль программы
├── LICENSE
├── README.md
├── real.cabal  <- Сборочный конфиг проекта
├── Setup.hs
├── src
│   └── Lib.hs  <- Ещё один модуль
├── stack.yaml  <- Конфиг Stack
└── test
    └── Spec.hs <- Тесты, они нам пока не нужны
```

Теперь переходим в каталог `real` и собираем проект командой:

```bash
$ stack build
```

Запомните эту команду, мы будем использовать её постоянно. В результате сборки появится файл `real-exe`. Располагается он внутри скрытого каталога `.stack-work` в корне проекта. Чтобы сразу его запустить, не копаясь во внутренностях этого скрытого каталога, используем команду:

```bash
$ stack exec real-exe
someFunc
```

Команда `stack exec` запускает программу (в данном случае `real-exe`) внутри `stack`-окружения. В одной из последующих глав я подробнее расскажу об этом окружении. Впрочем, мы можем запустить нашу программу и напрямую, без `stack`. Исполняемый файл `real-exe` находится внутри скрытого каталога `.stack-work` в корне проекта. Например, на моём компьютере путь к исполняемому файлу такой:

```bash
.stack-work/dist/x86_64-linux/Cabal-1.24.2.0/build/real-exe/real-exe
```

Но можно и упростить себе жизнь, выполнив команду:

```bash
$ stack install
```

В результате исполняемый файл будет скопирован в каталог `~/.local/bin` (подразумевается, что такой каталог у вас уже имеется). Кстати, полезно добавить `~/.local/bin` в `PATH`, что позволит вам тут же запускать программу:

```bash
$ real-exe
someFunc
```

Вот мы и создали Haskell-проект и запустили нашу первую программу, выведшую строку `someFunc`. Но как же это работает? Пришла пора познакомиться с фундаментальной единицей проекта &mdash; модулем.

## Модули: знакомство

Haskell-проект состоит из модулей. Модулем называется файл, содержащий исходный Haskell-код. Один файл &mdash; один модуль. Расширение `.hs` &mdash; стандартное расширения для модулей. В Haskell нет понятия &laquo;заголовочный файл&raquo;: каждый из модулей рассматривается как самостоятельная единица проекта, содержащая в себе разные полезные вещи. А чтобы воспользоваться этими вещами, необходимо один модуль импортировать в другой.

Откроем модуль `src/Lib.hs`:

```haskell
module Lib      -- Имя модуля
    ( someFunc  -- Интерфейс модуля
    ) where

-- Всё содержимое модуля - эта функция.
someFunc :: IO ()
someFunc = putStrLn "someFunc"
```

В первой строке объявлено, что имя этого модуля &mdash; `Lib`. Далее в круглых скобках указан интерфейс данного модуля, то есть та его часть, которая видна всему миру. В данном случае это единственная функция `someFunc`, объявление и определение которой идёт далее, вслед за ключевым словом `where`. Пока вам не нужно знать о синтаксисе объявления и определений функции, в следующих главах мы разберём его тщательнейшим образом.

Теперь откроем модуль `app/Main.hs`:

```haskell
module Main where

import Lib      -- Импортируем модуль Lib...

main :: IO ()
main = someFunc -- Используем его содержимое...
```

Это модуль `Main`, главный модуль нашего приложения, ведь именно здесь определена функция `main`. С помощью директивы `import` мы включаем сюда модуль `Lib` и можем работать с содержимым этого модуля.

Запомните модуль `Main`, с ним мы будем работать чаще всего. Все примеры исходного кода, которые вы увидите на страницах этой книги, живут именно в модуле `Main`, если не оговорено иное.

Все модули в наших проектах можно разделить на две части: те, которые мы берём из библиотек и те, которые мы создали сами. Библиотеки &mdash; это уже кем-то написанные решения, в последующих главах мы познакомимся со многими из них. Среди библиотек следует выделить одну, так называемую стандартную библиотеку. Модули из стандартной библиотеки мы начнём использовать уже в ближайших главах. А одна из глав будет полностью посвящена рассказу о библиотеках: из неё мы подробно узнаем, откуда берутся библиотеки и как их можно использовать.

## Для любопытных

До появления `stack` основным способом установки Haskell была так называемая [Haskell Platform](https://www.haskell.org/platform/). Однако именно `stack`, несмотря на свою молодость (вышел в свет летом 2015 года), является предпочтительным путём в мир Haskell, особенно для новичков. Его настолько полюбили, что последние версии Haskell Platform включают в себя `stack` по умолчанию!

Как вы заметили, имена файлов с исходным кодом начинаются с большой буквы: `app/Main.hs` и `src/Lib.hs`. Строго говоря, это необязательно, можно и с маленькой буквы, однако для гармонии с именем модуля лучше придерживаться общепринятой практики и называть файл модуля по имени самого модуля:

```haskell
app/Main.hs -> module Main ...
src/Lib.hs  -> module Lib ...
```

И ещё. При создании проекта мы могли бы использовать схему `simple` вместо предлагаемой по умолчанию. Для этого проект нужно было создать командой:

```bash
$ stack new real simple
```

где `simple` &mdash; имя схемы проекта. Дело в том, что команда `stack new` может создавать заготовки проектов для разных нужд. Простейшая из заготовок называется `simple`. В этом случае в проекте отсутствует модуль `src/Lib.hs`, а есть лишь `src/Main.hs`:

```bash
.
├── LICENSE
├── Setup.hs
├── real.cabal
├── src
│   └── Main.hs <- Единственный модуль
└── stack.yaml
```

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