不能在 IO 上下文中使用状态 monad
Cannot use state monad in IO context
我正在尝试使用 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
并且我想使用它。在这种情况下,我不知道如何提供状态和变压器。
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
动作。
我正在尝试使用 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
并且我想使用它。在这种情况下,我不知道如何提供状态和变压器。
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
动作。