Мы можем реализовать объект State
, который будет увеличивать состояние и возвращать его, например:
incState :: State Int Int
incState = modify (1+) >> get
Тогда мы можем запустить это State Int Int
по списку, например:
numerate :: (Traversable t) => t a -> t Int
numerate = flip evalState 0 . traverse (const incState)
Например:
Prelude Control.Monad.State> numerate Nothing
Nothing
Prelude Control.Monad.State> numerate (Just 'a')
Just 1
Prelude Control.Monad.State> numerate (Just 0)
Just 1
Prelude Control.Monad.State> numerate [1,4,2,5]
[1,2,3,4]
Prelude Control.Monad.State> numerate [(), (), ()]
[1,2,3]
Мы также можем работать с другими перемещаемыми структурами, такими как Tree
, например:
Prelude Control.Monad.State Data.Tree> numerate (Node 'a' [Node 'b' [], Node 'c' []])
Node {rootLabel = 1, subForest = [Node {rootLabel = 2, subForest = []},Node {rootLabel = 3, subForest = []}]}