2009-05-31 13 views
50

Ho una lista di stringhe, e provato questo:Haskell: impossibile usare "map putStrLn"?

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

main = do 
     map PutStrLn list_of_strings 

che non ha funzionato, e non riesco a capire il perché.

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' 

Eventuali suggerimenti? Suppongo che abbia a che fare con la mappa che restituisce una lista e non un valore, ma non ho trovato un modo semplice per risolvere questo problema.

In questo momento, l'unico modo che conosco per stampare un elenco di stringhe è scrivere una funzione che itererà l'elenco, stampando ogni elemento (stampa se l'elenco è [a], ma stampa e riceva se è (a: b)). Ma sarebbe molto più semplice da usare per la mappa ...

Grazie!

risposta

89

Il tipo di funzione main deve essere IO t (dove t è una variabile di tipo). Il tipo di è [IO()]. Questo è il motivo per cui ricevi questo messaggio di errore. È possibile verificare questo da soli con il seguente in ghci:

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

Una soluzione al problema sta usando mapM, che è la versione "monade" di map. Oppure puoi usare mapM_ che è lo stesso di mapM ma non raccoglie i valori restituiti dalla funzione. Poiché non ti interessa il valore di ritorno di putStrLn, è più appropriato utilizzare mapM_ qui. mapM_ ha il tipo seguente:

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

Ecco come usarlo:

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

Qualcosa che vorrei aver imparato molto prima era che c'è un'altra mappaM definita in Data.Traversable. Questa mappaM lavora più strutture dati oltre a liste, come mappe e array. –

+5

Ho sempre pensato che 'main' dovrebbe essere di tipo' IO() ', non si sa mai che potrebbe essere 'forall t. IO t'. Questo mostra come puoi imparare qualcosa di nuovo ogni giorno :-) –

19

risposta di Ayman rende più senso per questa situazione. In generale, se si dispone di [m()] e si desidera m(), quindi utilizzare sequence_, dove m può essere qualsiasi monade tra cui IO.