Control.Monad.Trans.State.Lazy
| Авторские права | (c) Andy Gill 2001, (c) Oregon Graduate Institute of Science and Technology, 2001 |
|---|---|
| Лицензия | BSD-стиль (см. файл LICENSE) |
| Поддержка | ross@soi.city.ac.uk |
| Устойчивость | экспериментальная |
| Переносимость | переносимая |
| Безопасный Haskell | Безопасный |
| Язык | Haskell98 |
Содержание
Описание
Ленивые монады состояния, передающие изменяемое состояние через вычисление. См. примеры ниже.
Некоторые вычисления могут не требовать полной мощи трансформаторов состояния:
- Для чтения только состояния см. Control.Monad.Trans.Reader.
- Для накопления значения без его использования по пути см. Control.Monad.Trans.Writer.
В этой версии последовательность вычислений является ленивой, поэтому, например, следующее производит применимый результат:
evalState (sequence $ repeat $ do { n <- get; put (n*2); return n }) 1
Для строгой версии с тем же интерфейсом см. Control.Monad.Trans.State.Strict.
Монада состояния
type State s = StateT s Identity Исходный код
Монада состояния, параметризованная типом s состояния, которое нужно передать.
Функция return оставляет состояние неизменным, в то время как >>= использует конечное состояние первого вычисления в качестве начального состояния второго.
Аргументы
| :: Monad m | |
| => (s -> (a, s)) | чистая трансформация состояния |
| -> StateT s m a | эквивалентное вычисление с передачей состояния |
Создаёт вычисление монады состояния из функции. (Обратная функция runState.)
Аргументы
| :: State s a | вычисление с передачей состояния для выполнения |
| -> s | начальное состояние |
| -> (a, s) | возвращаемое значение и конечное состояние |
Распаковывает вычисление монады состояния в функцию. (Обратная функция state.)
Аргументы
| :: State s a | вычисление с передачей состояния для выполнения |
| -> s | начальное значение |
| -> a | возвращаемое значение вычисления со состоянием |
Вычисляет вычисление со состоянием с заданным начальным состоянием и возвращает конечное значение, отбрасывая конечное состояние.
Аргументы
| :: State s a | вычисление с передачей состояния для выполнения |
| -> s | начальное значение |
| -> s | конечное состояние |
Вычисляет вычисление со состоянием с заданным начальным состоянием и возвращает конечное состояние, отбрасывая конечное значение.
mapState :: ((a, s) -> (b, s)) -> State s a -> State s b Исходный код
Преобразует возвращаемое значение и конечное состояние вычисления с помощью заданной функции.
withState :: (s -> s) -> State s a -> State s a Исходный код
withState f m выполняет действие m над состоянием, изменённым применением f.
Трансформатор монады состояния
newtype StateT s m a Исходный код
Трансформатор монады состояния, параметризованный:
-
s- Состояние. -
m- Внутренняя монада.
Функция return оставляет состояние неизменным, в то время как >>= использует конечное состояние первого вычисления в качестве начального состояния второго.
Реализации
evalStateT :: Monad m => StateT s m a -> s -> m a Исходный код
Вычисляет вычисление со состоянием с заданным начальным состоянием и возвращает конечное значение, отбрасывая конечное состояние.
evalStateTm s =liftMfst(runStateTm s)
execStateT :: Monad m => StateT s m a -> s -> m s Исходный код
Вычисляет вычисление со состоянием с заданным начальным состоянием и возвращает конечное состояние, отбрасывая конечное значение.
execStateTm s =liftMsnd(runStateTm s)
mapStateT :: (m (a, s) -> n (b, s)) -> StateT s m a -> StateT s n b Исходный код
Преобразует возвращаемое значение и конечное состояние вычисления с помощью заданной функции.
withStateT :: (s -> s) -> StateT s m a -> StateT s m a Source
withStateT f m выполняет действие m над состоянием, изменённым путём применения f.
withStateTf m =modifyf >> m
Операции со состоянием
get :: Monad m => StateT s m s Source
Получение текущего значения состояния в монаде.
put :: Monad m => s -> StateT s m () Source
put s устанавливает состояние в монаде на значение s.
modify :: Monad m => (s -> s) -> StateT s m () Source
modify f — это действие, которое обновляет состояние результатом применения f к текущему состоянию.
modify' :: Monad m => (s -> s) -> StateT s m () Source
Вариант modify, в котором вычисление строго относится к новому состоянию.
gets :: Monad m => (s -> a) -> StateT s m a Source
Получение конкретного компонента состояния с помощью функции-проекции.
Поднятие других операций
liftCallCC :: CallCC m (a, s) (b, s) -> CallCC (StateT s m) a b Source
Единое поднятие операции callCC в новую монаду. В этой версии при входе в продолжение происходит откат к исходному состоянию.
liftCallCC' :: CallCC m (a, s) (b, s) -> CallCC (StateT s m) a b Source
Поднятие операции callCC в новую монаду «на месте». Эта версия использует текущее состояние при входе в продолжение. Она не удовлетворяет законам монады-трансформатора.
liftCatch :: Catch e m (a, s) -> Catch e (StateT s m) a Source
Поднять операцию catchE в новую монаду.
liftListen :: Monad m => Listen w m (a, s) -> Listen w (StateT s m) a Source
Поднять операцию listen в новую монаду.
liftPass :: Monad m => Pass w m (a, s) -> Pass w (StateT s m) a Source
Поднять операцию pass в новую монаду.
Примеры
Монады состояния
Парсер из ParseLib с Hugs:
type Parser a = StateT String [] a ==> StateT (String -> [(a,String)])
Например, item можно записать как:
item = do (x:xs) <- get
put xs
return x
type BoringState s a = StateT s Identity a
==> StateT (s -> Identity (a,s))
type StateWithIO s a = StateT s IO a
==> StateT (s -> IO (a,s))
type StateWithErr s a = StateT s Maybe a
==> StateT (s -> Maybe (a,s))
Счёт
Функция для инкрементирования счётчика. Взято из статьи "Generalising Monads to Arrows", Джон Хьюз (http://www.cse.chalmers.se/~rjmh/), ноябрь 1998 года:
tick :: State Int Int
tick = do n <- get
put (n+1)
return n
Добавить единицу к заданному числу с помощью монады состояния:
plusOne :: Int -> Int plusOne n = execState tick n
Искусственный пример сложения. Работает только с положительными числами:
plus :: Int -> Int -> Int plus n x = execState (sequence $ replicate n tick) x
Разметка деревьев
Пример из The Craft of Functional Programming, Саймон Томпсон (http://www.cs.kent.ac.uk/people/staff/sjt/), Addison-Wesley 1999: "Учитывая произвольное дерево, преобразуйте его в дерево целых чисел, в котором исходные элементы заменены натуральными числами, начиная с 0. Один и тот же элемент должен заменяться одним и тем же числом в каждом вхождении, и когда мы встречаем ещё не посещённый элемент, мы должны найти «новое» число, чтобы сопоставить его с ним:"
data Tree a = Nil | Node a (Tree a) (Tree a) deriving (Show, Eq) type Table a = [a]
numberTree :: Eq a => Tree a -> State (Table a) (Tree Int)
numberTree Nil = return Nil
numberTree (Node x t1 t2) = do
num <- numberNode x
nt1 <- numberTree t1
nt2 <- numberTree t2
return (Node num nt1 nt2)
where
numberNode :: Eq a => a -> State (Table a) Int
numberNode x = do
table <- get
case elemIndex x table of
Nothing -> do
put (table ++ [x])
return (length table)
Just i -> return i
numTree применяет numberTree с начальным состоянием:
numTree :: (Eq a) => Tree a -> Tree Int numTree t = evalState (numberTree t) []
testTree = Node "Zero" (Node "One" (Node "Two" Nil Nil) (Node "One" (Node "Zero" Nil Nil) Nil)) Nil numTree testTree => Node 0 (Node 1 (Node 2 Nil Nil) (Node 1 (Node 0 Nil Nil) Nil)) Nil
© The University of Glasgow and others
Licensed under a BSD-style license (see top of the page).
https://downloads.haskell.org/~ghc/7.10.3/docs/html/libraries/transformers-0.4.2.0/Control-Monad-Trans-State-Lazy.html