52700.fb2
where read
file = readFile file >>= putStrLn >> return file
append file = msg2 >> getLine >>= appendFile file
msg1
= putStr ”input file: ”
msg2
= putStr ”input text: ”
В самом левом вызове getLine мы читаем имя файла, затем оно используется в локальной функции
read. Там мы читаем содержание файла (readLine), выводим его на экран (putStrLn), и в самом конце мы
возвращаем из функции имя файла. Оно нам понадобится в следующей части программы, в которой мы
будем читать новые записи и добавлять их в файл. Новая запись читается функцией getLine в локальной
функции append.
Сохраним в модуле File. hs и посмотрим, что у нас получилось. Перед этим создадим в текущей дирек-
тории тестовый пустой файл под именем test. В него мы будем добавлять новые записи.
*Prelude> :l File
[1 of 1] Compiling File
( File. hs, interpreted )
Ok, modules loaded: File.
*File> main
input file: test
input text: Hello!
*File> main
input file: test
Hello!
input text: Hi)
*File> main
input file: test
Hello!Hi)
В самом начале наш файл пуст, поэтому сначала мы видим пустую строчку вместо содержания, но потом
мы начинаем добавлять в него новые записи.
Ленивое и энергичное чтение файлов
С чтением файлов связана одна тонкость. Функция readFile читает содержимое файла в ленивом стиле.
Подробнее о ленивой стратегии вычислений мы поговорим в следующей главе. По ка отметим, что readFile
не читает следующую порцию файла до тех пор пока она не понадобится в программе. Иногда это очень удоб-
но. Например мы можем читать содержание очень большого файла и составлять какую-нибудь статистику
на основе прочитанного текста. При этом в памяти будет храниться лишь малая часть файла. Но иногда
это свойство мешает. Рассмотрим такую задачу: перевернуть текст в файле под именем ”test”. Мы должны
сначала считать текст из файла, затем перевернуть его и в конце записать в тот же файл. Мы могли бы
написать эту программу так:
module Main where
main :: IO ()
main = inFile reverse ”test”
inFile :: (String -> String) -> FilePath -> IO ()
inFile fun file = writeFile file . fun =<< readFile file
Типичные задачи IO | 131
Функция inFile обновляет текст файла с помощью некоторого преобразование. Но если мы запустим эту
программу:
*Main> main
*** Exception: test: openFile: resource busy (file is locked)