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

京都に住んでいた頃は,ズバリ大学付近の予想降水量をないんたんで知ることができたが,ないんたん天気予報@東京 で提供されているのは,本郷・駒場・大岡山・六本木ヒルズの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 はエラーメッセージがわかりにくいと聞いていたので,今回は意図的に避けた.

続きを読む

wercker v2 で Rails + RSpec のビルドを高速化する

TL; DR

  • 予め作っておいた Docker イメージを box として指定する
  • rake assets:precompile で生成されたファイルをキャッシュする
  • test-queueRSpec の実行を並列化する
  • Database Cleaner の代わりに DatabaseRewinder を使う
続きを読む

Haskell でマルコフ連鎖を用いたツイートの自動生成

元ネタ

morishin.hatenablog.com

やったこと

これまでの Twitter 上の発言をもとに,マルコフ連鎖で文章を生成して,それを垂れ流す bot がいるとおもしろいかなと思って作った.しゅうまい君 (@shuumai) みたいなものなのだけど,ソースが特定の人物のものに限定されるという点で異なる.

Twitter からダウンロードできる archive に含まれる tweets.csv を入力として,MeCab形態素解析を行い,マルコフ連鎖で文章を適当に生成して,それを Twitter に投稿する.詳細な実装についてはもりしんの記事を参照のこと.

「おもしろいかな」と思った経緯はまったく覚えてないけど,たぶん inspired by @taketo958 とか @morishin_retro だと思う.

twitter.com

twitter.com

Twitter アカウントはこちら.

twitter.com

リポジトリはこちら.

github.com

続きを読む

キヨシ

界隈の人たちはみんなポエムを書くのが好きなので,散々既出だと思うけど,先週京都にいるときに少し話が出て,自分だったらこう書くかなぁと,フワッと思ったものを書き下してみた.

import Data.Bool (bool)
import Data.List (isPrefixOf)
import System.Random (randomIO)

data Kiyoshi = Z | D | K deriving Eq

instance Show Kiyoshi where
    show Z = "ズン"
    show D = "ドコ"
    show K = "キ・ヨ・シ!"

gen :: IO Kiyoshi
gen = bool Z D <$> randomIO

test :: [Kiyoshi] -> Bool
test = isPrefixOf [D, Z, Z, Z, Z]

main :: IO ()
main = let go xs = do
           x <- gen
           print x
           let xxs = x:xs
           if test xxs then print K else go xxs
       in go []

2016年5月23日追記

fix を使った無名再帰main を書き直してみた. あと,せっかく bool を import しているので,最後で if を使うのをやめた.

import Control.Monad.Fix (fix)
import Data.Bool (bool)
import Data.List (isPrefixOf)
import System.Random (randomIO)

data Kiyoshi = Z | D | K deriving Eq

instance Show Kiyoshi where
    show Z = "ズン"
    show D = "ドコ"
    show K = "キ・ヨ・シ!"

gen :: IO Kiyoshi
gen = bool Z D <$> randomIO

test :: [Kiyoshi] -> Bool
test = isPrefixOf [D, Z, Z, Z, Z]

main :: IO ()
main = flip fix [] $ \loop xs -> do
    x <- gen
    print x
    let xxs = x:xs
    bool (loop xxs) (print K) (test xxs)

beautiful people

data Person = Person {
    isBeautiful :: Bool
  , isNice      :: Bool
  , isTall      :: Bool
  } deriving Show

type People = [Person]

people :: People
people = let b = [minBound ..] in Person <$> b <*> b <*> b

beautiful :: People -> People
beautiful = filter isBeautiful

nice :: People -> People
nice = filter isNice

tall :: People -> People
tall = filter isTall

main :: IO ()
main = do
    print $ beautiful people
    print $ (beautiful . nice) people
    print $ (beautiful . nice . tall) people

これはなに

職場で Rails の scope の名前を決める際のアドバイスとして,形容詞の限定用法について話していて,引数として述語を与えた filter 関数がまさにそれに当たるのではと思い付いたので書いてみた.

逆に isBeautiful は叙述用法だろうか. 叙述用法に関して言えば,isBeautiful のような疑問文は Person -> Bool 型の関数として解釈できるけれども,Alice is beautiful. のような平叙文は,命題(あるいは内容が真であることが保証できる場合には定理)として捉えられるだろうから,もっと型レベルプログラミングでごにょごにょできそうな匂いもする. (ぼくはその道の人ではないので,formulae-as-types なんかについては詳しく知らないのだけれども.)