Может ли кто-нибудь рассказать мне об этой функции Haskell (связанной с монадой состояния)?

StackOverflow https://stackoverflow.com/questions/1795785

  •  22-09-2019
  •  | 
  •  

Вопрос

tick :: State Int Int
tick = get >>= \n ->
       put (n+1) >>= \y ->
       return n

Я в замешательстве относительно того, как put (n+1) вообще не влияет на конечный результат этой функции.Вроде бы эта функция должна возвращать исходное состояние без изменений.Я пытаюсь продумать это в уме, но мне все время не хватает места, чтобы удержать вещи на месте.:\

Если бы кто-нибудь мог помочь мне оценить эту функцию, это было бы очень полезно.

Это было полезно?

Решение

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

Ах, теперь я понимаю ваш вопрос.Вам интересно, как putget) работать, да?

Возможно, поможет пример на 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, get и put.Надеюсь, станет более понятно, как работает государство.

Другие советы

Вы совершенно правы.Результат 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

В этом случае, поскольку вы никогда больше не проверяете состояние внутри tick, вы не видите измененное состояние.Однако, если после этого произойдет какое-то другое вычисление tick, он может видеть обновленное состояние.

Например, делая tick дважды (второй будет читать обновленное состояние):

-- 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) не влияет на результат вычислений, он изменяет состояние, находящееся внутри монады состояния.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top