Elm 0.14に際して思ったこと

Elm 0.14がリリースされました。

今回のリリースには後方互換性が保たれない、大きな変更が含まれてます。 これによりHaskellとの違いが大きくなったため、もはや「Haskellベースの言語」という表現はふさわしくないかも知れません。

ところで、このような大きな変更は、メジャーな言語では、Rubyが2007年に1.9.0で、Pythonが2008年に3.0で行っていますが、その評価は対照的です。 Rubyでは1.9.0のことはもはや話題にもなりませんが、 Pythonでは未だに「2.xと3.xのどちらを使って開発すべきか」「2.x系の開発を続行するべきか」のような記事が書かれます。

私はこんな記事こんな記事を書くほどPython好きだったので、Pythonが移行の失敗例のように語られるのは悲しいです。

両者の明暗が別れた理由としてよく言われるのは、

  • Rubyは本格的な普及の前に大きな変更をした。Pythonは2008年当時すでに主要なLinux内部やGoogle App Engineで使われ、かなり普及していた。
  • RubyはいわゆるWEB系で使われていたためライフサイクルが短かった。PythonはWEB系以外でも使われており、簡単に移行できなかった。*1

などがありますが、個人的には、

  • RubyではRuby on Railsを使うユーザーが多く、Ruby on Railsが旧バージョンを切り捨てれば、ユーザーも新バージョンに映らざるをえない
  • Rubyの方が元々アグレッシブで非互換性バッチコイなのユーザーが多い?(多かった?)。

のような理由もあると思います。

いずれにせよ、Elmは普及にはまだほど遠い段階なので(そもそも1.0以前ですし)、0.14での変更はElmの進化に良い影響を与えることと思います。

*1:私自身、仕事では未だに時々RHEL5.x向け製品のメンテナンスをしてますし。RHEL5.xのPythonは2.4系です。

Elmはそもそも誰が作ってるの?【Elmアドベントカレンダー2014 7日目】

これはElm Advent Calendar 2014の7日目です。 社内勉強会でElmを紹介したら、

ボス「Who is creating Elm language ?」
私 「えっ?」
ボス「Elmって誰が作ってるの?」

というわけで調べてみました。

メイン開発者はPreziの中の人

Elmコンパイラに一番多くコミットしているのはEvan CzaplickiさんWikipediaによると、もともとElmはCzaplickiさんが2012年に論文(大学の卒業論文か何か?)のために始めたプロジェクトだったそうです。

CzaplickiさんはPrezi2013年に入社しフルタイムでElmの仕事をしているそうです。elm-compilerにはCzaplickiさん以外にもPrezi社員が多いようです。

Preziはプレゼン作成用WEBサービスの会社

Prezi - YouTube

マインドマップベースのプレゼンがとってもオサレです。上手くハマればスゴいプレゼンができそうですね!

パワポやGoogleDrive等のスライド式プレゼンに慣れた身からは「使いこなせるかな?」とちょっと不安にもなりますが。

しかし、今の所、PreziのWEBツール自体は主にFlushで作られているようです。

結論

次の勉強会では、Elmの紹介プレゼンをPreziを使って作るのがいいかもしれません。

あとがき

おかげさまでElm Advent Calendar 2014はまだまだ空きがあります。ふるってご参加ください。

Elmで青春のフラクタルを描画する【Elmアドベントカレンダー2014 6日目】

これはElm Advent Calendar 2014の6日目です。

Elmの優れた点と言えば、

  1. Haskellベースの静的型関数型言語
  2. Functional Reactive Programming
  3. 強力なレイアウト機能

などがまず挙がるでしょう。しかし、

  1. 図形描画ライブラリ

も、実はElmの長所の一つなのです。

Elmの図形描画機能

まずは 公式サイトの例をご覧ください。

HTML5Canvasは、JavaScriptによる手続き型の実装を前提にしていたので、コマ毎にclearRectで消去したり、save/restoreで状態を管理したりする必要がありました。プログラマーはともかく、「学校で習った図形を書いてみよう」と言う場合にはやや非直感的です。

一方Elmでは更新処理自体はElmがやってくれます。 また、図形はFormという「図形そのもの」を表す型として、 図形の移動や拡大縮小はmove scaleといった関数として、自然に表現できます。

なお、注意点とがあり、collage w h forms でw×hのキャンバスを作ったとき、原点はキャンバスの中心で、Xが大きくなるほど右、Yが大きくなるほど上の座標です。つまり、数学と同じ座標なのです。

フラクタルを書いてみる

図形が描ける、ならば初めにフラクタルを描くものと相場は決まっています。再帰呼出し&縮小+移動で、シェルピンスキーのギャスケットを描画してみました!

Sierpinski gasket with Elm

n = 0では単なる三角形を、n > 0では自分自身の縮小コピー×3を描画しています。

なお、Elmでは小さすぎる図形(1ピクセル未満?)は描画してくれないらしく、上の例で再帰が深すぎると何も表示されなくなりました。

自分語り&妄想:Elmは未来の十進BASIC

フラクタルを書いていると、十年前私がまだ紅顔の少年だった頃を思い出します。

私がプログラマーになったのは図書館から↓の本を借りたのがきっかけでした。

当時は悪名高いMicrosoft Visual Basicがボロクソに言われつつも全盛の時代でしたが、十進BASICVBとは全く別の"Full Basic"という規格に沿った教育用BASIC環境でした。

教育用だけあって

と、初心者用の機能が充実しているだけではなく、

  • 数値は10進小数がデフォルト(2進数モードもある)
  • 10進1000桁モード(数値型が小数点以下1000桁まで格納可能になる)
  • 有理数モード
  • 複素数モード
  • 強力な図形描画機能
    • function文とは別に、図形を定義するpicture文がある
    • scale, rotate, shift, 任意のアフィン変換, それらの合成変換
  • グラフ描画用関数
  • 図形関連の豊富なExample(含シェルピンスキーのギャスケット)

等など、数学用の機能がとても充実していました。

言うまでもなく、構造化プログラミングにも対応しており、良いプログラミングを教われなくなったり完膚なきまでに壊れることもありませんでした。

さすがに今では、プログラマー志望の高校生にはPythonあたりを薦めます。 でも、数学者・科学者志望だけどプログラミングの素養を身につけたい高校生ならば、今でも10進BASICを薦めたいと思います。(高校生の知り合いはいないけど)。

一方Elmですが、Playground、デバッガ、図形ライブラリなどは既にかなりの充実度です。 このまま発展すれば21世紀版・十進BASIC的な地位に着けるのではないか? と、ガスケットを書いていて思いました。

あとがき

おかげさまでElm Advent Calendar 2014は今のところ途切れず続いていますが、まだまだ空きがあります。ふるってご参加ください。

フラクタルで描く 魅惑的な画像の世界

フラクタルで描く 魅惑的な画像の世界

ElmとHaskellの6つの非互換性【Elmアドベントカレンダー2014 3日目】

これはElm Advent Calendar 2014の3日目です。

f:id:doloopwhile:20141204015840p:plain

ElmはHaskellベースの言語なので、Haskellの記事や入門書もElmの学習に使えます。しかし、実はElmにはチョコチョコHaskellと違うところがあって互換性はありません。

相違点をElm公式サイトLearnSyntaxFAQから抜粋して解説します。

1. Elmは遅延評価ではありません

Haskellは遅延評価なのでリスト処理の効率が良いのがウリでした。 JavaScriptにもジェネレータという形で遅延評価の思想が取り入れられています。

しかし、Elmのリストや辞書等などは遅延評価ではありません。

Elmはクライアントサイドの言語なので、遅延評価があまり役立たないこと、 SignalJavaScriptのジェネレータのような機能を持っているためのようです。

2. Elmにモナドはありません

Signalがあるので、IOモナドは不要です。それどころかMaybeモナドもListモナドもありません。したがって、do文もありません。

なお、Maybeは標準ライブラリにMaybeパッケージがあり、JavaScriptnullを使うようなコードを安全に書けます。

でも、やっぱりdo文はあった方がいいと私は思うことがあります・・・。caseを5段階ぐらいネストしたりすると。

まぁ「モナド圏論に基づいています*1」という説明が「Haskellってモナドが難しいんでしょ?」という誤解を生むことがないからいいのかな?

3. 関数関連の演算子が違う

Elm Haskell 意味 同値なJavaScript
f x <| g y z f x $ g y z (f x (g y z)) f(x, g(y, z))
g y z |> f x なし
(f << g) x (f . g) x (f (g x)) f(g(x))
(g >> f) x なし

$.がそれぞれ<|<<に変わっています。そして引数の順番を逆にした>|>>が加わっています。

4. :::の意味が逆

Elm Haskell
norm : Float -> Float -> Float
norm x y = sqrt (x * x + y * y)
norm :: Float -> Float -> Float
norm x y = sqrt (x * x + y * y)
1 :: 2 :: alist == [1, 2] ++ alist
1 : 2 : alist == [1, 2] ++ alist

これは型アノテーションの方がリストへの追加よりも頻繁に使うからです。

5. foldl系関数の引数の順序が逆

List.foldr, List.foldl はリストの要素に次々に関数を適用する関数です。 データ構造毎にDict.foldlSet.foldlといった変種もあります。他言語ではreduceinjectという名前で提供されていることがあります。

// elm
v = List.foldr (+) 0 [1,2,3]

// 同等なJS
var list = [1, 2, 3];
var v = 0;
for (var i = 0; i < list.length; i++) {
  v = v + list[i];
}

微妙な違いですがElmではList.foldlが受け取る関数の引数の順序をあえてHaskellと逆にしてあります。

Elm Haskell
List.foldl : (a -> b -> b) -> b -> [a] -> b List.foldl : (b -> a -> b) -> b -> [a] -> b
List.foldr : (a -> b -> b) -> b -> [a] -> b List.foldr : (a -> b -> b) -> b -> [a] -> b

これは、Elmでは標準ライブラリを「データ構造はいつも最後の引数」というルールで設計しているのに関係しています。

たしかに、HaskellのようにList.foldl : (b -> a -> b) -> b -> [a] -> bであったとすると、foldrにはそのまま使えるのにfoldlには使えない関数が出てきて困る気がしますが・・・私にはよく分かりませんでした。

公式サイトのLibrary Design Guidelinesにその点が書いてあるのですが、例がおかしい(間違っている?古い?)気がします。

6. 他にも色々なものがありません。

  • do文以外のモナド関連の構文や演算子
  • where文。代わりにletを使う
  • (+1) のような記法。代わりに((+) 1)と書く
  • ライブラリ

こんなに違って大丈夫?

Haskellは元もと演算子が多い(多すぎる?)言語なので、ElmではSignalが入って互換性がなくなるなら演算子も整理したいと言うことなのでしょう。

ただ「HaskellのライブラリがElmに流用できない」という懸念をもつ方もいらっしゃると思います。私も不安です。

しかし、Haskellは主にサーバーサイドやコンパイラなどに使われ、Elmはクライアントサイドのための言語なので、「ブラウザ上で動くコンパイラを作りたい」というのでもなければ、HaskellのライブラリをElmに流用する機会は実は無いのかもしれません。

あとがき

更新が24時を過ぎてしまいました。

Elm Advent Calendar 2014にはまだ空きがあります。ふるってご参加ください。

すごいHaskellたのしく学ぼう!

すごいHaskellたのしく学ぼう!

*1:確かにモナドは圏論にルーツがありますが、 「『変数』はデカルトにルーツがあります」「正規表現はオートマトン理論に基づいています」「while文を使用することで原始計算可能な関数だけでなく真に計算可能な関数を作成することが可能になります」ってあえて説明したりしないでしょう?「モナドは圏論(ry」が使われる背景には、数学という虎の威を借りてHaskellを高尚に見せようとする心理があるように私には思えます。

ソースに一行追加するだけで実行時にバイナリをバルスできるモジュールを書いた

バズーカが弾切れ、絶対絶命のピンチ、メガネの小悪党がmain関数を実行する前に実行ファイルを削除したいというのはよくあることです。

使用例

たとえばこういうコードに・・・

// get.go
package main

func main() {
   println("ハハハハハ!飛行石を手に入れたぞー!!")
}

importをくわえるだけで・・・

// get.go
package main

import (
  _ "github.com/doloopwhile/go-balse"
)

func main() {
   println("ハハハハハ!飛行石を手に入れたぞー!!")
}

たったこれだけでバルスします!

$ go build get.go
$ ./get
panic: _人人人人人_
      > バルス!<
        ̄Y^Y^ Y^Y^ ̄

goroutine 16 [running]:
runtime.panic(0x44cc20, 0xc208000120)
    /usr/local/go/src/pkg/runtime/panic.c:279 +0xf5
github.com/doloopwhile/go-balse.init·1()
    /home/kenjiomoto/gocode/src/github.com/doloopwhile/go-balse/balse.go:9 +0x87
github.com/doloopwhile/go-balse.init()
    /home/kenjiomoto/gocode/src/github.com/doloopwhile/go-balse/balse.go:10 +0x4b
main.init()
    /home/kenjiomoto/Downloads/get.go:10 +0x46

goroutine 17 [runnable]:
runtime.MHeap_Scavenger()
    /usr/local/go/src/pkg/runtime/mheap.c:507
runtime.goexit()
    /usr/local/go/src/pkg/runtime/proc.c:1445

goroutine 18 [runnable]:
bgsweep()
    /usr/local/go/src/pkg/runtime/mgc0.c:1976
runtime.goexit()
    /usr/local/go/src/pkg/runtime/proc.c:1445

goroutine 19 [runnable]:
runfinq()
    /usr/local/go/src/pkg/runtime/mgc0.c:2606
runtime.goexit()
    /usr/local/go/src/pkg/runtime/proc.c:1445

$ ./get
bash: ./get: そのようなファイルやディレクトリはありません

doloopwhile/go-balse

あとがき

最初は「importするだけでカレントディレクトリのファイルを全て削除」という仕様にしたところ、うっかり「README.mdがー!!README.mdがー!!」となってしまったので、実行ファイルを削除するだけのオトナシイ仕様にしました。

「ソースに一行追加するだけで・・・」は本来もっと真面目な目的で利用できるものです。

ElmのインストールとHelloWorldのコンパイル【Elmアドベントカレンダー2014 2日目】

ElmはPlaygroundで簡単にコードを試せますが、最終的にはelmコマンドでコンパイルする必要があります。

0. バイナリをインストール

MacとWindowは、公式サイトのInstallから、 バイナリをダウンロードできます。

しかし、LinuxではHaskell Platformを使ってソースからインストールしなければなりません。

1. Haskell Platformのインストール

Haskell Platformapt-getなどでインストールできますが、古い場合があるので新しくインストールした方が良いかもしれません.

cd /
curl -L https://www.haskell.org/platform/download/2014.2.0.0/haskell-platform-2014.2.0.0-unknown-linux-x86_64.tar.gz | sudo tar xvzf -
sudo /usr/local/haskell/ghc-7.8.3-x86_64/bin/activate-hs

2. cabalのアップデートとElmのインストール

cabal update
cabal install cabal-install
cabal install -j Elm-0.13 elm-repl-0.3 elm-reactor-0.1 elm-get-0.1.3

echo 'export PATH=$PATH:~/.cabal/bin' >> ~/.bashrc

3. Hello Worldコンパイル

cd 【適当なディレクトリ】
echo 'main = plainText "hello"' > hello.elm
elm hello.elm
firefox build/hello.html

Elmとはどんな言語か?その7つの特徴【Elmアドベントカレンダー2014 1日目】

f:id:doloopwhile:20141129182134p:plain

Elmはクライアントサイド向けの関数型言語です。一体どんな言語なのでしょうか?

1. HTML/CSS/JSにコンパイルされる

ElmはHTML/CSS/JSにコンパイルして使用します。 この辺はJavaScriptコンパイルされるAltJSに似ています。 AltJS同様、Elmも特別なランタイムライブラリは不要です。

ただし、Elmは1つのソースでHTML/CSS/JSをすべてまかなえるのが特徴です。

2. 独自の抽象化レイヤーを提供している

代表的なAltJSであるCoffeeScriptは"It's just JavaScript"をモットーにしています。すなわち、文法を改良するのみで、「中身」はJavaScript以上でも以下でもありません。

一方、Elmでは直接JSやCSSを操作することはできません。 基本的にすべてElmの関数・レイアウトライブラリを使わなければなりません。

これはとっつきにくいのですが、逆に見れば「歴史的なしがらみによる汚さ」を扱う必要が無いと言うことです。

ただし、Portsを通じてJavaScriptとやりとりしたり、Canvas風にHTMLに埋め込んで使うこともできます。

3. Haskellベースである

ElmはHaskellを元に若干の修正を加えた独自言語です。

当然Elmは強力な静的型を備えています。 「0に.nameというプロパティはありません」的なエラーとは無縁です。

またあらゆるものは関数ですArray.some Array.every どころか、foldl, map, etc.. 使い放題です。

4. FRP(Functional Reactive Programing)に対応している

ElmはHaskellベースなので状態や変数はありません。

もちろん、クライアントには状態変化がありまくりです。 マウスの動き、ウィンドウサイズの変更、APIからのレスポンス etc...

JavaScriptの場合は状態変化はonmousemoveなどのcallbackを使って関数で明示的に扱うことになります。しかし、callbackが増えてきて、しかもネストしだすと何がなんだかわからなくなります。callback地獄です。

一方Elmでは組み込みの<~~を使います。

main =
  renderScene
  <~imageAPIResp
  ~ Mouse.position
  ~ Window.width
  ~ pagingAPIResp
  ~ (fps 30)

更新の処理はElmが勝手に行ってくれます。

FRPについてはこちらのスライドが大変優れているので、こちらをご覧ください。

http://www.slideshare.net/maedaunderscore/elmfunctional-reactive-programming

5. Playgroundが充実している

ElmはPlaygroundに力を入れています。

f:id:doloopwhile:20141129200243p:plain

GoなどにもPlaygroundはありますが、Elmのは、

と、かなり機能が充実しています。

また、Exampleも基本文法から、応用までそろっています。

Examples

ElmのPlaygroundのゆるかわほっこり感は、Haskellの取っ付きにくさを打ち消してあまりあるものがありますね。

6. Haskellだけど怖くない

私はHaskellはこんなイメージです。 f:id:doloopwhile:20141129201705j:plain

確かに、JavaScriptとはシンタックスが全然違うのでとっつきにくくはあります。 最初はコンパイルが通らなくて苦労します。

しかし、ElmはPlaygroundで簡単にトライ&エラーを繰り返す事ができます。 また、「最初の100個の素数を求める」のような人工的な例ではなく、目に見えて実際に動くアプリを作る事ができるので、Haskellよりモチベーションを保ちやすいでしょう。

また、ElmにはFRPがある代わりにElmにモナドはありません。

7. ElmはAnglarJSを置き換える言語である?

既にクライアントサイドには様々なAltJSやライブラリがあるのに、なぜ新しくElmを学ぶのか?

私の場合はAngularJSへの疑問でした。

AngularJSは優れたライブラリで、実際に仕事で使ってもいるんですが、 難しすぎる!

  • 3つの異なる言語(HTML/CSS/JavaScript)を同時に扱わなくてはならない。*1難しい!
  • 特定の使われ方(CRUD)に特化していて、汎用性が欠けているように見える→難しい!
  • ngBind, ngResource, ngDirective etc… 多い!→難しい!

WEBは10年20年先も存在し続けると思いますが、AngularJSが10年使われるか疑問です。

一方、Elmはシンプルです。

  • 言語は1つだけ*2
  • FRPの仕組みは汎用的(フォーム入力にも、APIコールにも、アニメーションにも何にでも使える)
  • 「すべてが関数」関数は容易に組み合わせられる

ひょっとしたら、Elmにはクライアントサイドの未来の主流になるかもしれません。 少なくともElmにヒントがあるのは確かです。

関連リンク

POSTDにElm関連の翻訳記事があります。

まず、これらをよんでモチベーションを高めてから始めるといいと思います。

あとがき

明日2日目は「Elmをインストールする」です。

Elm Advent Calendar 2014にはまだ空きがあります。ふるってご参加ください。

*1:場合によってはCoffeeScript、Less、Slimなども学ばなければなりません。

*2:基本的には。HTMLやJavaScriptと連携すれば別です。