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


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




[9]

instance Monad Maybe where

return=Just

fail=Nothing

Nothing >>= f=Nothing

(Just x) >>= f=f x

instance MonadPlus Maybe where

mzero= Nothing

Nothing "mplus" x = x x "mplus" = x

2.3.4. Пример

Общий пример состоит в объединении словарных поисков. Даны словарь, который отображает полные имена, чтобы пересылать по адресам, другой словарь, который отображает прозвища, чтобы пересылать по адресам, и третий, который отображает почтовые адреса в пересылочные предпочтения; вы могли бы создать функцию, которая находит предпочтения человека, основываясь на полном имени или на прозвище.

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

data MailPref= HTML Plain

data MailSystem = ...

getMailPrefs::

getMailPrefs sys name =

let nameDB = fullNameDB sys nickDB = nickNameDB sys prefDB = prefsDB sys addr <- (lookup name nameDB) lookup addr prefDB

MailSystem -> String -> Maybe MailPref

"mplus" (lookup name nickDB)

2.4. Монада Error 2.4.1. Обзор

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

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

Вычисления, которые могут изменять или отбрасывать исключения.

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

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

Полезна для:

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

ФП 02005-03 01

№ докум.

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


£ то

Нуль и плюс:

Нуль представлен пустой ошибкой, а операция «плюс» исполняет роль второго аргумента, если первый терпит неудачу.

Пример:

Either String a

2.4.2.Мотивация

Монада Error (также её называют монадой Exception) олицетворяет стратегию объединённых вычислений, которые могут отбрасывать исключения с помощью обхода связанной функции от точки, где отброшено исключение, к точке, которая им управляет.

Класс MonadError работает над типом информации об ошибке и конструктором типа монады. Распространено использование Either String, как конструктора типа монады для монады Error, где описания ошибки имеют форму строк. В этом случае и многих других распространённых случаях результирующая монада уже определена как пример класса MonadError. Вы можете также определить ваш собственный тип ошибки и/или использовать конструктор типа монады, отличные от Either String или Either IOError. В этих случаях вам придется точно определить экземпляры классов Error и/или MonadError.

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

Описание класса MonadError ниже использует мультипараметрические типовые классы и funDeps, которые являются языковыми расширениями, не найденными в стандартном Haskell 98. Вам не нужно понимать их, чтобы увидеть преимущество класса MonadError.

class Error a where

noMsg:: a

strMsg:: String -> a

class (Monad m) => MonadError e m m -> e where throwError:: e -> m a

catchError:: m a -> (e -> m a) -> m a

Функция throwError используется в унарных вычислениях, чтобы начать обработку исключений. Функция catchError связывает управляющую функцию, чтобы управлять предыдущими ошибками и возвращаться к нормальному выполнению. Общая идиома:

do { actionl; action2; action3 } "catchError" handler

где функции action могут вызвать throwError. Заметьте, что handler и создатель блоков должны иметь одинаковый возвращаемый тип.

Определение типа конструктора Either e, как примера класса MonadError, является правильным. Опишем следующие условия: Left используется для ошибочных значений, а Right используется для правильных значений.

instance MonadError (Either e) where

ФП 02005-03 01

Лист 34

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


throwError

(Left e) "catchError" handler a "catchError"

handler e a

2.4.4. Пример

Это пример, который демонстрирует использование обычного типа данных Error с использованием механизмов исключений throwError и catchError. В примере пытаются разобрать шестнадцатеричные числа и отбросить исключения, если встречается неправильный символ. Мы используем обычный тип данных Error, чтобы записать размещение разбирающейся ошибки. Исключения отыскиваются путём вызванной функции и сопровождаемым печатью информативным сообщением об ошибке.

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

- Это тип нашего представления разбираемой ошибки.

data ParseError = Err {location::Int, reason::String}

-- Мы делаем её экземпляром класса Error instance Error ParseError where

noMsg = Err 0 "Parse Error"

strMsg s = Err 0 s

-- Для нашего конструктора типа монады мы используем Either ParseError, -- которая выдает неудачный результат при использовании Left ParseError или -- удачный результат типа а, используя Right a. type ParseMonad = Either ParseError

-- parseHexDigit пытается превратить единственную шестнадцатиричную цифру в -- целое в монаде ParseMonad и отбросить ошибку с неправильным символом parseHexDigit:: Char -> Int -> ParseMonad Integer

parseHexDigit c idx= if isHexDigit c

then return (toInteger (digitToInt c))

throwError (Err idx ("Invalid character " ++ [c] ++ ""))

-- parseHex переводит строку, состоящую из шестнадцатиричных чисел в -- целое в монаде ParseMonad. Разбираемая ошибка из parseHexDigit -- вызовет исключительный возврат из parseHex. parseHex:: String -> ParseMonad Integer

parseHex s= parseHex s 0 1

parseHex [] val = return val

parseHex (c:cs) val idx = do d <- parseHexDigit c idx

parseHex cs ((val * 16) + d) (idx + 1)

-- toString преобразовывает целое в строку в монадеParseMonad toString:: Integer -> ParseMonad String

ФП 02005-03 01

Лист 35

№ докум.

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



[стр.Начало] [стр.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]