2009-05-31 14 views
50

mam listy ciągów i wypróbowane to:Haskell: nie można użyć "map putStrLn"?

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

main = do 
     map PutStrLn list_of_strings 

To nie działa, i nie mogę zrozumieć, dlaczego.

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' 

Jakieś wskazówki? Przypuszczam, że ma to związek z mapą zwracającą listę, a nie wartością, ale nie znalazłem łatwego sposobu na rozwiązanie tego problemu.

W tej chwili jedynym sposobem, w jaki mogę wydrukować listę napisów, jest napisanie funkcji, która będzie iterować listę, drukowanie każdego elementu (drukowanie, jeśli lista jest [a], ale drukowanie i rekurencja, jeśli jest (a: b)). Ale byłoby to znacznie łatwiejsze w użyciu, gdybym używał mapy ...

Dzięki!

Odpowiedz

89

Typ funkcji main powinien być IO t (gdzie t jest zmienną typu). Typ map putStrLn ls to [IO()]. To dlatego otrzymujesz ten komunikat o błędzie. Można to sprawdzić samemu wykonując następujące czynności w ghci:

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

Jednym z rozwiązań tego problemu jest użycie mapM, która jest „monadycznego” wersja map. Lub możesz użyć mapM_, który jest taki sam jak mapM, ale nie zbiera zwróconych wartości z funkcji. Ponieważ nie interesuje Cię wartość zwracana przez putStrLn, bardziej odpowiednie jest użycie tutaj mapM_. mapM_ ma następujący typ:

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

Oto jak go używać:

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

Coś, czego chciałbym się nauczyć wcześniej, było to, że istnieje inna mapa M zdefiniowana w Data.Traversable. Ta mapaM działa więcej struktur danych oprócz list, takich jak mapy i tablice. –

+5

Zawsze uważałem, że 'main' powinno być typu' IO() ', nigdy nie wiedziałem, że może to być' na wszelki wypadek '. IO t'. To pokazuje, jak możesz nauczyć się czegoś nowego każdego dnia :-) –

19

odpowiedź Ayman sprawia największy sens dla tej sytuacji. Ogólnie rzecz biorąc, jeśli masz [m()] i chcesz m(), użyj sequence_, gdzie m może być dowolną monadą, w tym IO.