IOモナドのリスト

IO Intが100個入っているリストがあるんですが、Intが1の物の個数を調べるにはどうしたらいいのでしょう。こんな関数を作ったらIOなんてデータコンストラクタはないと言われました。

won :: IO Int -> Int -> Bool
won (IO x) y = (x == y)


The monad laws

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) 

だいぶ綺麗になった