Ремонт принтеров, сканнеров, факсов и остальной офисной техники


назад Оглавление вперед




[11]

В этой статье мы ссылались на унарные величины, как на вычисления. Тем не менее, величины в монаде IO часто называют действиями ввода/вывода, и мы используем эту терминологию здесь. В языке Haskell основная функция верхнего уровня должна иметь тип IO (), чтобы программы являлись естественно структурированными на верхнем уровне в виде необходимой последовательности действий ввода/вывода и вызывали функциональный стиль кода. Функции, экспортированные из модуля IO, не выполняют операций ввода/вывода сами. Они возвращают действия ввода/вывода, которые описывают операцию ввода/вывода, которая должна выполниться. Действия ввода/вывода объединены в пределах монады IO (в чисто функциональном стиле), чтобы создавать более сложные действия ввода/вывода, заканчивающиеся конечным действием ввода/вывода, которое является основной величиной программы.

Стандартный модуль Prelude и модуль IO определяют много функций, которые могут быть использованы в пределах монады IO, и любой программист на языке Haskell несомненно будет знаком с некоторыми из них. Эта статья только обсудит унарные аспекты монады IO; не полный ряд функций способен выполнять действия ввода/вывода.

Конструктор типа IO - это экземпляр класса Monad и класса MonadError, где ошибки имеют тип IOError. Недостаток определён для того, чтобы отбросить ошибку, созданную из аргумента строки. В пределах монады IO вы можете использовать исключительные механизмы из модуля Управления.Монада. Ошибка в библиотеке шаблона монад, если вы импортируете модуль. Те же механизмы имеют альтернативные имена, экспортированные модулем IO:ioError и catch.

instance Monad IO where return a = ... m >>= k = ...

data IOError

ioError ioError

userError userError

catch catch

try try f

... -- функция из a -> IO a

... -- выполняет действие ввода/вывода m и привязывает

-- величину на k- ый ввод ioError (userError s)

IOError -> IO a

String -> IOError

IO a -> (IOError -> IO a) -> IO a

IO a -> IO (Either IOError a) catch(do r <- f

return (Right r)) (return . Left)

ФП 02005-03 01

Лист 39

№ докум.

Копипова Формат


Монада IO включена в состав библиотеки шаблонов монады как пример класса MonadError.

instance Error IOError where

instance MonadError IO where

throwError = ioError catchError = catch

Модуль IO экспортирует специальную функцию, вызывающую попытку выполнения действий ввода/вывода, и возвращает результат Right, если действие успешно, или Left IOError, если была найдена ошибка ввода/вывода.

2.6.4. Пример

Этот пример показывает частичную реализацию команды tr, которая копирует стандартный входной поток в стандартный выходной поток с символьными переводами, контролируемыми командной строкой аргументов. Это демонстрирует использование исключения, обрабатывающего механизмы класса MonadError с монадой IO.

Код, имеющийся в example14.hs

import Monad import System import IO

import Control.Monad.Error

- переводится символ из setl в соответствующий символ в set2

translate:

translate [] c=

translate (x:xs) [] c=

translate (x:xs) [y] c=

translate (x:xs) (y:ys) c=

-- переводится целая строка translateString

translateString setl set2str

String -> String -> Char -> Char c

if x == c then else translate xs [] c if x == c then y else translate xs [y] c if x == c then y else translate xs ys c

String -> String -> String -> String map (translate setl set2) str

usage :: IOError -> IO () usage e = do

putStrLn "Usage: ex14 setl set2"

putStrLn "Переводит символы из setl на stdin в соответствующие" putStrLn " символы из set2 и записывает перевод на stdout."

-- переводит stdin в stdout на основаннии командных аргументов main:: IO ()

main= (do

ФП 02005-03 01

Лист 40

Копиоова Формат


[set1,set2] <- getArgs

contents <- hGetContents stdin

putStr $ translateString set1 set2 contents)

"catchError" usage

2.7. Монада State 2.7.1. Обзор

Таблица 7. Свойства монады State

Тип вычисления:

Вычисления, которые поддерживают состояние.

Стратегия связывания:

Связь управляет параметром состояния через последовательность связанных функций, поэтому одни и те же величины состояния никогда не используются дважды, создавая иллюзию коррекции на месте.

Полезна для:

Построение вычислений из последовательностей операций, которые требуют разделенного состояния.

Нуль и плюс:

Пример:

State st a

2.7.2. Мотивация

Чистый функциональный язык не может корректировать величины на месте, поскольку это нарушает прозрачность. Общая идиома для имитации таких вычислений состояния - «управлять» параметром состояния через последовательность функций:

data MyType = MT Int Bool Char Int deriving Show

makeRandomValue :: makeRandomValue g =

StdGen -> (MyType, StdGen) let (n, g1) = randomR (1,100) g (b, g2) = random g1 (c, g3) = randomR (a, z) g2 (m, g4) = randomR (-n, n) g3 in (MT n b c m, g4)

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

2.7.3. Определение

Показанное здесь определение использует классы многопараметрического типа и funDeps, которые не являются стандартными в языке Haskell 98. Нет необходимости полностью понимать эти детали, чтобы использовать монаду State.

ФП 02005-03 01

Лист 41

№ докум.

Копипова Фопмат



[стр.Начало] [стр.1] [стр.2] [стр.3] [стр.4] [стр.5] [стр.6] [стр.7] [стр.8] [стр.9] [стр.10] [стр.11] [стр.12] [стр.13] [стр.14] [стр.15] [стр.16] [стр.17] [стр.18] [стр.19] [стр.20] [стр.21] [стр.22] [стр.23] [стр.24] [стр.25]