映射需要IO在列表上的函数的更好方法

Dan*_*Man 3 haskell

最近我有一个字符串列表,需要独立遍历每个字符串并执行一些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
Run Code Online (Sandbox Code Playgroud)

IO有点复杂,但这是它的要点(需要有一个功能超过列表,并IO根据列表成员做)我希望有人可以告诉我如何更好地做到这一点.

sep*_*p2k 15

你的goOverList功能几乎相当于mapM_ putStrLn.(几乎是因为mapM_在你的函数没有的情况下也可以使用空列表).

mapM是一个函数,它将类型a -> IO b¹ 的函数应用于as 列表中的每个项目,并返回一个IO带有bs 列表的² .mapM_是一样的mapM,只是它不存储在列表中的结果(这是没有意义的返回行动()putStrLn那样).

¹实际上它比这更通用:函数的类型a -> m b在哪里Monad m,但在这种情况下mIO.

²再次它实际上是m.


Lui*_*las 9

sepp2k和solrize是正确的推荐mapM_.但是,本着教导你钓鱼而不是给你钓鱼的精神,这里有你可以尝试的东西:

  1. 尝试提出您需要的操作的类型签名.例如,在您的情况下,您需要某种类型的东西(String -> IO ()) -> [String] -> IO ().
  2. 转到Hoogle搜索引擎查找Haskell库并搜索该类型.
  3. 那个没有结果,所以尝试稍微修改一下类型以使其更通用.更换Stringa得到(a -> IO ()) -> [a] -> IO (),并搜索.

现在第二次搜索的第三个结果是mapM_ :: Monad m => (a -> m b) -> [a] -> m (),这正是你想要的.(第一个答案,closeFdWith :: (Fd -> IO ()) -> Fd -> IO ()不是相关的结果;第二个答案,是相关的,traverse_ :: (Foldable t, Applicative f) => (a -> f b) -> t a -> f ()但理解和使用有点复杂.)