21062012 drum'n'bass
これはよいですね。
元ネタもなかなか(買ってないけど)。
21062012 drum'n'bass
これはよいですね。
元ネタもなかなか(買ってないけど)。
20062012 Haskell
Haskellで躓く理由の一つにPerl,Pythonみたいなノリでprintデバッグしにくいってのがありますね。
Haskell の printf デバッグ / tnomuraのブログでprintデバッグをやっていたので、これをWriterTで書きなおしてみた(最近モナド変換子を理解したので)。
元のコードは階乗計算ですね。
fact 0 = return 1 fact n = do print n n1 <- fact (n-1) return (n * n1)
WriterTモナド変換子を積むとこうなる。
import Control.Monad.Writer factT :: Int -> WriterT [Int] IO Int factT 0 = tell [0] >> return 1 factT n = do tell [n] n1 <- factT (pred n)
tellでログるので、runWriterTで実行する。
*Main> runWriterT $ factT 5 (120,[5,4,3,2,1,0]) *Main> execWriterT $ factT 5 [5,4,3,2,1,0] *Main> liftM fst $ runWriterT $ factT 5 120
do記法で何故WriterTとIOが剥がれるのかちょっとよくわからなかったんだけど、bindの定義を見たら
instance (Monoid w, Monad m) => Monad (WriterT w m) where return a = WriterT $ return (a, mempty) m >>= k = WriterT $ do (a, w) <- runWriterT m (b, w') <- runWriterT (k a) return (b, w `mappend` w') fail msg = WriterT $ fail msg
ってなっていたので、型だけちゃんとあわせてあとはtellをはさめばロギングしてくれるようになっているのねと(便利だ)。
階乗計算の例だったらIOモナドを通さなくてもWriterモナドを使えばピュアな計算にログ機能を付加することもできる。
import Control.Monad.Writer factW :: Int -> Writer [Int] Int factW 0 = tell [0] >> return 1 factW n = do tell [n] n1 <- factW (pred n) return $ n * n1
実行する場合はrunWriter
*Main> runWriter $ factW 5 (120,[5,4,3,2,1,0])
こういうのは、理屈がわからなくてもいいからとりあえず身体で覚える的に早い段階で説明されててもいいのかなぁなんて思った。
19062012 家庭菜園
台風四号対策で出社前に畑に行ってトマトとかキュウリを縛ってきた。
ズッキーニはちょっと見ない間に大きくなってた。ちょっとちいさめで、どうしようか悩んだんだが二本収穫した。

人参間引いたのとズッキーニとこぼれ種で畝じゃないところで大きくなった大根を収穫した。

枝豆とつるなしインゲンの本葉が出てたので間引きもおこなった。
後から植えたゴーヤはなぜか枯れてたので、苗を調達するか違うものを植えるか悩む。
19062012 Haskell
18062012 名古屋
名古屋のあたりに住んでいる友人に子どもが生まれたので、挨拶も兼ねて旅行をすることにした。
豊橋で乗り継ぎなので、昼はちょっと気になっていた豊橋カレーうどんを。雨が降っていて、外に出たくないなぁという理由で、駅ビル内の「みかわの郷カルミア店」で。

うずらの卵は事前情報通りだが、湯通ししたミニトマトも入ってた。バランス的にどうなの、これ?と思ったが来にせず食べた。カレーうどんに食べるラー油みたいなのがかかっているのもよくわからんところではある(スープに最初から入れとけばいいんじゃないのかね?)

豊橋カレーうどんの5か条には食べ終わりがどうなっているか書いてないけど、ライスを混ぜるってことは、最終的にスープがカレーライスとして消費され尽くすということでしょ?茶の多すぎるお茶漬けみたいな状態になっているってどういうことよ?10m手前に止まった電車でGoみたいな中途半端感が得られた。
新規開発型B級グルメって難しいなぁ。
ちょっと時間があったので、路面電車を見た。道路を走る電車は新鮮だったらしい。

夜は世界の山ちゃんで手羽先を食べた。
二日目は常滑に行った
INAXライブミュージアムに行って「光るどろだんご」作りをねらっていたのだけど、予約制だったらしく埋まっていた。しょうがないので、当日申し込みOKなタイル張りを申し込んだ。


昼はミュージアム併設のレストランでイタリアンを。



焼き物散歩コースを歩いて帰る。





夜はエスカの稲生でひつまぶし。
お酒は銘柄聞いてから頼めばよかったかな。地酒を期待してた

うなぎはまぁまぁ。


最終日は、あおなみ線でリニア鉄道館まで。
先頭車両に乗ったら、子どもも大人も鉄分高かった。

N700系シミュレーターの抽選には外れたけど、在来線には当選した。

アミューズメント的な要素が少ないので、鉄度高くないとすぐ飽きるリスクを感じた場所だった。(娘は速攻飽きた)
名古屋は久しぶりだけど、なかなか楽しめた。
17062012 sake
16062012 Haskell
すごいHaskellを読んでみて、結局理解があやふやなままなのがタイトルの2つ(というか似たようなもんなので実際は一つかな)だ。使い方はわかるけどなんでそうなんのかなー的なモヤモヤ感が残りまくりだ。
定義(p.247)だと
pure x = (\_ -> x) f <*> g =\x -> f x (g x)
ってなってて、pureはいいんだけど、なんでfは二引数取るようになってんだよと(Readerモナドも一緒)。 本書の例のとおりに
(+) <$> (+3) <*> (*100)
を考えた場合
Prelude Control.Applicative> :t ((+3) <*> (*100)) <interactive>:1:12: Occurs check: cannot construct the infinite type: a0 = a0 -> b0 Expected type: (a0 -> b0) -> a0 Actual type: (a0 -> b0) -> a0 -> b0 In the second argument of `(<*>)', namely `(* 100)' In the expression: ((+ 3) <*> (* 100))
は、普通にエラー。まぁ実際そうだし、fってこれだよなぁ
Prelude Control.Applicative> :t ((+) <$> (+3)) ((+) <$> (+3)) :: Num a => a -> a -> a
p.249の例を見るとつないでるっていうよりは分配してる感しか得られないんだよなぁ。
Prelude Control.Applicative> (\x y z -> [x,y,z]) <$> (+3) <*> (*2) <*> (/2) $ 5 [8.0,10.0,2.5]
bind(>>=)ってIOが強く印象づけられてたのでb順番に計算を実行するための枠組みだと思っていたが、別に計算を連鎖させるわけじゃないのかな。
より大きい計算を作るための計算戦略の枠組みを提供するだけで。
Pyccoを使ってソースコードリーディングすると、ソースとコメントが一緒に管理されるので調子いいんだけど、Haskellに対応してなかったのでやっといた。
今は出力した静的なドキュメントを単純にリンクしてるだけなんだけど、手間がかかるのでgithubにpushした時点でよろしくやってくれるようにしたいなぁと思っているんだが、いい方法が思い浮かばない。
15062012 Haskell
モナドの上にまたモナドって株か?二階建てか?なんて思って敬遠してたのだけど、なんとなくわかってくると、包んで包んでしてるだけじゃないかと。
RWH18章
モナド変換子を使わないでログ記録。これはIO [(FilePath, Int)]型になる。
module CountEntries (listDirectory, countEntriesTrad) where import System.Directory (doesDirectoryExist, getDirectoryContents) import System.FilePath ((</>)) import Control.Monad (forM, liftM, when) listDirectory :: FilePath -> IO [String] listDirectory = liftM (filter notDots) . getDirectoryContents where notDots p = p /= "." && p /= ".." countEntriesTrad ::FilePath -> IO [(FilePath, Int)] countEntriesTrad path = do contents <- listDirectory path rest <- forM contents $ \name -> do let newName = path </> name isDir <- doesDirectoryExist newName -- when isDir $ countEntriesTrad newName if isDir then countEntriesTrad newName else return [] return $ (path, length contents) : concat rest
続いてモナド変換子(WriterT)を使う。WriterT [(FilePath, Int)] IO () という型は一見威圧されて目を背けたくなるところだが、単にIO箱を更にWriterT箱に包みつつそっちの箱に記録を取っていると考えればいいだけ。
元のcountEntriesTradと新しいcountEntriesを見比べてみるとliftIOっていうIOの箱の梱包を解いて中身を取り出す関数が増えているくらいだというのがわかる。
module CountEntriesT (listDirectory, countEntries) where import CountEntries (listDirectory) import System.Directory (doesDirectoryExist) import System.FilePath ((</>)) import Control.Monad (forM_, when) import Control.Monad.Trans (liftIO) import Control.Monad.Writer (WriterT, tell) countEntries ::FilePath -> WriterT [(FilePath, Int)] IO () countEntries path = do contents <- liftIO . listDirectory $ path tell [(path, length contents)] forM_ contents $ \name -> do let newName = path </> name isDir <- liftIO . doesDirectoryExist $ newName when isDir $ countEntries newName
countEntriesでwhenを使っていたのでcountEntriesTradでも使えるかなと思ったんだけど、型が合わなくて無理だった。ソース見ると
when :: (Monad m) => Bool -> m () -> m () when p s = if p then s else return () -- | The reverse of 'when'. unless :: (Monad m) => Bool -> m () -> m () unless p s = if p then return () else s
と定義されているのでIO ()型の時しか使えないのね。
IO剥がすのになんでliftIOって言うんだろ?liftっていうのが自分の直感的なイメージに反するのだけど。
14062012 Haskell
文脈を読む感じで。
Prelude Control.Applicative> [(x*) | x <- [1..9]] <*> [1..9]
リスト内包表記が操作してる感を醸し出しているので排除する。
Prelude Control.Applicative> (*) <$> [1..9] <*> [1..9]
2つのリストから値を取り出しては、可能な組み合わせ全てに対して掛け算をする。
Prelude Control.Applicative> :t ((*) <$>) ((*) <$>) :: (Functor f, Num a) => f a -> f (a -> a) Prelude Control.Applicative> :t [1..9] <*> [1..9] [1..9] <*> [1..9] :: (Enum a, Enum (a -> b), Num a, Num (a -> b)) => [b]
さらに、これをliftAを使って書き直せば
Prelude Control.Applicative> liftA2 (*) [1..9] [1..9]
これは、掛け算っていう演算をアプリカティブの文脈に持ちあげておいて、リストに適用するっていう理解でいいのかな。
Prelude Control.Applicative> :t liftA2 (*) liftA2 (*) :: (Num c, Applicative f) => f c -> f c -> f c