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

时间:2012-07-09 22:16:49

标签: 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

我的IO有点复杂,但这是它的要点(需要让一个函数遍历列表并根据列表成员执行IO)我希望有人可能会显示我怎么做得更好。

4 个答案:

答案 0 :(得分:15)

您的goOverList功能几乎等同于mapM_ putStrLn。 (差不多因为mapM_也适用于空列表而你的函数没有)。

mapM是一个函数,它将a -> IO b¹类型的函数应用于a列表中的每个项目,并返回一个IO²列表b的。{ mapM_mapM相同,只是它不会将结果存储在列表中(对于()返回putStrLn的操作没有意义。

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

²实际上它实际上是m。

答案 1 :(得分:9)

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

  1. 尝试提供您需要的操作的类型签名。例如,在您的情况下,您需要(String -> IO ()) -> [String] -> IO ()类型的内容。
  2. 转到Hoogle search engine for Haskell libraries并搜索该类型。
  3. 那个没有结果,所以尝试稍微修改一下类型以使其更通用。将String替换为a以获取(a -> IO ()) -> [a] -> IO (),并搜索该内容。
  4. 现在the second search的第三个结果是mapM_ :: Monad m => (a -> m b) -> [a] -> m (),这正是您想要的。 (第一个答案,closeFdWith :: (Fd -> IO ()) -> Fd -> IO ()不是相关结果;第二个,traverse_ :: (Foldable t, Applicative f) => (a -> f b) -> t a -> f ()是相关的,但理解和使用起来有点复杂。)

答案 2 :(得分:4)

首先,轻松改进:

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

递归的基本情况应该是空列表:在这种情况下,您只需返回不执行任何操作的IO操作return ()。如果您有一个或多个元素,则打印它并继续使用列表的其余部分,这很简单。

同样精确的事情可以通过mapM_ :: Monad m => (a -> m b) -> [a] -> m ()更紧凑的定义来实现:它与常规map相同,除了它适用于monadic动作。它不会像常规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

答案 3 :(得分:2)

您的goOverList函数可以写为mapM_ putStrLn,其中mapM_是标准前奏中的函数。

您还可以简化自己的实施:

goOverList :: [String] -> IO ()

goOverList [] = return ()

goOverList (x:xs) = do
    putStrLn x
    goOverList xs