読者です 読者をやめる 読者になる 読者になる

ないんたんのパーザを書いた

京都に住んでいた頃は,ズバリ大学付近の予想降水量をないんたんで知ることができたが,ないんたん天気予報@東京 で提供されているのは,本郷・駒場・大岡山・六本木ヒルズの4ヶ所なので,以前に比べると自分の行動範囲からは遠のいてしまった.が,普段は目黒区内を行動しているので,「駒場と大岡山を足して2で割れば,それっぽい予測が得られるのでは?」という雑なアイディアを思い付いたので,やってみたくなった.

しかしながら,ないんたんのデータセットは公開されているわけではなく,JavaScript のファイルを見ても,以下のような形式の記述がなされているだけで,非常に扱いにくい.

function update_kyoto_yoshida(data) {
    data.addRows(151);
    data.setValue(0, 0, '09月04日 23時58分');
    data.setValue(0, 1, 0);
    data.setValue(0, 2, 0);
    data.setValue(0, 3, 0);
    data.setValue(0, 4, 0);
    data.setValue(0, 5, 0);
    data.setValue(0, 6, 0);
    data.setValue(0, 7, 0);
    data.setValue(1, 0, '09月04日 23時59分');
    data.setValue(1, 1, 0);
    data.setValue(1, 2, 0);
    data.setValue(1, 3, 0);
    data.setValue(1, 4, 0);
    data.setValue(1, 5, 0);
    data.setValue(1, 6, 0);
    data.setValue(1, 7, 0);
    // ...
    data.setValue(150, 0, '09月05日 02時28分');
    data.setValue(150, 1, 82);
    data.setValue(150, 2, 26);
    data.setValue(150, 3, 8);
    data.setValue(150, 4, 1);
    data.setValue(150, 5, 0);
    data.setValue(150, 6, 0);
    data.setValue(150, 7, 0);
}

そこで,パーザを書く練習がてら,上記のデータのパーザを書くことにした.

ソースコードはこちら. github.com

attoparsecmegaparsec の存在は知っていたが,パーザを書くのは初めてなので,素直に parsec を使うことにした,特に,attoparsec はエラーメッセージがわかりにくいと聞いていたので,今回は意図的に避けた.

パーザを書くのは今回が初めてだったが,モナド (というか do notation) のおかげで最初から割とスラスラ書けてよかった.基本的には Applicative 信者なので,途中から applicative style に書き換えたが,<* <*> *> を駆使して値を拾ったり捨てたりしたことが今までになかったので,慣れるまでに少し時間がかかったが,今回でできるようになった感じがするので成長したという気分になっている.あと,パーザコンビネータだから当たり前なのだが,パーザをシュッと combine できたりしてすごかった.

ないんたんが返すデータに,月と日は含まれているが,年が含まれていないので,その情報を明示的に与えてあげないといけないというようになってしまったのは残念だった.(とはいえどうしようもない.)

サンプルとして app/Main.hs に,Unix 系 OS 上で扱いやすい (というか cut(1) に渡しやすい) 形式で出力するようなプログラムを書いておいた.

$ curl -s http://sx9.jp/weather/kyoto-yoshida.js | stack exec ninetan-parser-exe
kyoto
yoshida
2016-09-05 00:40:00 2 0 0 0 0 0 0
2016-09-05 00:41:00 1 0 0 0 0 0 0
# ...
2016-09-05 03:10:00 40 8 1 0 0 0 0

# 左から 0.1+ mm/h, 1+ mm/h, ..., 100+ mm/h の降水確率

便利.