无法在IO上下文中使用状态monad

时间:2019-06-08 04:57:33

标签: haskell state-monad

我正在尝试使用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并要使用它为止。在这种情况下,我不知道如何提供状态和变压器。

PS 变压器是指s->(a,s)上的包装器

1 个答案:

答案 0 :(得分:5)

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

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

即从State do块内部运行IO操作。