我正在尝试使用State monad进行一些计算,同时还要对其进行更改。我已经实现了Applicative
,Monad
和Functor
以及get
和put
,modify
等的实例。
我不了解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)
上的包装器
答案 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
操作。