или
>"не
>палиндром"
.
>respondPalindromes :: String -> String
>respondPalindromes =
> unlines .
> map (\xs -> if isPal xs then "палиндром" else "не палиндром") .
> lines
>isPal xs = xs == reverse xs
Всё вполне очевидно. Вначале преобразуем строку, например
>"слон\nпотоп\nчто-нибудь"
в список строк
>["слон", "потоп", "что-нибудь"]
Затем применяем анонимную функцию к элементам списка и получаем:
>["не палиндром", "палиндром", "не палиндром"]
Соединяем список обратно в строку функцией >unlines
. Теперь мы можем определить главное действие ввода-вывода:
>main = interact respondPalindromes
Протестируем:
>$ ./palindromes
>ха-ха
>не палиндром
>арозаупаланалапуазора
>палиндром
>печенька
>не палиндром
Хоть мы и написали программу, которая преобразует одну большую составную строку в другую составную строку, она работает так, как будто мы обрабатываем строку за строкой. Это потому что язык Haskell ленив – он хочет распечатать первую строку результата, но не может, поскольку пока не имеет первой строки ввода. Как только мы введём первую строку на вход, он напечатает первую строку на выходе. Мы выходим из программы по символу конца файла.
Также можно запустить нашу программу, перенаправив в неё содержимое файла. Например, у нас есть файл words.txt:
>кенгуру
>радар
>ротор
>мадам
Вот что мы получим, если перенаправим его на вход нашей программы:
>$ ./palindromes < words.txt
>не палиндром
>палиндром
>палиндром
>палиндром
Ещё раз: результат аналогичен тому, как если бы мы запускали программу и вводили слова вручную. Здесь мы не видим входных строк, потому что вход берётся из файла, а не со стандартного ввода.
К этому моменту, вероятно, вы уже усвоили, как работает ленивый ввод-вывод и как его можно использовать с пользой для себя. Вы можете рассуждать о том, каким должен быть выход для данного входа, и писать функцию для преобразования входа в выход. В ленивом вводе-выводе ничего не считывается со входа до тех пор, пока это не станет абсолютно необходимым для того, что мы собираемся напечатать.