2009-05-31 4 views
50

Ich habe eine Liste von Strings, und versuchte, dies:Haskell: Kann "map putStrLn" nicht verwenden?

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

main = do 
     map PutStrLn list_of_strings 

, die nicht funktioniert, und ich kann nicht verstehen, warum.

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' 

Irgendwelche Hinweise? Ich nehme an, es hat mit Map zu tun, die eine Liste und nicht einen Wert zurückgibt, aber ich fand keine einfache Möglichkeit, das zu beheben.

Im Moment ist die einzige Möglichkeit, eine Liste von Strings zu drucken, eine Funktion zu schreiben, die die Liste iteriert, jedes Element druckt (drucke, wenn die Liste [a] ist, aber printe und rekursiere, wenn es b)). Aber es wäre viel einfacher, einfach zu verwenden Karte ...

Vielen Dank!

Antwort

89

Der Typ der main-Funktion sollte IO t sein (wobei t eine Typvariable ist). Der Typ map putStrLn ls ist [IO()]. Deshalb erhalten Sie diese Fehlermeldung. Sie können dies selbst überprüfen, indem Sie die folgenden in ghci ausgeführt wird:

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

Eine Lösung für das Problem mapM verwendet, die die „monadischen“ -Version von map ist. Oder Sie können mapM_ verwenden, das ist das gleiche wie mapM, aber sammelt nicht die zurückgegebenen Werte von der Funktion. Da Sie den Rückgabewert von putStrLn nicht interessieren, ist es besser, hier mapM_ zu verwenden. mapM_ hat die folgende Art:

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

Hier ist, wie es zu benutzen:

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

Etwas, das ich gerne früher gelernt hätte, war, dass in Data.Traversable eine andere mapM definiert ist. Dieser mapM arbeitet zusätzlich zu Listen, wie z. B. Karten und Arrays, mit mehr Datenstrukturen. –

+5

Ich dachte immer, dass 'main' vom Typ' IO() 'sein sollte, wusste nie, dass es' forall t 'sein könnte. IO t'. Das zeigt, wie man jeden Tag etwas Neues lernen kann :-) –

19

Ayman Antwort am meisten Sinn für diese Situation macht. Wenn Sie [m()] haben und m() möchten, verwenden Sie sequence_, wobei m eine beliebige Monade sein kann, einschließlich IO.