Изучай Haskell во имя добра! (Липовача) - страница 129

Функция >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. Когда вы её используете, всегда думайте, как преобразовать некий вход в желаемый выход. В нашем случае мы хотим заменить строку на входе на