Существует много читателей канала RSS там, что люди привыкли использовать, и самое главное, RSS очень хорошо известен и был вокруг намного дольше. Почему путаница с чем-то, если это работает?
... Как ставит обновление состояния в первую очередь? Кажется, он просто сидит и ничего не делает ...
А, теперь я понял ваш вопрос. Вам интересно, как работает put
(и get
), верно?
Может быть, поможет пример на JavaScript (язык с фактическим изменяемым состоянием):
var s; // mutable state
function get() { return s; }
function put(x) { s = x; }
function tick() {
var n = get();
put(n + 1);
return n;
}
Надеюсь это показывает, что, хотя n
не меняется, внутреннее состояние все равно будет обновляться. Если вы выполните tick ()
дважды, состояние будет увеличено дважды.
Чтобы вернуться в Haskell, вот полное определение (соответствующих частей) монады State
:
newtype State s a = State { runState :: s -> (a, s) }
instance Monad (State s) where
return a = State $ \s -> (a, s)
m >>= k = State $ \s -> let
(a, r) = runState m s
in runState (k a) r
get = State $ \s -> (s, s)
put s = State $ \_ -> ((), s)
Теперь попробуйте еще больше расширить свой пример tick
, вставив вручную >> =
, return
, получить
и положить
. Надеюсь, станет более понятно, как работает State.
Вы совершенно правы. «Результатом» tick
«функции» является начальное значение состояния.
Конечно, tick
не настоящая «функция», а вычисление, которое может читать и записывать состояние перед выдачей результата.
В этом случае обновляется состояние , но вы по-прежнему возвращаете исходное значение состояния:
-- 4 is the inital state
ghci> runState tick 4
(4, 5)
-- 4 is the result of the tick computation, 5 is the updated state
В этом случае, поскольку вы больше никогда не проверяете состояние внутри галочки
, вы не видите измененное состояние. Однако, если какое-либо другое вычисление происходит после галочки
, он может видеть обновленное состояние.
Например, выполнение галочки
дважды (второй будет читать обновленное состояние):
-- 4 is the inital state
ghci> runState (tick >> tick) 4
(5, 6)
-- 5 is the result of the tick computation executed twice,
-- 6 is the updated state
может помочь записать его, используя нотацию do
tick :: State Int Int
tick = do
n <- get -- get the state
put (n+1) -- save an incremented state
return n -- return the original state
, в то время как put (n + 1)
не влияет на результат вычисления , он действительно изменяет состояние, которое содержится в монаде состояний.