Кто-то может обойти меня через эту функцию Haskell (Связанная монада состояния)?

Существует много читателей канала RSS там, что люди привыкли использовать, и самое главное, RSS очень хорошо известен и был вокруг намного дольше. Почему путаница с чем-то, если это работает?

7
задан Rayne 25 November 2009 в 09:45
поделиться

3 ответа

... Как ставит обновление состояния в первую очередь? Кажется, он просто сидит и ничего не делает ...

А, теперь я понял ваш вопрос. Вам интересно, как работает 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.

10
ответ дан 6 December 2019 в 08:15
поделиться

Вы совершенно правы. «Результатом» 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
7
ответ дан 6 December 2019 в 08:15
поделиться

может помочь записать его, используя нотацию 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) не влияет на результат вычисления , он действительно изменяет состояние, которое содержится в монаде состояний.

5
ответ дан 6 December 2019 в 08:15
поделиться