IOモナドのリスト
IO Intが100個入っているリストがあるんですが、Intが1の物の個数を調べるにはどうしたらいいのでしょう。こんな関数を作ったらIOなんてデータコンストラクタはないと言われました。
won :: IO Int -> Int -> Bool won (IO x) y = (x == y)
IO モナドは Haskell におけるよく知られた一方向モナドの例です。IO モナドから脱出することはできませんから、 IO モナド中で計算を行うにもかかわらず、結果の値として型構築子 IO を含まないような関数の定義を書くことは不可能です。
ってことは
won :: IO Int -> Int -> IO Bool
になればいいのか? (m >>= f) >>= g == m >>= (\x -> f x >>= g)をつかうのか?
won :: IO Int -> Int -> IO Bool won m x = m >>= (\y -> return (x == y))
できたできた。これでIO IntのリストがIO Boolのリストに変わったので…ってダメじゃん
filterM :: Monad m => (a -> m Bool) -> [a] -> m [a]
これをつかうのかな。aがIO IntでmがIOなら (IO Int -> IO Bool) -> [IO Int] -> IO [IO Int]になる。うーむ。さっきのwonの引数を入れ替えればIO Int -> IO Boolはできる。しかしIO [IO Int]なんかつくってどうするのかと言う気はする。
msumってのがあるな。
won :: IO Int -> Int -> IO Int won m x = m >>= (\y -> return if (x == y) then 1 else 0) main = print $ msum $ map won [...]
あー、だめだ。IO IntはMonadPlusじゃない。
落ち着いて考えてみよう。そろそろ眠い。
count_n :: Int -> [IO Int] -> IO Int -> IO Int count_n _ [] mresult = mresult count_n n (mx:mxs) mresult = count_n n mxs (mresult >>= (\r -> mx >>= (\x -> return (if (x == n) then r + 1 else r)))) main = do game <- init_game play <- return $ (possible_hands game) !! 0 result <- count_n 2 [(step_game game play) >> (while_game_finished select_ai_for_monte game) | _ <- [1..100]] (return 0) print result
わーい、できたー!
これで明日はモンテカルロなAIを作ることができる。
id:pi8027にliftMを教えてもらった
count_n n (mx:mxs) mresult = count_n n mxs (liftM2 (\x r -> (if (x == n) then r + 1 else r)) mx mresult)
だいぶ綺麗になった