Возможно ли в Haskell применить функцию putStrLn к каждому элементу списка строк, вывести его на экран, не будучи рекурсивным - PullRequest
0 голосов
/ 06 марта 2019

Я пытаюсь создать функцию, которая принимает список строк и выполняет команду putStrLn или print (я думаю, что они в основном эквивалентны, пожалуйста, исправьте меня, если я ошибаюсь, так как я все еще новичок в Haskell) к каждому элементу и распечатать его на экране моего терминала.Я экспериментировал с функцией map, а также с лямбда / анонимными функциями, так как я уже знаю, как сделать это рекурсивно, но хотел попробовать более сложную нерекурсивную версию.map возвратил список типа IO (), который не был тем, к чему я стремился, и мои попытки лямбда-функций не соответствовали плану.Основной код был:

test :: [String] -> something
test x = map (\a->putStrLn a) x -- output for this function would have to be [IO()]

Не совсем уверен, каким должен был быть вывод функции, что также вызывало у меня проблемы.

Я думал о создании переменной temp :: String и добавлял каждую строку к значению temp, а затем putStrLn temp, но не знал, как это сделать полностью.Я хотя бы с использованием where был бы жизнеспособным, но я все еще сталкивался с проблемами.Я знаю, как это сделать на таких языках, как Java и C, но я все еще новичок в Haskell.Любая помощь будет оценена.

Ответы [ 2 ]

5 голосов
/ 06 марта 2019

Существует специальная версия map, которая работает с монадическими функциями, она называется mapM:

test :: [String] -> IO [()]
test x = mapM putStrLn x

Обратите внимание, что в этом случае тип возврата test представляет собой список единиц - это потому, что каждый вызов putStrLn возвращает единицу, поэтому результатом применения его к каждому элементу в списке будет список единиц. Если вы не хотите иметь дело с этой глупостью, и тип возврата должен быть простой единицей, используйте специальную версию mapM_:

test :: [String] -> IO ()
test x = mapM_ putStrLn x
2 голосов
/ 06 марта 2019

Я думал о создании переменной temp :: String, чтобы каждая строка добавлялась к temp, а затем putStrLn temp

Хорошая идея. Паттерн «рендеринг сообщения», а затем отдельного «генерация сообщения» часто бывает полезен на длительный срок.

test xs = let temp = unlines (map show xs)
          in putStrLn temp

Или просто

test xs = putStrLn (unlines (show <$> xs))

Или

test = putStrLn . unlines . map show

Не совсем уверен, каким должен был быть вывод функции, что также вызывало у меня проблемы.

Хорошо, вы составили список действий ввода-вывода:

test :: [String] -> [IO ()]
test x = map (\a->putStrLn a) x

Итак, с этим списком действий ввода-вывода, когда вы хотите их выполнить? Сейчас? Только раз? Первый много раз, остальные никогда? В каком порядке?

Вероятно, вы хотите выполнить их все сейчас Давайте также уменьшим (\a -> putStrLn a) до putStrLn, поскольку это означает то же самое:

test :: [String] -> IO ()
test x = sequence_ (map (\a->putStrLn a) x)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...