2014-03-02 64 views
2

我试图了解下面的代码会发生什么,代码的行为是否正确,但我试图了解为什么范围状态Monad

import Control.Monad.State 
import System.IO 
import System.Environment 

echoArgs :: [String] -> State Int [String] 
echoArgs x = loopArgs x >> return x 
     where loopArgs [] = return() 
      loopArgs [email protected](x':xs') = modify (+1) >> loopArgs xs' 

main :: IO() 
main = do 
    argv <- getArgs 
    let s = echoArgs argv 
    mapM_ putStr' (evalState s 0) 
    putStrLn $ "\nNum Args = " ++ show (execState s 0) 
    where putStr' x = putStr $ x ++ " " 

什么我不理解就是为什么国家单子的状态没有得到“复位”一起loopArgs每个连续通话。状态是否作为变量传递,每个>>如果有的话,有人可以告诉我怎么做?

回答

3

状态是否作为变量传递,每个>>如果有的话可以有人告诉我如何?

确实如此。查看玩具的状态monad是很有帮助的。

newtype State s a = State { runState :: s -> (a,s) } 

instance Monad (State s) where 
    return a = State $ \s -> (a, s) 

    State act >>= k = State $ \s -> 
    let (a, s') = act s 
    in runState (k a) s' 

get :: State s s 
get = State $ \s -> (s, s) 

put :: s -> State s() 
put s = State $ \_ -> ((), s) 

modify :: (s -> s) -> State s() 
modify f = get >>= \x -> put (f x) 

如果绑定使用>>=>>累积状态通过作为参数传递给该函数在右手侧螺纹。

当您运行execStateevalState时,它只是从结果元组中提取结果值或状态。

execState :: State s a -> s -> s 
execState act = snd . runState act 

evalState :: State s a -> s -> a 
evalState act = fst . runState act 
+0

感谢您的回应,是否有一个'''如何工作的例子(在国家monad),我理解'>> ='如何在您的示例中工作,状态每次都会通过。 – hcaulfield57

+1

''>>''只是''>> =''的一个特例,它被定义为''m >> k = m >> = \ _ - > k'' –

+0

哦,对,但它仍然通过关于状态,谢谢! – hcaulfield57