国家Monad的范围

时间:2014-03-02 23:19:08

标签: haskell monads state-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 s@(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 ++ " "

我不理解的是为什么州议会的州不会重置&#39;每次连续调用loopArgs。状态是否作为变量传递,每个>>如果有,有人可以告诉我如何?

1 个答案:

答案 0 :(得分:3)

  

状态是否作为变量传递,每个&gt;&gt;若有,有人可以告诉我怎么做?

确实如此。查看State 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