2009-05-31 3 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: б)). Но это было бы много проще просто использовать карту ...

Спасибо!

ответ

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

Что-то, чего я бы хотел, чтобы я узнал намного раньше, было то, что есть еще один mapM, определенный в Data.Traversable. Этот mapM работает с большим количеством структур данных в дополнение к спискам, таким как карты и массивы. –

+5

Я всегда думал, что 'main' должен быть типа' IO() ', никогда не знал, что это может быть' forall t. IO t'. Это показывает, как вы можете узнать что-то новое каждый день :-) –

19

ответ Айман делает самый смысл для этой ситуации. В общем, если у вас есть [m()], и вы хотите m(), тогда используйте sequence_, где m может быть любая монада, включая IO.