easimonenko Evgeny Simonenko

Инструменты разработчика на языке Elm

08 Feb 2018 |  Tutorial  |  Elm   Brunch   Atom   Functional Programming   Frontend   Web Development  

С момента публикации статьи Инструменты разработчика на языке Elm прошло полтора года. За это время в инструментарии для языка разработки веб-интерфейсов Elm произошли многочисленные изменения: появилась более удобная система сборки с возможностью генерации нового проекта; для редактора Atom набор дополнений в некоторых отношениях теперь лучше, чем для популярного тогда среди разработчиков на Elm редактора LightTable; заработал инспектор состояния приложения. Давайте пройдёмся по этому набору на простом примере.

Инструменты разработчика на языке Elm: обложка

Базовые средства Elm

Elm можно установить как пакет NPM:

npm install -g elm

Есть и другие способы установить Elm. Они описываются в официальном руководстве.

Проверим версию только что установленного Elm:

elm --version
0.18.0

elm является обёрткой для вызова отдельных утилит:

Управление кодом на Elm с помощью Brunch

Одним из удобнейших средств управления кодом на Elm представляется Brunch. Устанавливается Brunch как пакет NPM:

npm install -g brunch

Проверим версию только что установленного Brunch:

brunch --version
2.10.12

Вызовем Brunch для генерации кода нашего примера проекта на Elm:

brunch new --skeleton MattCheely/elm-brunch-skeleton demo-application

После генерации кода Brunch также сразу загрузит все необходимые NPM- и Elm-пакеты.

Рассмотрим сгенерированное дерево каталогов:

Уже сейчас мы можем собрать наш проект:

cd demo-application
npm build

После сборки проекта появится также папка public, в которой разместятся все части нашего веб-приложения.

Давайте запустим приложение в режиме отладки:

npm start

Откроем в браузере ссылку http://localhost:3333/ и полюбуемся на прекрасное веб-приложение:

Пример приложения на Elm

В правом нижнем углу находится интерфейс инспектора состояния приложения. Щёлкнем на нём. Сейчас счётчик value имеет значение 0:

Начальное состояние приложения

Пощёлкаем на кнопках +1 и -1 и понаблюдаем как меняется состояние:

Наблюдение за изменением состояния приложения

Мы можем вернуться к любому предыдущему состоянию:

Просмотр предыдущего состояния приложения

И даже вернуться к последнему, просто нажав на кнопку Resume.

Неискушённому зрителю читателю наверное будет интересно также узнать, как устроено приложение на Elm, но сначала давайте настроим редактор, чтобы изучать исходный код приложения было приятней и удобней.

Настройка Atom для работы с Elm

Поддержка разработки на Elm есть для многих редакторов, однако здесь мы рассмотрим только один, Atom, так как на взгляд автора для него существует самый функциональный набор дополнений, облегчающий работу с Elm. Будем исходить из того, что Atom у вас уже установлен (хотя, подскажу откуда его можно загрузить: https://github.com/atom/atom/releases).

Перво наперво установим дополнение language-elm:

apm install language-elm

Это дополнение предоставит базовую поддержку Elm, такую как синтаксическая подсветка кода.

Для поддержки переходов к определениям и всплывающим подсказкам с типами выражений установим пакет atom-ide-ui.

apm install atom-ide-ui

Для поддержки автодополнения поставим autocomplete-plus:

apm install autocomplete-plus

Если используете сокращённый набор кода, поставьте snippets:

apm install snippets

Наконец мы готовы установить Elmjutsu:

apm install elmjutsu

Теперь мы можем открыть наш проект в Atom:

Код Elm в Atom

Для руководства по настройке и функциям Elmjutsu обязательно зайдите на страничку этого дополнения, и не забудьте задать все необходимые параметры в Atom.

Дополнительный, но важный инструментарий

Пожалуй самый важный инструмент из дополнительных это elm-format. С помощью этой утилиты можно приводить внешний вид программы к стандартному (общепринятому) виду. Установим его:

npm install -g elm-format

Также установим соответствующее дополнение для Atom elm-format:

apm install elm-format

Благодаря этому дополнению, каждый раз, как мы будем сохранять наш код, elm-format будет его форматировать. Если в коде будет синтаксическая ошибка, то утилита её обнаружит, и мы об этом узнаем, хотя, для выяснения наличия ошибок всё же лучше использовать компилятор. А в этом нам будет помогать дополнение для Atom linter-elm-make.

Поставим его:

apm install linter
apm install linter-elm-make

Не забудьте также зайти в настройки этих дополнений и задать все необходимые параметры.

Дополнение elm-lens показывает прямо в коде для функций и типов экспонируются ли они или являются локальными, а также сколько раз на них ссылаются. Для установки дополнения просто вызовите:

apm install elm-lens

Для поддержки REPL в Atom можно установить дополнение elm-instant:

apm install elm-instant

Если вы хотите работать с терминалом прямо в Atom, рекомендую установить дополнение platformio-ide-terminal:

apm install platformio-ide-terminal

Поэкспериментируем

Для начала откроем окно терминала в Atom, нажав кнопку + в нижней части окна, и запустим слежение за нашим кодом на Elm:

npm start

Код на Elm в Atom с запущенным слежением в терминале

Давайте внесём ошибку в код:

Код на Elm в Atom с ошибкой

Можно заметить, что во-первых ошибка была обнаружена без ручного запуска компиляции, во-вторых были предложены варианты для исправления ошибки.

Для непосвящённых

Как и обещал, немного расскажу, как устроен код приложения на Elm. Давайте взглянем на тот исходный код, который нам сгенерировал Brunch:

module Main exposing (main)

import Html exposing (Html, text, div, button)
import Html.Attributes exposing (class)
import Html.Events exposing (onClick)


main : Program Never Model Msg
main =
    Html.beginnerProgram
        { model = initalModel
        , update = update
        , view = view
        }



-- Model


type alias Model =
    { value : Int
    }


initalModel : Model
initalModel =
    { value = 0
    }



-- Update


type Msg
    = Increment
    | Decrement


update : Msg -> Model -> Model
update msg model =
    case msg of
        Increment ->
            { model | value = model.value + 1 }

        Decrement ->
            { model | value = model.value - 1 }



-- View


view : Model -> Html Msg
view model =
    div []
        [ div [ class "counter" ]
            [ text (toString model.value) ]
        , div [ class "controls" ]
            [ button [ onClick Increment ] [ text "+1" ]
            , button [ onClick Decrement ] [ text "-1" ]
            ]
        ]

Приложение на Elm оформляется как модуль Main, экспонирующий функцию main. Это мы видим в первой строке кода. Далее идёт импорт модулей. Некоторые модули импортируются по умолчанию, но модули Html, Html.Attributes и Html.Events нужно импортировать. Здесь они импортируются с экспонированием отдельных функций и типов. Это делается, чтобы не квалифицировать имя модуля, например, вместо Html.Attributes.class будем писать просто class.

Ниже объявляется и определяется функция main. В объявлении задаётся её тип. Тип функции указывается после символа :, определение происходит после знака =. Как увидим ниже, указание имён параметров и их типов осуществляется раздельно. Elm поддерживает вывод типов, однако для функций верхнего уровня хорошим тоном считается ручное указание типа.

В нашем случае функция main вызывает функцию Html.beginnerProgram, которая получает на вход структуру с тремя полями: model, update, view. Эта функция запустит цикл обработки сообщений. Параметр model получает начальное состояние приложения, которое задано в функции initialModel. Функция update вызывается всякий раз, когда происходит какое-то событие и передаётся соответствующее сообщение. После обработки сообщения вызывается функция view, занимающаяся формированием нового дерева DOM.

Далее определяется тип Model, точнее синоним типа структуры, состоящей из поля value типа Int. Тип Int, как нетрудно догадаться, представляет целые числа.

Как уже было сказано, функция initialModel возвращает начальное значение состояния, которое содержит одно поле value со значением 0. Типом состояния может быть любой тип, не только структура.

Далее определяется тип сообщения Msg. Это тип-перечисление с двумя возможными значениями: Increment и Decrement.

Функция update получает на вход сообщение и состояние приложения. Обычно код этой функции включает в себя оператор сопоставления с образцом case .. of ... Здесь происходит изменение состояния в зависимости от пришедшего сообщения: значение поля value либо увеличивается на 1, либо уменьшается на 1.

Наконец, функция view принимает состояние приложения и формирует с помощью функций модулей Html, Html.Attributes и Html.Events требуемое дерево DOM.

Установка дополнительных пакетов Elm

И последнее, но не менее важное: чтобы установить дополнительные пакеты Elm, нужно вызвать команду elm-package. Например, установим пакет elm-community/list-extra:

elm package install elm-community/list-extra

Обратите внимание, что идентификатор пакета состоит из двух частей, то есть не просто list-extra, а elm-community/list-extra.

С этой командой связан файл проекта elm-package.json. В него записываются названия и версии устанавливаемых пакетов в разделе dependencies. Например, сгенерированный Brunch файл elm-package.json выглядит так:

{
  "version": "1.0.0",
  "summary": "helpful summary of your project, less than 80 characters",
  "repository": "https://github.com/user/project.git",
  "license": "BSD3",
  "source-directories": ["app/elm"],
  "exposed-modules": [],
  "dependencies": {
    "elm-lang/core": "5.0.0 <= v < 6.0.0",
    "elm-lang/dom": "1.1.1 <= v < 2.0.0",
    "elm-lang/html": "2.0.0 <= v < 3.0.0"
  },
  "elm-version": "0.18.0 <= v < 0.19.0"
}

Репозиторий пакетов можно просматривать здесь http://package.elm-lang.org/.

Что дальше

Пожалуй лучший источник информации об Elm это его родной сайт:

Вероятно стоит также перечитать статью 2016 года Инструменты разработчика на языке Elm.

Опрос

Как и в прошлый раз проводится опрос, но он немного переориентирован, если можно так сказать. Ведь в прошлый раз автор приглашал к опросу только тех, кто уже программирует на функциональных языках, теперь же аудитория расширяется до всех, кто разрабатывает веб-приложения.

Подведу также итоги прошлого опроса. Итак, на вопрос “Если Вы программируете на функциональных языках, то каково Ваше мнение об Elm” расклад был получен такой:

Проголосовало 170, воздержалось 147. Прочитало статью 13,9k, добавило в закладки 51.

Интересно, наверное, будет сравнить с результатами голосования, зафиксированными автором через неделю после публикации той статьи:

Проголосовало 99, воздержалось 76. Прочитало статью 5,5k, добавило в закладки 41.

Заметен рост благосклонности к Elm, существенно уменьшилось число тех, кто считал, что Elm не нужен, также заметно выросло число тех, кто на нём уже программирует. При этом также увеличилось число тех, кто считает язык годным, но писать на нём не собирается.

Сообщество

С момента публикации прошлой версии статьи (30 мая 2016) существует рускоязычное сообщество во Вконтакте https://vk.com/elm_lang_ru. Число участников сообщества на момент написания этой статьи 179. Присоединяйтесь и активно участвуйте!

Ссылки

Дополнения

8 февраля 2018. Итоги опроса за чуть больше недели с момента публикации:

  1. не нужен в принципе: 28.2%
  2. годный, но на нём не пишу: 26%
  3. в первый раз вижу, но выглядит годным: 17.3%
  4. сыроват для серьёзной разработки: 17.3%
  5. годный, я на нём уже программирую: 10.8%

Проголосовало 46, воздержалось 10. В закладки добавили 28, просмотрели 2,9k.

Из показателей видно, что вторая статья вызвала существенно меньший интерес, чем первая. Чем это вызвано, не ясно. Вероятно, что Elm уже не выглядит новинкой, и при этом не пользуется ажиотажным спросом.

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

В отличие от первой статьи эта статья на рост сообщества во Вконтакте никак не повлияла.

Общее ощущение, что интерес к Elm спал, и рост сообщества стабилизировался. Митапы, по крайней мере в Санкт-Петербурге, не проводятся. За полтора года встречалась только одна вакансия разработчика на Elm.

15 мая 2018. Итоги опроса по прошествии трёх с половиной месяцев:

  1. не нужен в принципе: 26.9%
  2. годный, но на нём не пишу: 25%
  3. в первый раз вижу, но выглядит годным: 19.2%
  4. сыроват для серьёзной разработки: 15.3%
  5. годный, я на нём уже программирую: 13.4%

Проголосовало 52, воздержалось 13. В закладки добавили 30, просмотрели 3,8k.

Примечание

Эта статья в немного другой редакции была первоначально опубликована на Habrahabr (29 января 2018): https://habrahabr.ru/post/347730/

(c) Симоненко Евгений, 2018