序
Haste は haskell で書いたら javascript にコンパイルできて超ハッピーというアレです.
Haste のいいところの1つは,haskell で書かれたライブラリも使いうる1というところです.Haskell ですごく便利なライブラリで,ブラウザ上で動かしたいかもしれないものといえば Parsec を思いついたので,Haste と Parsec を組み合わせてブラウザ上で動く電卓を作ってみましょう.
準備
パーザを書く
まずは後で haste を使うことは忘れて,普通に haskell で Parsec を使って電卓に使えるパーザを書きましょう.今回は最終的に Double
の計算をすることとします. expr :: Parsec String u Double
という型のものができればオッケーです(名前は何でもいいですが,以下 expr
はこの函数を指します).ここは Haste に関係ないので省略しますが,Haskell 構文解析 超入門 という記事が非常にお勧めです2.
Parsec に不慣れなのでだいぶ不安なのですが,以前上の記事を読んだ記憶を頼りにとりあえず加減乗除と括弧に対応したものを書きました.
module Parse (expr) where
import Text.Parsec
-- |
-- >>> parseTest expr "1 + 2*(3+5)"
-- 17.0
expr :: Parsec String u Double
...
--- このあといい感じの実装
Haste 側の準備
ghc とは別に,Haste が Parsec を呼べるようにしておく必要があります.最近の Haste だと haste-cabal
というツール3が同梱されており,これを使ってこのへんの管理をします.以前 haskell 環境を作りなおして以来若干大胆なので,sandbox
とか使わずにインストールしてしまいましょう.
$ haste-cabal install parsec
Haste 側の準備はこれだけ(!)です.次で完成します.
書き書き
実装はどうしましょうか.シンプルな電卓ということ,折角 parsec を使うこと,などを考えてこういうふうにしてみます:
-
<input type="text" .. >
に計算したい式を打ち込む -
keyUp
で計算を試みる.成功したらそれを表示,失敗したら parsec のエラーを表示. - 表示は
div.textContent
で4.
html を用意します.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Calc</title>
<script src="./build/calc.js"></script>
</head>
<body>
<div>
<input type="text" name="calcInput" id="calcInput">
</div>
<div id="output"></div>
</body>
</html>
あとは,「keyUp
で #calcInput
の中身を呼んで,さっき書いたパーザに渡した結果を #output
に書き込む」という部分を,Haste
を import
したうえで haskell で書いてやればおしまいです.
import Haste
import Haste.DOM
import Haste.Events
import Text.Parsec
-- さっき書いたパーザ
import Parse (expr)
main = do
-- elemById :: MonadIO m => ElemID -> m (Maybe Elem)
Just input <- elemById "calcInput"
Just output <- elemById "output"
-- onEvent element event (EventData evt -> m ()) という形
-- この場合 e にはイベント情報が入り,(今回は使っていないが)函数に渡される
onEvent input KeyUp $ \ e -> do
-- getValue :: (IsElem e, MonadIO m, JSType a) => e -> m (Maybe a)
Just ln <- getValue input
case parse expr "" ln of
Right s -> setProp output "textContent" (show s)
Left l -> setProp output "textContent" (show l)
コンパイルすれば終わり
$ hastec ./src/Calc.hs -isrc -o ./build/calc.js
$ firefox index.html
結果はこちらです(github.io).keyUp
で動くのでちょっと動きが面白い.
まとめ
Haste と Parsec の組み合わせで簡単にブラウザ上で動く電卓を作ることができました.この辺りのライブラリを使えることで加速するうれしさというものもあると思いますし,場合によっては昔 ghc でコンパイルするために書いたソースを流用することもできましょう.積極的に使っていきましょう.
-
残念ながらTemplate haskell にはまだ対応していないので,それを使っているライブラリ(lens など.cf: オートマトンで遊ぶやつを作った - Just $ A sandbox) は使えません.また hashable も現時点ではbuild できないようです. ↩
-
それに限らず,この方の入門記事は全般に大変為になるので,いくつか目を通すといいと思います. ↩
-
名前の通り
cabal
からの fork ですが,普通に haste をインストールするときはhaste-boot
で降ってきます. ↩