Elmは、ウェブブラウザベースのグラフィカルユーザインタフェースを宣言的に作成するためのドメイン固有プログラミング言語である。Elmは純粋関数型言語であり、ユーザビリティ・パフォーマンス・堅牢性を重視して開発されている。静的かつ強力な型検査によって「事実上一切の実行時例外が起こらない」ことを売りにしている。
歴史 Elmは2012年にEvan Czaplickiの修士論文として最初に設計されたElm: Concurrent FRP for Functional GUIs。最初のElmは多くのサンプルコードとそれらをブラウザで簡単に試すことの出来るオンラインエディタとともにリリースされたElm's Online Editor。Evan CzaplickiはElm開発のため2013年にPreziに入社Elm joins Prezi、2016年からはオープンソースエンジニアとしてNoRedInkに所属し、同時にElmソフトウェア財団を立ち上げたNew Adventures for Elm。
最初の実装ではElmコンパイラはHTML・CSS・JavaScriptをターゲットとしていたElm compiler source code。一連のツールはその後も拡張を続けており、現在はREPLElm REPL announcement、パッケージマネージャーElm Package Manager announcement、タイムトラベルデバッガーElm's Time-Traveling Debugger、MacとWindows向けのインストーラーを備えているElm Platform。Elmはまたコミュニティ製ライブラリを提供するエコシステムを持っているElm Packages。
特徴 Elmは小さいながらも表現力豊かな言語の構成要素(if式、let式、case式、匿名関数)を持っているThe Syntax of ElmAbout Elm Elm features。さらに、不変性、静的型付け、HTML・CSS・JavaScriptとの相互運用性を主要な機能として持っている。
不変性 Elmのすべての値はイミュータブルであり、一度作られた値に対して後から変更が加えることはできない。
Elmは永続データ構造を用いてArray・Dict・Setライブラリを実装しているElm Standard Libraries。
静的型 Elmは静的型付けである。すべての定義にはその値を正確に表現する型注釈をつけることができる。型には以下が含まれる。
整数や文字列などのプリミティブ型 リストやタプル・拡張レコードなどの基本的なデータ構造 タグ付きユニオンと呼ばれるカスタム型
Elm は完全な型推論をもサポートしており、コンパイラは型注釈なしに型安全かどうかを判定できる。
モジュールシステム Elmはモジュールシステムを持っており、ユーザーはコードをモジュールと呼ばれる小さな単位に分割することができる。ユーザーは値をインポート・エクスポートすることができ、実装の詳細を他のプログラマが意識する必要のないように隠蔽することができる。モジュールはElmコミュニティライブラリの基礎になっている。
HTML、CSS、JavaScriptとの相互運用 Elmはポートと呼ばれる抽象を用いてJavaScriptと協調することができるPorts。これによってElmとJavaScriptの間でデータのやりとりが可能になる。
Elmはelm/htmlというライブラリによってElmの内部でHTMLやCSSを扱うことができるdocumentation。これはVirtual DOMを使って効率的に更新を行うBlazing Fast Html。
制限 HaskellやPureScriptと違い、Elmは型クラスをサポートしていないため、多くの共通的な処理を抽象化することはできない。たとえば、map、apply、fold、あるいはfilterといった汎用的な関数はない。代わりに、List.map Dict.map のように、それぞれのモジュール名でプレフィックスをつけて使う。
ツール オンラインエディタ(簡単な確認用) elm-lang.org/try ローカルへのインストール Install Elm 学習用リソースとサンプル集 コアライブラリとコミュニティライブラリ
サンプルコード -- 1行コメント
{- 複数行コメント It can span multiple lines.
{- 複数行コメントは {- ネスト -} することができる -}
-- ''greeting'' という値を定義している。型は String と推論される。 greeting = "Hello World!"
-- トップレベルの宣言には型注釈をつけた方が良い hello : String hello = "Hi there."
-- 関数も同じように宣言される。引数は関数名の後ろに書く。 add x y = x + y
-- やはり型注釈をつけたほうが良い hypotenuse : Float -> Float -> Float hypotenuse a b = sqrt (a^2 + b^2)
-- 関数はカリー化されている。ここでは掛け算の中置演算子を 2 で部分適用している。 multiplyBy2 : number -> number multiplyBy2 = (*) 2
-- 条件分岐には if 式を使う absoluteValue : number -> number absoluteValue number = if number < 0 then negate number else number
-- 名前つきのフィールドを保持するにはレコードを使う book : { title : String, author : String, pages : Int } book = { title = "Steppenwolf" , author = "Hesse" , pages = 237
-- `.`でレコードの値にアクセスする title : String title = book.title
-- `.`でのレコードのアクセスは関数として使うことも出来る author : String author = .author book
-- 新しい型を定義するには`type`キーワードを使う -- 次の型は2分木を表している type Tree a = Empty | Node a (Tree a) (Tree a)
-- これらの型はcase式によって分岐することができる depth : Tree a -> Int depth tree = case tree of Empty -> 0
Node value left right -> 1 + max (depth left) (depth right)
脚注
外部リンク