Проблема:
Я пытаюсь понять состояние-монада.
Немного застрял, чтобы понять, как я могу его использовать, и я ищу пример.
Допустим, я хочу реализовать функцию [()] -> [Int]
:
numerate :: [()] -> [Int]
Должен ли я отображать каждый элемент списка в состояние, а затем сворачивать его?
Как я могу сделать это с помощью State
?
Ожидаемое поведение:
numerate [(), (), (), (), ()]
-- [1, 2, 3, 4, 5]
Спасибо!
Извиняюсь. Непонятно, в чем у вас проблема...
Я думал начать с чего-то вроде map (_ ->modify(+1)) xs, но потом... После сворачивания как вернуться к списку?
Мы можем реализовать объект 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 = []}]}
Оператор >>
в modify (1+) >> get
игнорирует предыдущее состояние?
@mkUltra: нет, >>
опускает результат предыдущего State s a
(то есть a
), но поскольку modify (1+)
является State Int ()
, результата все равно нет.
Мне интересно, можно ли сделать то же самое, используя только MonadWriter?
Что не работает с вашей попыткой?