Quelqu'un peut-il me promener à travers cette fonction Haskell (monade État lié)?

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

  •  22-09-2019
  •  | 
  •  

Question

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

Je suis confus quant à la façon dont put (n+1) a un effet sur le résultat final de cette fonction du tout. Il semble que cette fonction doit retourner l'état initial inchangé. Je suis en train de courir à travers cela dans mon esprit, mais je continue à manquer de place pour maintenir les choses en place. : \

Si quelqu'un pouvait me promener à travers l'évaluation de cette fonction, il serait vraiment utile.

Était-ce utile?

La solution

  

... Comment met la mise à jour de l'état en premier lieu? Il semble juste être assis là sans rien faire ...

Ah, je comprends maintenant votre question. Vous vous demandez comment put (et get) fonctionnent, droit?

Peut-être un exemple en JavaScript contribuera (une langue avec l'état mutable réelle):

var s; // mutable state
function get() { return s; }
function put(x) { s = x; }

function tick() {
    var n = get();
    put(n + 1);
    return n;
}

J'espère que cela montre que, alors que n ne change pas, l'état interne sera toujours mise à jour se. Si vous exécutez tick() deux fois, l'état sera incrémenté deux fois.

Pour revenir à Haskell, voici la définition complète de (les parties pertinentes) du monade 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)

Maintenant, essayez d'élargir votre exemple tick encore manuellement par inline >>=, return, get et put. Espérons que cela va obtenir plus de comprendre comment fonctionne l'Etat.

Autres conseils

Vous êtes tout à fait raison. Le « résultat » de « fonction » tick est la valeur initiale de l'état.

Maintenant, bien sûr, tick n'est pas la « fonction » réel, mais un calcul qui peut lire et écrire état avant de produire un résultat.
Dans ce cas, le État est mis à jour, mais vous êtes toujours revenir la valeur initiale de l'état:

-- 4 is the inital state
ghci> runState tick 4
(4, 5)
-- 4 is the result of the tick computation, 5 is the updated state

Dans ce cas, puisque vous n'êtes jamais inspecter l'état à nouveau à l'intérieur tick, vous ne voyez pas l'état a changé. Toutefois, si un autre calcul qui se passe après tick, il peut voir l'état mis à jour.

Par exemple, faire tick deux fois (la deuxième lira l'état mis à jour):

-- 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

il pourrait aider à écrire en utilisant la notation 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

alors que le put (n+1) n'a pas d'impact le résultat du calcul, il ne modifie l'état qui est tenue dans la monade de l'Etat.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top