不能在 IO 上下文中使用状态 monad

Cannot use state monad in IO context

我正在尝试使用 State monad 进行一些计算,同时也对其进行更改。我已经实现了 ApplicativeMonadFunctor 以及 getputmodify 等实例。 我不明白 do 块的脱糖。如何同时提供状态和状态转换器?

工具

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

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

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

    evalState::State s a->s->a
    evalState act =fst . run act

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

代码

module Env where
    import State 
    import System.Directory
    import Control.Monad
    data Env=Env{
        envName::String,
        fileNames::[String]
    }
    instance Show Env where 
        show Env{envName=x,fileNames=xs} = "{ envName:"++x++" , files: ["++foldr (\t y-> t++","++y) "" xs ++"] }"

    initEnv::IO Env
    initEnv=do
        name<- getLine
        names<- getCurrentDirectory>>=listDirectory
        return Env{envName=name,fileNames=names}

    changeName::String->State Env ()
    changeName (y:ys)=State $ \ (Env (x:xs) ls) -> ((),Env (y:xs) ls)

    toStats::State Env String
    toStats= State $ \env -> (show env,env)

    useEnv::IO (State Env String)
    useEnv=do
        liftM put initEnv   --passes state transformer
        liftM changeName getLine  --passes strate transformer
        print . evalState . toStats         --how do i supply both ?
        return toStats

如您所见,在我的最后一行中,我正在初始化状态转换器并传递它以进行进一步更改...直到我达到 evalState 并且我想使用它。在这种情况下,我不知道如何提供状态和变压器。

P.S 变压器是指 s->(a,s)

上的包装器

您的代码没有使用任何 monad 转换器。我想你只是在寻找

useEnv :: IO ()
useEnv = do
    env <- initEnv
    name <- getLine
    let actions = do
            changeName name
            toStats
    let str = evalState actions env
    putStrLn str

即运行 来自 IO do 块内的 State 动作。