【问题标题】:Scope of State Monad状态单子的范围
【发布时间】:2014-03-02 23:19:08
【问题描述】:

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

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 的状态都不会“重置”。状态是否作为变量传递给每个&gt;&gt;,如果是这样,有人可以告诉我怎么做吗?

【问题讨论】:

    标签: haskell monads state-monad


    【解决方案1】:

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

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

    当您使用&gt;&gt;=&gt;&gt; 绑定时,累积的状态将作为参数传递给右侧的函数。

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

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

    【讨论】:

    • 感谢您的回复,有没有 &gt;&gt; 如何工作的示例(在 State monad 中),我从您的示例中了解 &gt;&gt;= 如何工作,状态每次都通过。
    • &gt;&gt; 只是&gt;&gt;= 的一个特例,它被定义为m &gt;&gt; k = m &gt;&gt;= \_ -&gt; k
    • 哦,对了,但它仍然传递状态,谢谢!
    • 对不起那个斯蒂芬!
    猜你喜欢
    • 1970-01-01
    • 2013-11-09
    • 2011-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-29
    • 2020-02-22
    相关资源
    最近更新 更多