Haskell: нельзя использовать "map putStrLn"? - PullRequest
52 голосов
/ 31 мая 2009

У меня есть список строк, и попробовал это:

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

Спасибо!

Ответы [ 2 ]

94 голосов
/ 31 мая 2009

Тип функции 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
20 голосов
/ 31 мая 2009

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

...