Haskell:不能使用“map putStrLn”?

时间:2009-05-31 19:08:19

标签: haskell io monads

我有一个字符串列表,并尝试了这个:

ls = [ "banana", "mango", "orange" ]

main = do
       map PutStrLn list_of_strings

那不起作用,我无法理解为什么。

ghc print-list.hs
print-list.hs:3:0:
    Couldn't match expected type `IO t' against inferred type `[IO ()]'
    In the expression: main
    When checking the type of the function `main'

任何提示?我想它与地图返回列表而不是值有关,但我找不到一种简单的方法来解决这个问题。

现在,我知道打印字符串列表的唯一方法是编写一个函数来迭代列表,打印每个元素(如果列表是[a]则打印,但打印并递归如果它是(a:b) ))。但是使用map ...

会更简单

谢谢!

2 个答案:

答案 0 :(得分:93)

main函数的类型应为IO t(其中t是一个类型变量)。 map putStrLn ls的类型为[IO ()]。这就是您收到此错误消息的原因。您可以通过在ghci中运行以下内容来自行验证:

Prelude> :type map putStrLn ls
map putStrLn ls :: [IO ()]

问题的一个解决方案是使用mapM,这是map的“monadic”版本。或者,您可以使用与mapM相同的mapM_,但不会从函数中收集返回的值。由于您不关心putStrLn的返回值,因此在此处使用mapM_更为合适。 mapM_具有以下类型:

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

以下是如何使用它:

ls = [ "banana", "mango", "orange" ]
main = mapM_ putStrLn ls

答案 1 :(得分:20)

艾曼的回答对这种情况最有意义。一般情况下,如果您有[m ()]并且想要m (),请使用sequence_,其中m可以是任何包含IO的monad。