2

我试图理解以下代码中发生了什么,代码行为正常,但我试图理解为什么

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

我不明白为什么每次连续调用 loopArgs 时 State monad 的状态都不会“重置”。状态是否作为变量传递,>>如果是的话,有人可以告诉我怎么做吗?

4

1 回答 1

3

状态是否作为变量传递,每个 >> ,如果是这样,有人可以告诉我怎么做吗?

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

当您绑定 using>>=>>累积状态作为参数传递给右侧的函数时。

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

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

evalState :: State s a -> s -> a
evalState act = fst . runState act
于 2014-03-03T00:09:03.960 回答