Elm」カテゴリーアーカイブ

Elm Platform 0.13以降/Windows上で日本語を含むUTF8のソースコードをコンパイルすると…

hGetContents: invalid argument (invalid byte sequence)

というエラーが出る。おそらくHaskellがSystemデフォルトのエンコーディング(Shift-JIS)を使っているせいでこういうのが発生する…

回避方法

  1. 日本語でコメント書かない

  2. Shift-JISでソースコード保存

  3. 修正してプルリク

ElmでWebsocketを使ってゲームを作ってみた例

説明

ElmでWebsocketを使って、非常にシンプルなネットゲームを作ってみました。

リポジトリこちら

実際に動いているのはこちら ※サーバー側(Erlang)がうまくバックグラウンドで動かせていないせいで、たまーにしかプレイできません。すんません。僕のErlang力不足が原因です…

構成

サーバー側はErlangだけ、クライアント側はElm+Javascript(Websocketのコネクション周り)で作っています。

クライアント側

Elmで作っています。Elmです。Elmですね。

Elmはリアクティブプログラミングというプログラミングパラダイムの上に存在します。なので、常にリアクティブな思考を持って作る必要があります。

ベースとなるシグナルを考える

僕の中でリアクティブプログラミングは、電気回路のイメージがあります。予め作られた回路(Elmで書かれた関数)に、信号(Signal)を流し込み、駆動する。そういう感じです。

入力シグナル

入力シグナルの中に、ユーザーの入力を全て詰め込みました。というのも、foldpでゲームエントリー関数を畳み込んでしまうと、もうそこに別のユーザー入力(つまりシグナル)を入れるのがかなり難しそうだと感じたからです。

入力シグナル部分

このシグナルを、foldpで初期ゲーム状態を与えた状態で畳み込みます。

ゲームシグナル部分

他にもウェブソケットのシグナルを扱わないといけないのですが、やっかいなことにElmのWebSocketを開く関数は

String -> Signal String -> Signal String

という型を持っていて、予め作ったシグナルを渡さないと返り値のシグナルが貰えないようになっています。つまり、シグナルのループが出来ないんです。ちょっと良い説明が出来ないのですが、foldpでWebSocketの返り値を含むような閉じたシグナルを作ると、そこからWebSocketの入力に何かを突っ込むことが非常に難しい感じになります。

じゃあどうしたの?

WebSocketはJavascript側でハンドルし、Portという仕組みを使ってWebSocketへの入力、返り値をそれぞれ独立したシグナルにしました。

WebSocketシグナル部分

これでfoldpで作るシグナルにWebSocketの返り値シグナルを入れても、WebSocketへ自由に入力させることができます。

出力シグナル

Elmからサーバーサイドへは、WebSocketへの入力を行うことで出力を行います。

出力シグナル部分

ゲーム関数

ゲーム関数は、クライアント側の中心となる存在です。この中で、

  • WebSocketから受け取った返り値の処理
  • 各種計算
  • ゲーム状態の遷移

これらの処理を全て行います。

ゲーム関数部分

この中の処理はもう普通の処理です。foldpとかElm特有の処理は出てきません。

まとめ

やっぱりリアクティブを意識するのが重要な感じがします。このゲームでは

  • FPSとなるシグナル
  • サーバー側からのシグナル

という2つの方向性が違うシグナルが有り、現状ではFPSの方で強制的にサーバー側のシグナルを同期させています。ただそのせいでサーバー側からのシグナルを一部取りこぼす(他のユーザーが生成したブロックの情報が同期されなかったり)ことがあるので、なんともどうしたものか…と思っています。

解決策としては、

  • サーバー側でクライアントが必ず受け取ったことが確認できない限りメッセージをキャッシュする
  • サーバー側とクライアント側のメッセージ送受信間隔を同期させる

ぐらいしか思いつきませぬ。

Elmのメリット

最後に、Elmのメリットをいくつか。

モジュールの分割が楽

モジュールを分割するのが楽です。しかもひとつのjavascriptファイルに簡単にコンパイルできるので、保守性が抜群です。

綺麗に書ける

javascriptのグチャッとしたソースコードに精神を削られている人も多いと思います。きっとElmは心の癒やしになるでしょう…

Intellij IDEAのscope language

ElmのコンパイルをFileWatcherプラグインを使ってやろうとしたら、ちょっとだけ躓いたのでメモ。

FileWatcherプラグインでElmのファイルを指定する場合、*.elmとかだと指定できない。なぜならScope Languageというのを使わないといけないから。

elmだと、
file:*/(elmがあるディレクトリ)/*.elm
みたいな感じで行ける。

ElmでWebSocket接続の例

説明

WebSocketというのは、TCPで使える(主にブラウザー用の)プロトコルです。

WebSocket(ウェブソケット)は、コンピュータ・ネットワーク用の通信規格の1つである。インターネットの標準化団体であるW3CIETFがウェブサーバーとウェブブラウザとの間の通信のために規定を予定している双方向通信用の技術規格であり、APIW3Cが、WebSocket プロトコルIETFが策定に関与している。プロトコルの仕様は RFC 6455。TCP上で動く。

引用元 Wikipedia

Javascriptから簡単に利用することができ、Httpに比べ低いレイテンシーでリアルタイムな通信に向いていると言われています。

WebSocketプロトコルについては次の2つのウェブサイトが参考になりました。

RFC6455 — The WebSocket Protocol 日本語訳

  • RFC6455の日本語訳を公開してくださってる方がいらっしゃいました。有り難いですね!しかもちゃんと最新版にアップデートされてます。

Block Rockin’ Codes – WebSocket サーバの実装とプロトコル解説

  • サーバー側でWebSocketの通信を行う部分を書いて見たのですが、その時一番参考にしたウェブサイトです。

WebSocket関連の記事・ソースコードは、以前の版(ドラフト版)をベースに書かれたものが多くあります。最新版とドラフト版ではかなり仕様が変わっているので、注意したほうが良いです。

ElmにもWebSocketを使うためのライブラリが備わっていて~ / Catalog / Elm / WebSocket、非常にシンプルなconnectという関数のみが用意されています。

connect : String -> Signal String -> Signal String

という型からわかるように、WebSocketへの送信も受信もどちらもシグナルになります。Httpと同じですね。正直エラーとかクローズとかどうやってハンドリングするのかわかりませんが、まずは使えることを喜びましょう。

今回ws://echo.websocket.orgにテキストを投げてそれを表示するだけのスクリプトを書きました。ご参考まで。

WebSocketはブラウザでTCPのようなコネクション持続型の通信を行える、非常に興味深い技術だと感じました。仕様もほぼ固まっている?ようなので、色々と使えたら面白いですね。現状WebSocketの中身をブラウザのデバッグツールでみれるのは、Chromeだけのようです。

続きを読む

ElmでN-Queenしてみた

説明

動作するもの

題名の通り、ElmでN-Queen問題をやってみました。リアルタイムにクイーンを配置していくので、アニメーションとして楽しめます。

N-Queen問題ではバックトラック法を使うわけですが、木構造深さ優先探索していないので、厳密な意味でのバックトラック法ではないかなと思います。

N-Queenの場合、縛りのせいで最大2手戻ればすべて網羅できるので、そのせいで解けています。

2014-08-16追記: 良く考えるとツリーをすべて網羅しているということはバックトラック出来ているということですよね。

書いてて思ったのはやはりリストをがっつり扱えるElmという言語のパワーです。特にクイーンの配置をチェックする部分が物凄くきれいに書けます。

斜めチェック用のリストを生成している部分です。

-- left down to right top
ldrtCoords w h =
let xys = xyCoords w h
in map (\(x, y) -> y - x) xys
-- right down to left top
rdltCoords w h =
let xys = xyCoords w h
in map (\(x, y) -> y + x) xys

それを使ってチェックします。

      -- チェッカー関数 nはそれぞれチェックするグループIDを示す
rowCheck n = filter (\(x, cellState) -> x == n) <| zip (yCoords bw bh) xyq
colCheck n = filter (\(y, cellState) -> y == n) <| zip (xCoords bw bh) xyq
ldrtCheck n = filter (\(ldrt, cellState) -> ldrt == n) <| zip (ldrtCoords bw bh) xyq
rdltCheck n = filter (\(rdlt, cellState) -> rdlt == n) <| zip (rdltCoords bw bh) xyq
checkFn = (>=) 1
-- チェックフラグ
rowCheck' = all checkFn <| log "row" <| map (countQueens . rowCheck) [1 .. bw]
colCheck' = all checkFn <| log "col" <| map (countQueens . colCheck) [1 .. bh]
ldrtCheck' = all checkFn <| log "ldrt" <| map (countQueens . ldrtCheck) [(1 - bw) .. (bw - 1)]
rdltCheck' = all checkFn <| log "rdlt" <| map (countQueens . rdltCheck) [2 .. (bw + bh)]

Cなどの手続き型で書かれたN-Queen問題のソースコードは結構ぐちゃっとしてる場合が多いと思うのですが、やはりここは関数型の簡潔さ・スマートさを感じますね。

ちなみにRosetta Codeというサイトでいろんな言語のN-Queen問題の解法を見ることができます。

続きを読む

ElmでHttpリクエストを投げる例

説明

ここ最近関数型言語が私の中でブームになっています。

中でもElmという言語が、取っつきやすく、また(他の関数型に比べて)平易なので楽しんで取り組むことができています。

まだ世間では知名度があまり高くないようですが、次のような記事が有ります。

Googleエンジニア曰く「私たちにはより多くのWebプログラミング言語が必要だ」

GoogleのソフトウェアエンジニアであるGilad Bracha氏は、ニューヨークで開催されたQCon開発者会議の壇上で、Webアプリケーションについて触れた。同氏はWebアプリケーションについて、機能と使いやすさでデスクトップアプリケーションを上回る可能性を有している。しかし、実現するにはWebアプリケーション開発でより多くのプログラミング言語が選択できる必要があるだろうとしている(ITWorld、Slashdot)。
その理由として、Webアプリケーションには、ネットワークに接続できない環境では使えないという欠点がある。将来的にはWebアプリケーションをオフラインで実行する能力は重要になる。このためどんなWebプログラミング言語でも、オフライン使用のための何らかの方法が必要になるだろう。またプログラマがアプリケーションを組み上げたり、テストするのがより簡単になる必要がある、と語った。
また、現在、Webアプリケーションに使用されている主要言語はJavaScriptだが、アプリケーションのオフライン運用には機能的に不十分だ。Googleプログラミング言語である「Dart」を支援することに決めたのは、Webのために強力なプログラミング言語を提供する目的があるという。同氏は有望ではあるが知名度が低い言語として「Elm」についても触れている。Googleとしては特定の言語を否定したり、支援するのではなくWebアプリケーション向けにより多くの開発言語の選択肢が増えることを望んでいるようだ。

この記事で触れられているように、Googleのエンジニアも注目しているプロダクトの様です。

Elmは主にリアクティブ・プログラミングというプログラミングパラダイムを使用するために存在するようですが、まだリアクティブ・プログラミングが従来のイベント駆動型プログラミングに対して持つ明確な優位性を私自身は理解できていません。しかし広く使われているイベント駆動型に比べて考え方がガラッと変わるので、頭の体操・新たなモノの見方を習得するといった観点において、Elmによるプログラミングを経験することは十分に意味があると思います。また関数型言語が持つ明瞭さ・簡潔さを朧げながらも感じ始めると、通常の手続き型言語によるプログラミングにもどかしさを感じれるようになると思います。どこか大人になったような気分になれます。

AppleSwiftという関数型の特徴を持った言語を新たに持ってきたりと、確実に主流の言語は関数型の特徴を取り入れようとしています。またElmの構文は、関数型言語でひときわ有名なHaskellの構文にとても良く似ています。しかしHaskellに比べるといくつか足りない構文があるせいか比較的シンプルです。特にモナド周りはElmにおいて存在が希薄なので、モナドで躓いた私のようなプログラマにとっては非常に取り組みやすいと思います。ElmでHaskellライクな構文や関数型言語に慣れ、その後Haskellや他の関数型言語に挑戦するという道筋も十分にありだと思います。というか私がその路線を考えています。Elmサイコーです。

以下私が考えたElmのメリットです。

  • モナドを意識しなくて良い
  • Javascriptに変換されるので様々な環境で実行可能
  • Haskellライクな構文で非常に読みやすく、簡潔に書ける

デメリットはそれほどないと無いと思いますが、あえてあげるとすれば

  • エディターの対応が貧弱(しかし関数型は型をしっかりと意識するのでさほどエディターの補助機能は必要ないように感じる)
  • 使ってる人があまりいない(しかしこれは時間の問題だと思われます)

ぐらいでしょうか。もっとあるかもしれませんが、まだElmはβバージョンであり、さらに期待してしまう部分が大きすぎて不満は特に感じないと思います。

長々と前置きを書きましたが、以下ElmでHttpリクエストを投げるサンプルコードです。Elm初心者なのでぐだぐだなコードになっていると思います。

続きを読む