Haskell:不能使用"map putStrLn"?

Jay*_*Jay 53 io monads haskell

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

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

main = do
       map PutStrLn list_of_strings
Run Code Online (Sandbox Code Playgroud)

这不起作用,我不明白为什么.

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'
Run Code Online (Sandbox Code Playgroud)

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

现在,我知道打印字符串列表的唯一方法是编写一个函数来迭代列表,打印每个元素(如果列表是[a]则打印,但如果是(a:b)则打印和递归).但是,这将是很多简单的只使用地图...

谢谢!

Aym*_*ieh 96

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

Prelude> :type map putStrLn ls
map putStrLn ls :: [IO ()]
Run Code Online (Sandbox Code Playgroud)

该问题的一个解决方案是使用mapM,这是"monadic"版本map.或者您可以使用mapM_与函数相同mapM但不收集返回值的函数.既然你不关心putStrLn它的返回值,那么mapM_在这里使用它更合适.mapM_有以下类型:

mapM_ :: Monad m => (a -> m b) -> [a] -> m ()
Run Code Online (Sandbox Code Playgroud)

以下是如何使用它:

ls = [ "banana", "mango", "orange" ]
main = mapM_ putStrLn ls
Run Code Online (Sandbox Code Playgroud)

  • 我希望我早点学到的东西是Data.Traversable中定义的另一个mapM.除了列表(例如地图和数组)之外,此mapM还可以处理更多数据结构. (16认同)
  • 我一直认为`main`应该是`IO()`类型,从来不知道它可能是'forall t.IO t`.这表明你每天都能学到新东西:-) (5认同)

GS *_*ica 20

艾曼的回答对这种情况最有意义.一般来说,如果你有[m ()],你想要m (),然后使用sequence_,哪里m可以是任何monad包括IO.