Je joue avec les tours de monade Cont
décrits here et this SO question.État sur cont. Pourquoi mon état n'est-il pas réinitialisé?
Cette fonction vous permet de « revenir en arrière » plus haut dans le calcul, en prenant un paramètre de sorte que vous pouvez faire les choses différemment:
import Control.Monad.Cont
import Control.Monad.State.Strict
import Control.Monad.Writer.Strict
getCC' :: MonadCont m => a -> m (a,a -> m b)
getCC' x0 = callCC (\c -> let f x = c (x, f) in return (x0, f))
Je ces exemples de jouets de transformateurs monade au-dessus de Cont
:
foo :: WriterT String (Cont String)()
foo = do
(stop,loop) <- getCC' False
if stop
then do tell "bbb"
else do tell "aaa"
loop True
foo' :: StateT String (Cont String)()
foo' = do
(stop,loop) <- getCC' False
if stop
then do modify $ \s -> s ++ "bbb"
else do modify $ \s -> s ++ "aaa"
loop True
dans le premier exemple (comme dans la explained liée SO question) les effets de Cont
ont « priorité » sur les effets de la WriterT
. Lorsque nous avons rétabli le calcul, le journal est perdu:
*Main> print $ runCont (execWriterT foo) id
"bbb"
Le second exemple fait exactement la même chose, en utilisant uniquement StateT
au lieu de WriterT
. Cependant, dans ce cas, le journal est conservé!
*Main> print $ runCont (execStateT foo' "") id
"aaabbb"
Quelle est l'explication de cette divergence?
je me sens le comportement oublier l'état doit être la valeur par défaut, pas seulement pour l'uniformité avec 'WriterT', mais de faire respecter la règle intuitive que les effets de monades internes « ont la priorité » dans un certain sens. – danidiaz