Читаем Учебник по Haskell полностью

main = try ‘catch‘ const (msg >> main)

where msg = putStrLn ”Wrong filename, try again.”

А что делать если нам хочется различать ошибки по типу и предпринимать различные действия в зави-

симости от типа ошибки? Ошибки распознаются с помощью специальных предикатов, которые определены

в модуле System.IO.Error. Рассмотрим некоторые из них.

136 | Глава 8: IO

Например с помощью с помощью предиката isDoesNotExistErrorType мы можем опознать ошибки,

которые случились из-за того, что один из аргументов функции не существует. С помощью предиката

isPermissionErrorType мы можем узнать, что ошибка произошла из-за того, что мы пытались получить до-

ступ к данным, на которые у нас нет прав. Мы можем, немного изменив функцию-обработчик исключений,

выводить более информативные сообщения об ошибках перед перезапуском:

main = try ‘catch‘ handler

handler :: IOError -> IO ()

handler = ( >> main) . putStrLn . msg2 . msg1

msg1 e

| isDoesNotExistErrorType e = ”File does not exist. ”

| isPermissionErrorType e

= ”Access denied. ”

| otherwise

= ””

msg2 = (++ ”Try again.”)

В модуле System.IO.Error вы можете найти ещё много разных предикатов.

Потоки текстовых данных

Обмен данными, чтение и запись происходят с помощью потоков. Каждый поток имеет дескриптор

(handle), через него мы можем общаться с потоком, например считывать данные или записывать. Функции

для работы с потоками данных определены в модуле System.IO.

В любой момент в системе открыты три стандартных потока:

• stdin – стандартный ввод

• stdout – стандартный вывод

• stderr – поток ошибок и отладочных сообщений

Например когда мы выводим строку на экран, на самом деле мы записываем строку в поток stdout. А

когда мы читаем символ с клавиатуры, мы считываем его из потока stdin.

Файлы также являются потоками. При открытии файлу присваивается дескриптор через который, мы

можем обмениваться данными. Файл может быть открыт для чтения, записи, дополнения (записи в конец

файла) или чтения и записи. Файл открывается функцией:

openFile :: FilePath -> IOMode -> IO Handle

Функция принимает путь к файлу и режим работы с файлом и возвращает дескриптор. Режим может

принимать одно из значений:

ReadMode – чтение

WriteMode – запись

AppendMode – добавление (запись в конец файла)

ReadWriteMode – чтение и запись

Открыв дескриптор, мы можем начать обмениваться данными. Для этого определены функции аналогич-

ные тем, что мы уже рассмотрели. Функции для записи данных:

-- запись символа

hPutChar :: Handle -> Char -> IO ()

-- запись строки

hPutStr :: Handle -> String -> IO ()

-- запись строки с переносом каретки

hPutStrLn :: Handle -> String -> IO ()

-- запись значения

hPrint :: Show a => Handle -> a -> IO ()

Типичные задачи IO | 137

Все функции принимают первым аргументом дескриптор потока. Дескриптор должен позволять записы-

вать данные. Например для дескриптора, открытого в режиме ReadMode, выполнение этих функций приведёт

к ошибке.

Из потоков также можно читать данные. Эти функции похожи на те, что мы уже рассмотрели:

-- чтение одного символа

hGetChar :: Handle -> IO Char

-- чтение строки

hGetLine :: Handle -> IO String

-- ленивое чтение строки

hGetContents :: Handle -> IO String

Как только, мы закончим работу с файлом, его необходимо закрыть. Нам нужно освободить дескриптор.

Сделать это можно функцией hClose:

hClose :: Handle -> IO ()

Стандартные функции ввода/вывода, которые мы рассмотрели ранее определены через функции работы

с дескрипторами. Например так мы выводим строку на экран:

putStr

:: String -> IO ()

putStr s

=

hPutStr stdout s

А так читаем строку с клавиатуры:

getLine

:: IO String

getLine

=

hGetLine stdin

В этих функциях используются дескрипторы стандартных потоков данных stdin и stdout. Отметим функ-

цию withFile:

withFile :: FilePath -> IOMode -> (Handle -> IO r) -> IO r

Она открывает файл в заданном режиме выполняет функцию на его дескрипторе и и закрывает файл.

Например через эту функцию определены функции readFile и appendFile:

appendFile

:: FilePath -> String -> IO ()

appendFile f txt = withFile f AppendMode (\hdl -> hPutStr hdl txt)

writeFile :: FilePath -> String -> IO ()

writeFile f txt = withFile f WriteMode (\hdl -> hPutStr hdl txt)

8.5 Форточка в мир побочных эффектов

В самом начале главы я сказал о том, что из мира IO

нет выхода. Нет функции с типом IO a -> a. На самом деле выход есть. Функция с таким типом живёт в

модуле System.IO.Unsafe:

unsafePerformIO :: IO a -> a

Длинное имя функции намекает на то, что её необходимо использовать с крайней осторожностью. По-

скольку последствия могут быть непредсказуемыми.

Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных