Elm

Elm 0.19で、Elmに速攻入門。

バージョン1.0が見えてきたElmが良さげなのでお試し。

バージョン0.19がリリースされ、その先にバージョン1.0が見えてきたというElm。
今勢いのある言語 Elm』という勢いあるエントリーに乗っかって、入門してみた次第。インストールやコマンド体系などが今までのバージョンと違うようだったので、備忘録をここに記す。

入門者のスペック

Haskellは以前に2冊くらい本を読んだ程度。Scalaはベターjavaとして実案件で活用。普段はPythonを使う。趣味は、同じくバージョン1.0出るか出たよが話題となる、NimとJulia。以前、フロントエンドも自前で書いた時に辛かったので、Immutableな言語で仮想DOMを操作してフロントエンドを完結できるならいいねと、Elmに期待(加えて、Mutableな処理をガリガリ書く必要があるならば、Nimでwebassemblyといきたいところ)。

時短に役立つ『Elm入門ハンズオン』

https://gitpitch.com/ababup1192/elm-handson1/master?grs=github&t=sky

カーソルキーを上下左右に動かしながらElm入門ができる素晴らしい資料。
本ハンズオンは、Elm0.18対応と思われるが、Elm0.19でもほぼほぼ動いた。
ブラウザ上の動作に特化したElmは、HaskellやScalaやNimに比べるとシンプルな言語仕様と思われ、言語仕様を軽く眺めDOMをいじってみるまでは、1時間ほどで行えた。

Elm 0.19に速攻入門記

(当座の)インストール方法

リリースされたばかりのElm0.19は、npm経由のインストールが推奨されていない(できない場合がある)模様。そのため、以下の指示に従う。

https://guide.elm-lang.org/install.html

いずれのプラットホームも簡単に入りそう。
Linux(debian等)の場合:

Elm 0.19 just came out, so the npm installer is not ready yet. In the meantime, you can download it manually like this:

wget "https://github.com/elm/compiler/releases/download/0.19.0/binaries-for-linux.tar.gz"
tar xzf binaries-for-linux.tar.gz
sudo mv elm /usr/local/bin/

ということで、elmのお試しだけならnode.js./npmは必要ない(mvにsudoが必要なのは、Windows 10上のWSL debianなどの場合)。

まずは、elm init

elm0.19では、作業ディレクトリにて、

elm init

とするのがお作法な模様。Scalaでいうsbtのようなものか。

kmry:/mnt/c/dev/elm1$ elm init
Hello! Elm projects always start with an elm.json file. I can create them!

Now you may be wondering, what will be in this file? How do I add Elm files to
my project? How do I see it in the browser? How will my code grow? Do I need
more directories? What about tests? Etc.

Check out <https://elm-lang.org/0.19.0/init> for all the answers!

Knowing all that, would you like me to create an elm.json file now? [Y/n]: Y
Okay, I created it. Now read that link!

kmry:/mnt/c/dev/elm1$ tree .
.
├── elm.json
├── elm-stuff
│   └── 0.19.0
│       ├── Elm_Repl.elmi
│       ├── Elm_Repl.elmo
│       └── summary.dat
└── src

kmry:/mnt/c/dev/elm1$ cat elm.json
{
    "type": "application",
    "source-directories": [
        "src"
    ],
    "elm-version": "0.19.0",
    "dependencies": {
        "direct": {
            "elm/browser": "1.0.0",
            "elm/core": "1.0.0",
            "elm/html": "1.0.0"
        },
        "indirect": {
            "elm/json": "1.0.0",
            "elm/time": "1.0.0",
            "elm/url": "1.0.0",
            "elm/virtual-dom": "1.0.0"
        }
    },
    "test-dependencies": {
        "direct": {},
        "indirect": {}
    }
}


...だいたい雰囲気はわかるだろう。elm.jsonに必要なパッケージを記していくものらしい。

次いで、elm reactor

開発用のwebサーバー(reactor)を立ち上げながら、エディタでelmコードを書いていくというのが流儀らしい。エラーが出た場合もブラウザ上で確認する。

kmry:/mnt/c/dev/elm1$ elm reactor
Go to <http://localhost:8000> to see your project dashboard.

http://localhost:8000にアクセスしてみる:

localhost.PNG

ということで、src配下にコードを書いていくらしい(自分の場合、VS-codeにelm拡張を入れた。)。
hello worldも、仮想DOM経由で行うのが流儀だろう。
helloとworldを宣言し、mainでつなげる:

hello.elm
import Html exposing (..) --(h1, div, p, text)

hello =  h1 [] [text "hello"]
world =  p [] [text "world."]

main =
  div [] [ hello , world]

import Html exposing (..)することで、h1, div, pなどの仮想DOM要素一式と、何もタグで囲まれていない文字列Html a を作るtextとが使用可能となる。

実行結果:
hello.PNG

次いで、関数型言語らしく(?)、関数を使ってみよう。

nobi1.elm
import Html exposing (..)

-- 識別名称をエイリアス宣言
type alias Name = String
type alias Age = Int
type alias Person = { name : Name, age : Age }

-- 代入用変数(≒オブジェクトの生成)
takeshi = { name = "剛田武", age = "10" }
nobi = { name = "野比のび太", age = "9" }

--表示用DOMの生成

get_text x s = text (x ++ s)
name_age x =
    div [] [
        h1 [] [get_text x.name  ":"] , 
        h2 [] [get_text x.age  "歳"] ,
        hr [] []
    ]

--mainを介し、仮想DOMを描画
main =
    div [] [
        name_age(takeshi) , 
        name_age(nobi)
    ]

実行結果:

nobi.PNG

『hr [] []』ってなんのことだろうとか若干気になるが、ともあれ,変数・関数を駆使し、ブラウザのDOMに反映できていることはわかるだろう。

ここから先は、ラジオボタンやプルダウンなどで、スネ夫やしずかちゃんを登場させるところは略する。ていうか、ボタンを用意するからには、サーバ側とデータをやり取りしたいよねと思ったあたりで、1時間経過したので、そのあたりの入門は今後の課題とする。

おまけ(Haskellになじみがない方向け):elm repl

node.jsが入っている環境では、elm replとタイプすることで、nodejsを活用したREPL環境でHaskell風なElmの関数型言語テイストな記述をお試しできる。
Haskell風な体系では、f(x)はf x とも記せる:

> f x = x^2
<function> : number -> number
> f 5
25 : number
> f (3)
9 : number

> g (x) = x*2
<function> : number -> number
> g 4
8 : number
> g (2)
4 : number

このかっこが省略できる記法に慣れておくと、関数渡しの場合などに可読性が向上すると思っている。
例えば、

> f (g 2)
16 : number

の場合、カッコ内のg 2を先に評価し、f(結果)を得ると読める。
ElmをHakellライクな言語として入門する場合には、REPLを使うのが良さそう。

> h x = if x > 4 then True else False
<function> : number -> Bool
> h (5)
True : Bool
> h (f 5)
True : Bool
> h (f 1)
False : Bool

0.19で、ちょっと困ったこと。

整数型を文字列型に変換する、toStringが使えなかった。モジュール体系が変わったからなのかな???

まぁ、Elmで仮想DOMな雰囲気は体験できたから良しとする。