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


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




[12]

newtype State s a

= State { runState :: (s -> (a,s)) }

instance Monad (State s) where

return a= State $ \s

(State x) >>= f = State $ \s

> (a,s)

-> let (v,s) = x s in runState (f v) s

Величины в монаде State представлены как переходные функции из начального состояния в пару (величина, newState), и новое определение типа предусмотрено для описания этой конструкции: State s - тип величины типа a вне монады State с состоянием типа s. Конструктор типа State s является экземпляром класса Monad. Возвращаемая функция просто создает функцию перехода состояния, которая устанавливает величину, но оставляет состояние неизменным. Связующий оператор создает функцию перехода состояния, которая прилагает свой правосторонний аргумент к величине и новому состоянию из своего левого аргумента.

class MonadState m s m -> s where get :: m s put :: s -> m ()

instance MonadState (State s) s where get= State $ \s -> (s,s)

put s = State $ \ -> ((),s)

Класс MonadState обеспечивает стандартный, но очень простой интерфейс для монад State. Полученная функция извлекает состояние, записывая его как величину. Заданная функция устанавливает состояние монады и не выдает величину. Есть много дополнительных функциональных обеспечений, которые выполняют более сложные вычисления, построенные на получении и задании. Наиболее полезный - получения, которые извлекают функцию состояния. Другие указаны в документации для библиотеки монады State.

2.7.4. Пример

Простое применение монады State состоит в управлении произвольным состоянием генератора через многочисленные вызовы функции генерации.

Код, используемый в example15.hs

data MyType = MT Int Bool Char Int deriving Show

- Используя монаду State, мы можем определить функцию, которая возвращает -- произвольную величину и в то же время корректирует произвольный генератор -- состояния

getAny :: (Random a) => State StdGen a getAny = do g <- get

(x, g) <- return $ random g put g

ФП 02005-03 01

Лист 42

№ докум.

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


return x

- подобен getAny, но ограничивает произвольную возвращенную величину getOne:: (Random a) => (a,a) -> State StdGen a

getOne bounds= do g <- get

(x, g) <- return $ randomR bounds g

return x

-- Используя монаду State с состоянием StdGen, мы можем сформировать -- произвольные сложные типы без управления произвольным состоянием -- генератора

makeRandomValueST :: StdGen -> (MyType, StdGen) makeRandomValueST = runState (do n <- getOne (1, 100)

b <- getAny c <- getOne (a, z) m <- getOne (-n, n) return (MT n b c m))

2.8. Монада Reader

2.8.1. Обзор

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

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

Вычисления, которые считывают значения из разделённой среды.

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

Величины монады являются функциями от среды к величине. Связанная функция приложена к связанной величине, и обе имеют доступ к разделённой среде.

Полезна для:

Поддерживание переменных связей или другой разделённой среды.

Нуль и плюс:

Пример:

Reader [(String, Value)] a

2.8.2. Мотивация

Некоторые проблемы программирования требуют вычислений в пределах разделённой среды (как, например, установка переменных связей). Эти вычисления обычно считывают величины из среды и иногда выполняют подвычисления в модифицированной среде (например, с новыми или затеняющими связями), но они не требуют полной общности монады State. Монада Reader разработана специально для этих типов вычислений, и это часто является наиболее ясным и лёгким механизмом, чем использование монады State.

ФП 02005-03 01

№ докум.

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


£ то

£ то

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

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

newtype Reader e a= Reader { runReader :: (e -> a) }

instance Monad (Reader e) where

return a= Reader $ \e -> a

(Reader r) >>= f = Reader $ \e -> f (r e) e

Величины в монаде Reader - это функции от среды к величине. Чтобы извлечь конечную величину из вычисления в монаде Reader, необходимо просто приложить считыватель runReader к величине среды.

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

class MonadReader e m m -> e where

ask:: m e

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

instance MonadReader (Reader e) where ask= Reader id

local f c= Reader $ \e -> runReader c (f e)

asks:: (MonadReader e m) => (e -> a) -> m a

asks sel = ask >>= return . sel

Класс MonadReader выделяет множество подходящих функций, которые являются очень удобными при работе с монадой Reader. Запрашивающая функция извлекает среду, а локальная функция выполняет вычисление в модифицированной среде. Запрашивающая функция является удобной функцией, которая извлекает функцию текущей среды, и обычно используется с селекторной функцией или функцией поиска.

2.8.4.Пример

Рассмотрим проблему приписывания значений шаблонам, которые содержат переменные подстановки и включенные шаблоны. Используя монаду Reader, мы можем поддержать среду всех известных шаблонов и всех известных переменных связей. Затем, столкнувшись с переменной подстановкой, мы можем использовать запрашивающую функцию, чтобы найти величину переменной. Когда в шаблон включены новые определения переменных, мы можем использовать локальную функцию для разрешения

ФП 02005-03 01

Лист 44

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



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