Функция >shortLinesOnly
принимает строку – например, такую: >"коротко\nдлииииииииииинно\nкоротко"
. В этом примере в строке на самом деле три строки входных данных: две короткие и одна (посередине) длинная. В результате применения функции >lines
получаем список >["коротко", "длииииииииииинно", "коротко"]
. Затем список строк фильтруется, и остаются только строки, длина которых меньше 15 символов: >["коротко", "коротко"]
. Наконец, функция >unlines
соединяет элементы списка в одну строку, разделяя их символом перевода строки: >"коротко\nкоротко"
.
Попробуем проверить, что получилось. Сохраните этот текст в файле shortlines.txt:
>Я короткая
>И я
>А я длиииииииинная!!!
>А уж я-то какая длиннющая!!!!!!!
>Коротенькая
>Длиииииииииииииииииииииинная
>Короткая
Сохраните программу в файле shortlinesonly.hs и скомпилируйте её:
>$ ghc shortlinesonly.hs
>[1 of 1] Compiling Main ( shortlinesonly.hs, shortlinesonly.o )
>Linking shortlinesonly ...
Чтобы её протестировать, перенаправим содержимое файла shortlines.txt на её поток ввода:
>$ ./shortlinesonly < shortlines.txt
>Я короткая
>И я
>Коротенькая
>Короткая
Видно, что на терминал выведены только короткие строки.
Преобразование входного потока
Подобная последовательность действий – считывание строки из потока ввода, преобразование её функцией и вывод результата – настолько часто встречается, что существует функция, которая делает эту задачу ещё легче; она называется >interact
. Функция >interact
принимает функцию типа >String –> String
как параметр и возвращает действие ввода-вывода, которое примет некоторый вход, запустит заданную функцию и распечатает результат. Давайте изменим нашу программу так, чтобы воспользоваться этой функцией:
>main = interact shortLinesOnly
>shortLinesOnly :: String -> String
>shortLinesOnly = unlines . filter (\line -> length line < 15) . lines
Этой программой можно пользоваться, либо перенаправляя файл в поток ввода, либо вводя данные непосредственно с клавиатуры, строка за строкой. Результат будет одинаковым, однако при вводе с клавиатуры входные данные будут чередоваться с выходными.
Давайте напишем программу, которая постоянно считывает строку и затем говорит нам, является ли введённая строка палиндромом. Можно было бы использовать функцию >getLine
, чтобы она считывала строку, затем говорить пользователю, является ли она палиндромом, и снова запускать функцию >main
. Но легче делать это с помощью функции >interact
. Когда вы её используете, всегда думайте, как преобразовать некий вход в желаемый выход. В нашем случае мы хотим заменить строку на входе на