今日の畑(120623)

先日の台風4号のせいで支柱が倒れたり、ズッキーニがおかしな方向向いてた。

キュウリは1本収穫した。

1340524418

サツマイモの苗は順調。枝豆とインゲンもまぁまぁ。

1340524420

ズッキーニは折れた葉を処分して支柱で支えるようにした。

1340524422

トマトはちょっと赤くなってた。

1340524424

ベランダで出番を待っている空芯菜とモロヘイヤ。再来週くらいに定植かな。

1340524425

収穫したもの

  • ズッキーニ
  • キュウリ
  • シソ
  • 人参

ParsecでつくるJSON Parser (RWH 16章)

HaskellでChemistryやBiology関連のParser書きたいなぁと思っているのでParsecをきちんと使えるようになりたい。

ProductName Real World Haskell―実戦で学ぶ関数型言語プログラミング
Bryan O'Sullivan
オライリージャパン / 3990円 ( 2009-10-26 )


16章にJSONのParserを書く例が載っていたのでやってみた。写経しててみて、Parserとデータコンストラクタというかデータ定義はセットなのかな?と思ったんだけどどうなんだろう?

Hackageに参考になりそうなパッケージないか、あとで探す。

{-# LANGUAGE FlexibleInstances,TypeSynonymInstances #-}

import JSONClass
import Numeric
import Control.Applicative
import Control.Monad (MonadPlus(..), ap)
import Text.ParserCombinators.Parsec hiding (many, optional, (<|>))

p_text :: CharParser () JValue
p_text = spaces *> text <?> "JSON text"
    where text = JObject <$> p_object
             <|> JArray <$> p_array

p_series :: Char -> CharParser () a -> Char -> CharParser () [a]
p_series left parser right =
    between (char left <* spaces) (char right) $
            (parser <* spaces) `sepBy` (char ',' <* spaces)

p_array :: CharParser () (JAry JValue)
p_array = JAry <$> p_series '[' p_value ']'

p_object :: CharParser () (JObj JValue)
p_object = JObj <$> p_series '{' p_field '}'
    where p_field = (,) <$> (p_string <* char ':' <* spaces) <*> p_value

p_value :: CharParser () JValue
p_value = value <* spaces
    where value = JString <$> p_string
              <|> JNumber <$> p_number
              <|> JObject <$> p_object
              <|> JArray <$> p_array
              <|> JBool <$> p_bool
              <|> JNull <$ string "null"
              <?> "JSON value"

p_bool :: CharParser () Bool
p_bool = True <$ string "true" <|> False <$ string "false"

p_value_choice = value <* spaces
    where value = choice [ JString <$> p_string
                         , JNumber <$> p_number
                         , JObject <$> p_object
                         , JArray <$> p_array
                         , JBool <$> p_bool
                         , JNull <$  string "null"
                         ]
                  <?> "JSON value"

p_number :: CharParser () Double
p_number = do s <- getInput
              case readSigned readFloat s of
                [(n, s')] -> n <$ setInput s'
                _ -> empty

p_string :: CharParser () String
p_string = between (char '\"') (char '\"') (many jchar)
    where jchar = char '\\' *> (p_escape <|> p_unicode)
              <|> satisfy (`notElem` "\"\\")

p_escape = choice (zipWith decode "bnfrt\\\"/" "\b\n\f\r\t\\\"/")
    where decode c r = r <$ char c

p_unicode :: CharParser () Char
p_unicode = char 'u' *> (decode <$> count 4 hexDigit)
    where decode x = toEnum code
              where ((code,_):_) = readHex x

動かす

*Main> parse p_text "(unknown)" "[1,2,3]"
Right (JArray (JAry {fromJAry = [JNumber 1.0,JNumber 2.0,JNumber 3.0]}))
*Main> parse p_text "(unknown)" "{\"test\":3}"
Right (JObject (JObj {fromJObj = [("test",JNumber 3.0)]}))

ちゃんと動いた。JSONの例題は5,6,16章ととびとびになっているので全体像が掴みにくかった。

JSON型クラスを作ってみた (RWH 6章)

こんな感じで定義してあるので

instance (JSON a) => JSON [a] where
    toJValue = undefined
    fromJValue = undefined

instance (JSON a) => JSON [(String, a)] where
    toJValue = undefined
    fromJValue = undefined

instance (JSON a) => JSON (JObj a) where
    toJValue = JObject . JObj . map (second toJValue) . fromJObj
    fromJValue (JObject (JObj o)) = whenRight JObj (mapEithers unwrap o)
        where unwrap (k,v) = whenRight ((,) k) (fromJValue v)
    fromJValue _ = Left "not a JSON object"

instance (JSON a) => JSON (JAry a) where
    toJValue = jaryToJValue
    fromJValue = jaryFromJValue

newtype JAry a = JAry {
      fromJAry :: [a]
    } deriving (Eq, Ord, Show)

newtype JObj a = JObj {
      fromJObj :: [(String, a)]
    } deriving (Eq, Ord, Show)

アレイとオブジェクトをJValue型にするために

*JSONClass> toJValue . JObj $ [("test", 1)]
JObject (JObj {fromJObj = [("test",JNumber 1.0)]})
*JSONClass> toJValue . JAry $ [1,2,3]
JArray (JAry {fromJAry = [JNumber 1.0,JNumber 2.0,JNumber 3.0]})

ってやらないといけないのが、ちょっと引っかかる。動かすとこまでは書いてないからなぁ。

ProductName Real World Haskell―実戦で学ぶ関数型言語プログラミング
Bryan O'Sullivan
オライリージャパン / 3990円 ( 2009-10-26 )


ソーシャルメディア進化論

amazonでは評価が分かれているが、物語としてみればそれなりに面白かった。数学的な話は殆ど出てこないし、ネットワークモデルとかかじったことがあれば、数学的になんかおかしい理論展開だなぁと思うけど。

ProductName ソーシャルメディア進化論
武田隆
ダイヤモンド社 / 1890円 ( 2011-07-29 )


ソーシャルネットワークとマネタイズを如何に両立させるかっていうあたりを拾い読みすればいいんじゃないかな。 コミュニティデザインのあたりは参考になることがあるんじゃないかなぁ。

改めて読みなおしてみると確かに自社宣伝臭はちょっと強いかもと思った。

  • 繭化の問題に対する処方箋は、実名性を高める方向ではなく、匿名性を維持したまま、社会につながるモデルであるということになる。
  • Facebookのように実名性を高め、オープンを強要すれば本音は隠れてしまう。

Haskellで(,)が関数だと知ったのだが中置演算子として使えないの?

RWHを読んでいたら(,)が関数だと知った

Prelude> :t (,)
(,) :: a -> b -> (a, b)
Prelude> (,) 'a' 'b'
('a','b')

期待通りタプルを返す。で括弧でくくられているってことは中置記法使えるのかなと思いやってみた

Prelude> 'a' , 'b'

<interactive>:33:5: parse error on input `,'

これはparse error。

なんで?

2012.06.21 追記

@ksmakotoに(,)はデータコンストラクタじゃないかと指摘された。

Prelude> :i (,)
data (,) a b = (,) a b  -- Defined in `GHC.Tuple'
instance (Bounded a, Bounded b) => Bounded (a, b)
  -- Defined in `GHC.Enum'
instance (Eq a, Eq b) => Eq (a, b) -- Defined in `GHC.Classes'
instance (Ord a, Ord b) => Ord (a, b) -- Defined in `GHC.Classes'
instance (Read a, Read b) => Read (a, b) -- Defined in `GHC.Read'
instance (Show a, Show b) => Show (a, b) -- Defined in `GHC.Show'

確かにデータコンストラクタですね。だから中置記法が使えないってことでいいのかな?

ついでに文法への参照も教えてもらったので後で読んでみる。

ProductName Real World Haskell―実戦で学ぶ関数型言語プログラミング
Bryan O'Sullivan
オライリージャパン / 3990円 ( 2009-10-26 )


SpectraSoul - Away With Me Feat. Tamara Blessa

これはよいですね。

元ネタもなかなか(買ってないけど)。

Haskell の printデバッグをWriterTモナドとWriterモナドで

Haskellで躓く理由の一つにPerl,Pythonみたいなノリでprintデバッグしにくいってのがありますね。

Haskell の printf デバッグ / tnomuraのブログでprintデバッグをやっていたので、これをWriterTで書きなおしてみた(最近モナド変換子を理解したので)。

ProductName すごいHaskellたのしく学ぼう!
Miran Lipovača
オーム社 / 2940円 ( 2012-05-23 )


元のコードは階乗計算ですね。

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])

こういうのは、理屈がわからなくてもいいからとりあえず身体で覚える的に早い段階で説明されててもいいのかなぁなんて思った。

今日の畑(120618)

台風四号対策で出社前に畑に行ってトマトとかキュウリを縛ってきた。

ズッキーニはちょっと見ない間に大きくなってた。ちょっとちいさめで、どうしようか悩んだんだが二本収穫した。

1340094954

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

1340094956

枝豆とつるなしインゲンの本葉が出てたので間引きもおこなった。

後から植えたゴーヤはなぜか枯れてたので、苗を調達するか違うものを植えるか悩む。

RWH5章の写経

台風が接近した関係で早退したので、RWHの5章のJSONパーサーを写経してみた。前にも一度しているはずなので二回目だと思うんだけど、写経はなかなか楽しかった。pretty printのために新しい型(Doc)を作って値コンストラクタで改行を入れるかどうか制御したりとか。

ProductName Real World Haskell―実戦で学ぶ関数型言語プログラミング
Bryan O'Sullivan
オライリージャパン / 3990円 ( 2009-10-26 )


そもそもaesonが速いらしいので、素朴なRWHの実装とどう違っているのかなぁと知りたかったのが今回の写経のモチベーションなのでこっちも読んでみる。

この後16章のParsecでもやる予定。

名古屋トリップ

名古屋のあたりに住んでいる友人に子どもが生まれたので、挨拶も兼ねて旅行をすることにした。

豊橋で乗り継ぎなので、昼はちょっと気になっていた豊橋カレーうどんを。雨が降っていて、外に出たくないなぁという理由で、駅ビル内の「みかわの郷カルミア店」で。

1340005392

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

1340005395

豊橋カレーうどんの5か条には食べ終わりがどうなっているか書いてないけど、ライスを混ぜるってことは、最終的にスープがカレーライスとして消費され尽くすということでしょ?茶の多すぎるお茶漬けみたいな状態になっているってどういうことよ?10m手前に止まった電車でGoみたいな中途半端感が得られた。

新規開発型B級グルメって難しいなぁ。

ちょっと時間があったので、路面電車を見た。道路を走る電車は新鮮だったらしい。

1340005396

夜は世界の山ちゃんで手羽先を食べた。

二日目は常滑に行った

INAXライブミュージアムに行って「光るどろだんご」作りをねらっていたのだけど、予約制だったらしく埋まっていた。しょうがないので、当日申し込みOKなタイル張りを申し込んだ。

1340005398

1340005400

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

1340005402

1340005404

1340005406

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

1340005408

1340005409

1340005411

1340005413

1340005415

夜はエスカの稲生でひつまぶし。

お酒は銘柄聞いてから頼めばよかったかな。地酒を期待してた

1340005417

うなぎはまぁまぁ。

1340005419

1340005421

最終日は、あおなみ線でリニア鉄道館まで。

先頭車両に乗ったら、子どもも大人も鉄分高かった。

1340005422

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

1340005424

アミューズメント的な要素が少ないので、鉄度高くないとすぐ飽きるリスクを感じた場所だった。(娘は速攻飽きた)

名古屋は久しぶりだけど、なかなか楽しめた。