Еще раз повторюсь, что я не силен в функциональном программировании, плохо знаком с математическими концепциями, на которых оно строится и изучению Elm удлелил, пока что, не очень много времени. Я считаю, что лучше бы эту статью написал кто-то другой, более осведомленный, но, таковых не нашлось, а до тех пор, я решил возложить эту ношу на себя, быть может, моя статья поможет кому-то открыть для себя прелести функционального программирования для веб, или по новому взглянуть на, казалось бы привычные вещи. Большинство материалов, представленных в статье взяты из официальной документации и переведены в довольно свободной форме. Всех страждующих, прошу под кат.
Для начала, давайте напишем наше первое приложение на Elm и попробуем разобраться, что же происходит. Не отходя от традиций, пусть это будет наш привет Миру.
import Html exposing (span, text)
import Html.Attributes exposing (class)
main =
span [class "welcome-message"] [text "Hello, World!"]
Первые две строчки подключают модули Html и Html.Attributes, благодаря которым мы можем отображать и изменять HTML-элементы и их атрибуты на странице. Директива exposing позволяет нам использовать указанные в параметрах функции напряму, например вместо
Html.span
мы можем писать просто
span
main это управляющая конструкция, которая управляет нашим приложением, большинству программ, написаных на Elm так или иначе будут содержать эту конструкцию.
Строка
span [class "welcome-message"] [text "Hello, World!"]
Сгенерирует простой HTML-код:<span class="welcome-message">Hello, World!</span>
Но это все не очень интересно, ведь для генерации простого HTML-кода в одну строку нам пришлось написать целых 4 строчки на Elm, пока что не очень впечатляет, но стоит только заглянуть в основные концепции архитектуры языка и все становится на свои места.
Вся логика программ на Elm разделена на 3 понятные и простые части, уже, так или иначе, знакомые многим в веб разработке:
- Model(модель)
- Update(обновление)
- View(представление)
Model(модель)
Я бы охрактеризовал модель, как состояние приложения, что отличается от того, что понимается под моделью в привычном MVC. Если выразить мою мысль более подробно, то Модель в Elm будет содержать в себе все модели в понимании MVC, необходимые в данном состоянии приложению, если таковые есть. При этом Model может быть чем-то намного более простым. Например, в следующем примере, в котором мы сделаем простой счетчик, Model будет простым целым числом(Int).
Update(обновление)
Когда дело касается обновления состояния, в игру вступает update. Здесь все не более сложно, чем с моделью. Update это функция, которая говорит КАК нам нужно изменить состояние приложения(Model)
View(представление)
Преставление это то, как мы хотим отобразить состояние нашего приложения, то есть Model.
В сухом остатке, приложение на Elm работает следующим образом:
Мы получаем запрос из внешнего мира, Используем его для того, чтобы обновить нашу модель, решаем, как хотим отобразить результат. Elm решает, как эффективно отобразить наш HTML.
Читая сухой текст, довольно трудно понять что к чему, поэтому, давайте рассмотрим обещаный пример создания счетчика
module Counter where
import Html exposing (..)
import Html.Attributes exposing (style)
import Html.Events exposing (onClick)
import StartApp
main =
StartApp.start
{ model = 0
, update = update
, view = view
}
-- MODEL
type alias Model = Int
-- UPDATE
type Action = Increment | Decrement
update : Action -> Model -> Model
update action model =
case action of
Increment -> model + 1
Decrement -> model - 1
-- VIEW
view : Signal.Address Action -> Model -> Html
view address model =
div []
[ button [ onClick address Decrement ] [ text "-" ]
, div [ countStyle ] [ text (toString model) ]
, button [ onClick address Increment ] [ text "+" ]
]
countStyle : Attribute
countStyle =
style
[ ("font-size", "20px")
, ("font-family", "monospace")
, ("display", "inline-block")
, ("width", "50px")
, ("text-align", "center")
]
В этом примере добавилась довольно важная концепция — Action(действие). Действия позволяют нам правильно реагировать на запросы полученные из внешнего мира. В данном примере мы определили два типа действий — Increment и Decrement. И, в зависимости от полученного действия принимаем решение, как изменить нашу модель.
Кстати, разработчики предусмотрели онлайн-компилятор, для того, чтобы можно было запустить один из множества доступных примеров, или попробовать написать что-то самостоятельно. Попробуйте запустить этот пример и посмотреть, что получится!
Можно еще долго рассказывать о базовых концепциях данного языка, но я думаю, что те, кому изложенный материал показался хоть чуточку интересным, сами зайдут на официальный сайт и посмотрят все, что называется своими глазами. А еще, я призываю тех, кого не заинтересовало то, что я написал, или не понравился мой стиль изложения, зайти и все же посмотреть на Elm своими глазами. В заключение, я хочу добавить пример кода с официального сайта, который генерирует игру в пинг-понг в браузере, по-моему, изящность и простота этого языка, заслуживают внимания со стороны сообщества elm-lang.org/examples/pong
Комментарии (22)
ShadowsMind
06.07.2015 10:21Хм, elm-compiler написал на Haskell, необычный выбор авторов надо сказать.
roman_kashitsyn
06.07.2015 11:11+4Что необычного в написании компилятора Haskell-подобного языка на Haskell, одном из лучших языков для написания компиляторов?
ShadowsMind
06.07.2015 11:15+1Не в курсе про то, что Haskell лучший язык для написания компиляторов. Мне казалось, что он больше академический, чем для практических нужд. Пожалуй пересмотрю свое мнение по поводу Haskell'а
roman_kashitsyn
06.07.2015 11:33+3Мне казалось, что он больше академический, чем для практических нужд
Это популярное заблуждение. При должном опыте можно делать очень классные практичные вещи на Haskell. Порог входа достаточно высок, но изучение Haskell однозначно изменит подход к программированию на других языках.
hlogeon Автор
06.07.2015 11:46+2Elm хорошее подтверждение Вашему заблуждению. И еще можно посмотреть на github реализации различных, вполне практичных вещей на Haskell. У меня часто возникает чувство: «Черт, почему я еще не пишу на Haskell»
dborovikov
06.07.2015 11:31Скажите, а в чем основное отличие Elm от PureScript?
hlogeon Автор
06.07.2015 12:03Отличий довольно много, что понимать под ОСНОВНЫМ, я не понимаю. Можете ознакомится вот с этой статьей
www.slant.co/topics/1515/compare/~elm_vs_purescript_vs_haste
dotneter
06.07.2015 12:05Elm проще. Нет тайпклассов, соответственно нет развесистой библиотеки этих же тайпклассов. Язык заточен под одну парадигму. PureScript более универсальный например при желании можно использовать тот же jQuery.
hlogeon Автор
06.07.2015 12:18Разработчики учли важность возможности использования ELM с существующими библиотеками и сделали вот это:
elm-lang.org/guide/interopdotneter
06.07.2015 12:43Да, общаться можно через порты, как вы себе представляете через них использовать jQuery?
hlogeon Автор
06.07.2015 14:29как вы себе представляете через них использовать jQuery?
Jquery действительно никак, но
а) Нет видимых причин использовать jQuery с Elm
б) Если всеже возникла такая необходимость, то любой функционал можно написать на elm, благо, на нём это займет совсем немного времени, и принести пользу сообществу, опубликовав пакет.
в) я не вижу никакого ограничение на использование чистого JS в elm-проекте
Под в) я имею ввиду примерно такую конструкцию во View
script [type "text-javascript"] [src "myAwesomeScript.js"]
potan
08.07.2015 14:31Очень интересный язык.
Только меня в нем разочаловал запрет на рекурсивную зависимость сигналов.vintage
08.07.2015 19:38Зачем вам рекурсивные сигналы?
potan
08.07.2015 19:52Хотел демонстранцию работы схемы написать. Провода из схемы хорошо описывались бы сигналами, если бы их можно было зациклить.
А вообще глобальное состояние с помощью fold хранить не всегда бывает удобно, особенно если к нему нужен доступ из многих мест. В зацикленных сигналах хранить было бы проще.
ConstSe
«Меня сразу вдохновила та простата» — исправьте. Думал в личку написать, но пусть уж другие тоже поржут над опечаткой. :)
hlogeon Автор
Спасибо. Хорошо, что я не пишу на медицинские темы.
Alexeyco
А может быть, наоборот, зря?