Хаскелл:нельзя использовать «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)).Но это было бы много проще просто использовать карту...
Спасибо!
Решение
Тип 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
Другие советы
Ответ Аймана имеет наибольший смысл в этой ситуации.В общем, если у вас есть [m ()]
и вы хотите m ()
, затем используйте sequence_
, где m
может быть любой монадой, включая IO
.