如何使用putStr和map输出字符串列表?我想做的事情如下:
s=["test1","test2"]
map putStr s
Run Code Online (Sandbox Code Playgroud)
但没有monad的经验,也不知道如何正确...
任何形式的提示都非常受欢迎!
这里正确的做法是使用mapM_ :: Monad m => (a -> m b) -> [a] -> m ().但是如果你想了解一些有用的Prelude功能......
我们这里有两个功能,
map :: (a -> b) -> [a] -> [b]
putStr :: String -> IO ()
Run Code Online (Sandbox Code Playgroud)
如果我们替代的类型putStr为map(即a ~ String,b ~ IO ())我们得到
map putStr :: [String] -> [IO ()]
Run Code Online (Sandbox Code Playgroud)
所以这需要一个字符串列表,并给我们一个IO ()行动列表; IO计算不返回任何有用的东西.
我们想把它[IO ()]转变为类似的东西,IO (...)因为我们需要IO成为最外层才能使用它main :: IO ()
sequence :: Monad m => [m a] -> m [a]来自的功能Prelude正是我们所需要的.它需要一个monadic动作列表,执行它们并将结果返回到monad中包含的列表中.直观地,它将monad移动到最外层.
sequence . map putStr :: [String] -> IO [()]
Run Code Online (Sandbox Code Playgroud)
这是非常接近的,但我们仍然有,IO [()]而不是IO (),我们并不真正关心[()]结果,忽略它是很好的.同样,Prelude我们需要的是:sequence_ :: Monad m => [m a] -> m ()它执行列表中的每个monadic动作并忽略它们的返回值.
注意,mapM_定义为
mapM_ f = sequence_ . map f
Run Code Online (Sandbox Code Playgroud)
类型map是:
map :: (a -> b) -> [a] -> [b]
Run Code Online (Sandbox Code Playgroud)
这意味着,因为putStr返回一个IO (),你的表达式将返回一个[IO ()].
相反,您可以使用mapM_(从中导入Prelude)忽略映射中的返回类型,并返回IO ()一个合适的返回类型main:
main = do
let s=["test1","test2"]
mapM_ putStr s
Run Code Online (Sandbox Code Playgroud)