Для начала напишем очень простую программу, которая открывает файл с именем girlfriend.txt и печатает его на терминале. В этом файле записаны слова лучшего хита Авриль Лавин, «Girlfriend». Вот содержимое girlfriend.txt:
>Эй! Ты! Эй! Ты!
>Мне не нравится твоя подружка!
>Однозначно! Однозначно!
>Думаю, тебе нужна другая!
Программа:
>import System.IO
>main = do
> handle <– openFile "girlfriend.txt" ReadMode
> contents <– hGetContents handle
> putStr contents
> hClose handle
Скомпилировав и запустив её, получаем ожидаемый результат:
>Эй! Ты! Эй! Ты!
>Мне не нравится твоя подружка!
>Однозначно! Однозначно!
>Думаю, тебе нужна другая!
Посмотрим, что у нас тут? Первая строка – это просто четыре восклицания: они привлекают наше внимание. Во второй строке Авриль сообщает вам, что ей не нравится ваша подружка. Третья строка подчёркивает, что неприятие это категорическое. Ну а четвёртая предписывает подружиться с кем-нибудь получше.
А теперь пройдёмся по каждой строке кода. Наша программа – это несколько действий ввода-вывода, «склеенных» с помощью блока >do
. В первой строке блока >do
мы использовали новую функцию, >openFile
. Вот её сигнатура: >openFile :: FilePath –> IOMode –> IO Handle
. Если попробовать это прочитать, получится следующее: «Функция >openFile
принимает путь к файлу и режим открытия файла (>IOMode
) и возвращает действие ввода-вывода, которое откроет файл, получит дескриптор файла и заключит его в результат».
Тип >FilePath
– это просто синоним для типа >String
; он определён так:
>type FilePath = String
Тип >IOMode
определён так:
>data IOMode = ReadMode | WriteMode | AppendMode | ReadWriteMode
Этот тип содержит перечисление режимов открытия файла, так же как наш тип содержал перечисление дней недели. Очень просто! Обратите внимание, что этот тип – >IOMode
; не путайте его с >IO Mode
. Тип >IO Mode
может быть типом действия ввода-вывода, которое возвращает результат типа >Mode
, но тип >IOMode
– это просто перечисление.
В конце концов функция вернёт действие ввода-вывода, которое откроет указанный файл в указанном режиме. Если мы привяжем это действие к имени, то получим дескриптор файла >(Handle)
. Значение типа >Handle
описывает, где находится наш файл. Мы будем использовать дескриптор для того, чтобы знать, из какого файла читать. Было бы глупо открыть файл и не связать дескриптор файла с именем, потому что с ним потом ничего нельзя будет сделать! В нашем случае мы связали дескриптор с идентификатором >handle
.
На следующей строке мы видим функцию >hGetContents
. Она принимает значение типа >Handle
; таким образом, она знает, с каким файлом работать, и возвращает значение типа