2009-05-31 20 views
50

我有一個字符串列表,並試圖這樣:Haskell:不能使用「map putStrLn」嗎?

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))。但它會更簡單的只是使用地圖...

謝謝!

回答

89

main函數的類型應該是IO t(其中t是一個類型變量)。 map putStrLn ls的類型是[IO()]。這就是你得到這個錯誤信息的原因。您可以通過運行在ghci以下驗證這一點你自己:

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

一個解決問題的方法是使用mapM,這是map的「一元」的版本。或者,您可以使用與mapM相同的mapM_,但不收集函數返回的值。由於您不關心putStrLn的返回值,因此在此處使用mapM_更合適。 mapM_有以下類型:

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

這裏是如何使用它:

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

我希望自己早點學到的東西是在Data.Traversable中定義了另一個mapM。這個mapM除了列表之外還有更多的數據結構,比如地圖和數組。 – 2009-05-31 20:56:19

19

艾曼的回答最有意義的這種情況。一般來說,如果您有[m()]並且您想要m(),那麼請使用sequence_,其中m可以是任何monad,包括IO