- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Изучай Haskell во имя добра! - Миран Липовача
Шрифт:
Интервал:
Закладка:
После компиляции и запуска получаем:
True
2
"ха-ха"
3.2
[3,4,3]
Как вы могли заметить, это очень полезная функция. Помните, мы говорили о том, что действия ввода-вывода выполняются только из функции main или когда мы выполняем их в интерпретаторе GHCi? После того как мы напечатаем значение (например, 3 или [1, 2, 3]) и нажмём клавишу «Ввод», интерпретатор GHCi вызовет функцию print с введённым значением для вывода на терминал!
ghci> 3
3
ghci> print 3
3
ghci> map (++"!") ["хей","хо","ууу"]
["хей!","хо!","ууу!"]
ghci> print $ map (++"!") ["хей","хо","ууу"]
["хей!","хо!","ууу!"]
Как правило, мы хотим видеть строку на экране, не заключённую в кавычки, поэтому для печати строк обычно используется функция putStrLn. Но для печати значений других типов преимущественно используется функция print.
Функция when
Функция when находится в модуле Control.Monad (чтобы к ней обратиться, воспользуйтесь import Control.Monad). Она интересна, потому что выглядит как оператор управления ходом вычислений, но на самом деле это обычная функция. Она принимает булевское значение и действие ввода-вывода. Если булевское значение истинно, она возвращает второй параметр – действие ввода-вывода. Если первый параметр ложен, функция возвращает return (), то есть пустое действие.
Напишем программу, которая запрашивает строку текста и, если строка равна «РЫБА-МЕЧ», печатает её:
import Control.Monad
main = do
input <- getLine
when (input == "РЫБА-МЕЧ") $ do
putStrLn input
Без when нам понадобилось бы написать нечто такое:
main = do
input <- getLine
if (input == "РЫБА-МЕЧ")
then putStrLn input
else return ()
Как вы видите, функция when позволяет выполнить заданное действие в случае, если некоторое условие истинно, и ничего не делать в противном случае.
Функция sequence
Функция sequence принимает список действий ввода-вывода и возвращает одно действие ввода-вывода, последовательно выполняющее действия из списка. Результат выполнения этого действия – список результатов вложенных действий. Сигнатура типа функции: sequence :: [IO a] –> IO [a]. Выполним следующее:
main = do
a <– getLine
b <– getLine
c <– getLine
print [a,b,c]
То же самое, но с использованием функции sequence:
main = do
rs <– sequence [getLine, getLine, getLine]
print rs
Итак, выражение sequence [getLine, getLine, getLine] создаст действие ввода-вывода, которое выполнит функцию getLine три раза. Если мы свяжем это действие с именем, результат будет представлять собой список результатов действий из изначального списка, в нашем случае – то, что пользователь введёт с клавиатуры.
Функция sequence обычно используется, если мы хотим пройтись по списку функциями print или putStrLn. Вызов map print [1,2,3,4] не создаёт действия ввода-вывода – вместо этого создаётся список действий. Такой код на самом деле эквивалентен следующему:
[print 1, print 2, print 3, print 4]
Если мы хотим преобразовать список действий в действие, то необходимо воспользоваться функцией sequence:
ghci> sequence $ map print [1,2,3,4]
1
2
3
4
[(),(),(),()]
Но что это за [(),(),(),()] в конце вывода? При выполнении в GHCi действия ввода-вывода помимо самого действия выводится результат выполнения, но только если этот результат не есть (). Поэтому при выполнении в GHCi putStrLn "ха-ха" просто выводится строка – результатом является (). Если же попробовать ввести getLine, то помимо собственно ввода с клавиатуры будет выведено введённое значение – результатом является IO String.
Функция mapM
Поскольку применение функции, возвращающей действие ввода-вывода, к элементам списка и последующее выполнение всех полученных действий очень распространено, для этих целей были введены две вспомогательные функции – mapM и mapM_. Функция mapM принимает функцию и список, применяет функцию к элементам списка, сводит элементы в одно действие ввода-вывода и выполняет их. Функция mapM_ работает так же, но отбрасывает результат действия ввода-вывода. Она используется, когда нам не важен результат комбинированного действия ввода-вывода.
ghci> mapM print [1,2,3]
1
2
3
[(),(),()]
ghci> mapM_ print [1,2,3]
1
2
3
Функция forever
Функция forever принимает действие ввода-вывода – параметр и возвращает действие ввода-вывода – результат. Действие-результат будет повторять действие-параметр вечно. Эта функция входит в модуль Control.Monad. Следующая программа будет бесконечно спрашивать у пользователя строку и возвращать её в верхнем регистре:
import Control.Monad
import Data.Char
main = forever $ do
putStr "Введите что-нибудь: "
l <– getLine
putStrLn $ map toUpper l
Функция forM
Функция forM (определена в модуле Control.Monad) похожа на функцию mapM, но её параметры поменяны местами. Первый параметр – это список, второй – это функция, которую надо применить к списку и затем свести действия из списка в одно действие. Для чего это придумано? Если творчески использовать лямбда-выражения и ключевое слово do, можно проделывать такие фокусы:
import Control.Monad
main = do
colors <– forM [1,2,3,4] (a –> do
putStrLn $ "С каким цветом ассоциируется число "
++ show a ++ "?"
color <– getLine
return color)
putStrLn "Цвета, ассоциирующиеся с 1, 2, 3 и 4: "
mapM putStrLn colors
Вот что мы получим при запуске:
С каким цветом ассоциируется число 1?
белый
С каким цветом ассоциируется число 2?
синий
С каким цветом ассоциируется число 3?
красный
С каким цветом ассоциируется число 4?
оранжевый
Цвета, ассоциирующиеся с 1, 2, 3 и 4:
белый
синий
красный
оранжевый
Анонимная функция (a –> do ...) – это функция, которая принимает число и возвращает действие ввода-вывода. Нам пришлось поместить её в скобки, иначе анонимная функция решит, что следующие два действия ввода-вывода принадлежат ей. Обратите внимание, что мы производим вызов return color внутри блока do. Это делается для того, чтобы действие ввода-вывода, возвращаемое блоком do, содержало в себе цвет. На самом деле мы не обязаны этого делать, потому что функция getLine уже содержит цвет внутри себя. Выполняя color <– getLine и затем return color, мы распаковываем результат getLine и затем запаковываем его обратно, то есть это то же самое, что просто вызвать функцию getLine. Функция forM (вызываемая с двумя параметрами) создаёт действие ввода-вывода, результат которого мы связываем с идентификатором colors. Этот идентификатор – обычный список, содержащий строки. В конце мы распечатываем все цвета, вызывая выражение mapM putStrLn colors.
Вы можете думать, что функция forM имеет следующий смысл: «Создай действие ввода-вывода для каждого элемента в списке. Каков будет результат каждого такого действия, может зависеть от элемента, из которого оно создаётся. После создания списка действий исполни их и привяжи их результаты к чему-либо». Однако мы не обязаны их связывать – результаты можно просто отбросить.
На самом деле мы могли бы сделать это без использования функции forM, но так легче читается. Обычно эта функция используется, когда нам нужно отобразить (map) и объединить (sequence) действия, которые мы тут же определяем в секции do. Таким образом, мы могли бы заменить последнюю строку на выражение forM colors putStrLn.
Обзор системы ввода-вывода
В этой главе мы изучили основы системы ввода-вывода языка Haskell. Также мы узнали, что такое действия ввода-вывода, как они позволяют выполнять ввод-вывод, в какой момент они выполняются. Итак, повторим пройденное: действия ввода-вывода – это значения, такие же, как любые другие в языке Haskell. Мы можем передать их в функции как параметры, функции могут возвращать действия ввода-вывода в качестве результата. Они отличаются тем, что если они попадут в функцию main (или их введут в интерпретаторе GHCi), то будут выполнены. В этот момент они могут выводить что-либо на экран или управлять звуковыводящим устройством. Каждое действие ввода-вывода может содержать результат общения с реальным миром.

