type InterpreterMonad = StateT (Env, Env) (ErrorT String IO ) ()
interpreter :: Stmts -> InterpreterMonad
interpreter (Statements s EmptyStmts) = interpreteStmt s
interpreter (Statements s stmts) = interpreteStmt s >>= \m -> (interpreter stmts)
-- definicja funkcji
interpreteStmt :: Stmt -> InterpreterMonad
interpreteStmt (DefFun (VarName name) args typ begin statements end) = get >>=
\(envOut, (sInnerEnvFun, sInnerEnvEVal)) -> case (Map.lookup (VarName name) sInnerEnvFun) of
Nothing -> put ( ( envOut, ((Map.insert (VarName name) (DefFun (VarName name) args typ begin statements end) sInnerEnvFun), sInnerEnvEVal)) ) >>= \_ -> return ()
(Just x) -> throwError "ee"
嗨,我无法理解为什么可以调用get
和put
函数? Haskell如何知道“哪里”是状态?我有一个支持命令式编程的问题 - 毕竟,我们必须调用对象(作为方法)或通过参数传递状态。
答案 0 :(得分:1)
当您使用State
monad函数get
和put
并使用do
表示法或>>=
对其进行排序时,您正在构建一个"配方" (通常称为"动作")用于访问和修改最终将与某个特定状态一起使用的本地状态。例如:
increment = do
count <- get
put (count + 1)
然后,此操作可以与State
接口的一部分一起使用,该部分允许您通过传入状态来运行操作。我们将使用execState
来返回状态并丢弃其他值,以演示:
> execState increment 1
2
execState
是将动作increment
与其修改的状态相关联的内容。 increment
本身并不包含任何状态,它只是与状态交互的一种方法,您必须在以后进行评估。
答案 1 :(得分:1)
State
类型(StateT
是一个概括)实现如下:
newtype State s a =
State { -- A function that takes a state of type `s` and
-- produces a pair `(a, s)` of a result of type
-- `a` and a new state of type `s`.
runState :: s -> (a, s)
}
此类型包含Functor
,Applicative
和Monad
的实例,允许您从较简单的值中汇总复杂的State
值:
-- I won't write the code for these here
instance Functor (State s) where ...
instance Applicative (State s) where ...
instance Monad (State s) where ...
基本上,State
是链接类似s -> (a, s)
类型函数的快捷方式,但不必明确传递这些s
值。当你准备好实际&#34;饲料&#34; State
值为s
的{{1}}操作您使用其中一项操作(取决于您想要的结果部分):
runState :: State s a -> s -> (a, s)
evalState :: State s a -> s -> a
execState :: State s a -> s -> s
然后,put
和get
会与&#34;隐藏&#34;进行互动。状态参数,State
类型在代码中隐式传递。他们的实现是这样的:
get :: State s s
get = State (\s -> (s, s))
put :: s -> State s ()
put s = State (\_ -> ((), s))
那就是它!