所以这个问题更多地是关于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)
...
答案 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 ()
(通常看起来更好,但对我来说有一点迫切的感觉)。