8

私はHaskellを初めて使用するので、これはばかげた質問かもしれません。機能があります

foo :: Int -> IO ()

その結果はいくつかの有用な情報を出力します。今私はこれをしたい:

do
    foo 0
    foo 1
    foo 0
    foo 2
    foo 3

これをループとして書くにはどうすればよいですか?私の問題は、モナドを「連結」することです。これは、doステートメントによって自動的に実行されます...

ご協力ありがとうございました!

4

2 に答える 2

14

mapM_ foo [0,1,0,2,3]トリックを行います。

おそらくもっと重要なのは、「どうやってそれを理解するのか」ということです。Hoogleは素晴らしいツールです。署名付きの関数をInt -> IO ()一連のIntsに適用して、新しいIOアクションを取得するとします。したがって、探しているものには署名(Int -> IO ()) -> [Int] -> IO ()があるので、Hoogleにその署名を持つ関数を要求します。2番目の結果はmapM_、です。その署名は

Monad m => (a -> m b) -> [a] -> m ()

そうmapM_です、実際には、任意のモナド(だけでなくIO)と任意のタイプ(だけでなくInt)で機能します。あなたがそれについて考えるとき、それはまったく驚くべきことではありません。

于 2013-02-10T13:11:55.050 に答える
12

mapM_モナド値を返す関数をリストにマップし、バインド演算子を使用して結果を順序付けするコンビネータが必要です。

>> let foo n = putStrLn (show n ++ "!")
>> mapM_ foo [0,1,0,2,3]
0!
1!
0!
2!
3!

反転バージョンを使用することを好む人もいます

for :: Monad m => [a] -> (a -> m b) -> m ()
for = flip mapM_

これは命令型コードのように見えます:

>> for [1..5] $ \n ->
     putStrLn ("Number: " ++ show n)
Number: 1
Number: 2
Number: 3
Number: 4
Number: 5

forM_と呼ばれるコンビネータは で定義されてControl.Monadおり、私が呼んだコンビネータとまったく同じことを行うことに注意してくださいfor

于 2013-02-10T13:17:52.467 に答える