3

最近、文字列のリストがあり、それぞれを個別に調べて、いくつかのIO機能を実行する必要があります。

だから基本的に私が持っているのはこれです:

goOverList :: [String] -> IO ()
goOverList (x:[]) = do
    putStrLn x
goOverList (x:xs) = do
    goOverList [x]
    goOverList xs

main = do
    let myList = ["first", "second", "third"]
    goOverList myList

IOはもう少し複雑ですが、それがその要点です(関数がリストをIO調べ、リストメンバーに基づいて実行する必要があります)誰かがこれをより良くする方法を教えてくれることを望んでいました。

4

4 に答える 4

15

あなたのgoOverList機能は とほぼ同等mapM_ putStrLnです。(ほとんどmapM_の場合、関数は機能しませんが、空のリストでも機能します)。

mapMa -> IO b型¹の関数を s のリスト内の各項目に適用し、 s のリストで ² をa返す関数です。結果をリストに保存しないことを除いて、 と同じです(これは、同様に返すアクションには意味がありません)。IObmapM_mapM()putStrLn

¹ 実際にはそれよりも一般的です。関数の型a -> m bは whereMonad mですが、この場合mIOです。

² 繰り返しますが、実際には m です。

于 2012-07-09T22:21:40.590 に答える
9

sepp2k と solrize をお勧めしmapM_ます。しかし、魚を与えるのではなく、魚を釣ることを教えるという精神で、将来試すことができるものを以下に示します。

  1. 必要な操作の型シグネチャを考えてみてください。たとえば、あなたの場合、 type の何かが必要です(String -> IO ()) -> [String] -> IO ()
  2. Haskell ライブラリの Hoogle 検索エンジンに移動し、そのタイプを検索します。
  3. これには結果がありません。型を少し変更して、より一般的なものにしてみてください。に置き換えStringa取得(a -> IO ()) -> [a] -> IO ()し、それを検索します。

2 番目の検索の 3 番目の結果はです。これはmapM_ :: Monad m => (a -> m b) -> [a] -> m ()、まさにあなたが望むものです。(最初の回答closeFdWith :: (Fd -> IO ()) -> Fd -> IO ()は関連する結果ではありません。2 番目の回答traverse_ :: (Foldable t, Applicative f) => (a -> f b) -> t a -> f ()は関連しますが、理解して使用するのは少し複雑です。)

于 2012-07-09T22:42:20.477 に答える
4

まず、簡単な改善:

goOverList' :: [String] -> IO ()
goOverList' []     = return ()
goOverList' (x:xs) = do
    putStrLn x
    goOverList' xs

再帰の基本ケースは空のリストであるべきです: その場合、return ()何もしない IO アクションを返すだけです。1 つ以上の要素がある場合は、それを印刷して、リストの残りの部分を続行します。

を使用してよりコンパクトな定義を行うことで、まったく同じことが実現できます。モナド アクションで動作することを除いてmapM_ :: Monad m => (a -> m b) -> [a] -> m ()、通常の と同じです。通常のようmapに結果のコレクションを返す代わりに、それを捨てます。この場合、リストの要素を出力することのみに関心があるため、これで問題なく機能します。m [b]mapM

goOverList'' :: [String] -> IO ()
goOverList'' = mapM_ putStrLn

さらに一般化するために、「表示可能な」アイテムのすべてのリストのprint :: Show a => a -> IO ()代わりに信頼して入力を受け入れることができます。putStrLn

goOverList''' :: (Show a) => [a] -> IO ()
goOverList''' = mapM_ print

data T = One | Two | Three deriving (Show)

main = do
    let myList = [One, Two, Three]
    goOverList''' myList
于 2012-07-09T22:23:19.373 に答える
2

関数は、標準の Prelude の関数である場所にgoOverList記述できます。mapM_ putStrLnmapM_

独自の実装を簡素化することもできます。

goOverList :: [String] -> IO ()

goOverList [] = return ()

goOverList (x:xs) = do
    putStrLn x
    goOverList xs
于 2012-07-09T22:24:03.330 に答える