如何使用带符号的列表上的映射 - 即避免键入`IO()'类型为`[IO()]'?

时间:2014-05-20 23:21:23

标签: haskell monads io-monad

所以这个问题更多地是关于Monads(尤其是Fay),但是我的例子使用了IO monad。

我有一个函数,其中输入是一个字符串列表,我想逐个打印每个字符串。所以这是我的想法:

funct :: [String] -> ?
funct strs = do
    map putStrLn strs

但是不起作用,因为它返回一个类型[IO()]。所以我的问题是,我如何映射列表,并将其视为我在逐行执行函数,以典型的符号,迭代风格(如下所示)?

funct :: [String] -> IO ()
funct strs = do
    putStrLn (strs !! 0)
    putStrLn (strs !! 1)
    ...

2 个答案:

答案 0 :(得分:13)

大多数标准库列表函数都具有以M结尾的monadic版本:

map :: (a -> b) -> [a] -> [b]
mapM :: (Monad m) => (a -> m b) -> [a] -> m [b]

replicate :: Int -> a -> [a]
replicateM :: (Monad m) => Int -> m a -> m [a]

等。有时他们在Prelude,有时他们在Control.Monad。我建议使用hoogle来查找它们。

特别针对您的情况,我经常使用mapM_ putStrLn

答案 1 :(得分:5)

使用序列

sequence $ map putStrLn strings

序列将monad从monad列表中拉出来

sequence :: Monad m => [m a] -> m [a]

从而将(map putStrLn strings):: [IO a]转换为IO [a]。您可能希望使用相关的sequence_来删除返回值。

您也可以使用forM_:: Monad m => [a] -> (a -> m b) -> m ()(通常看起来更好,但对我来说有一点迫切的感觉)。