Monad Stack和修改阅读器环境

时间:2016-05-06 23:58:42

标签: haskell

type InterpreterMonad = StateT (MEMORY, FUNCTIONS) (ReaderT (NameAddress, NameAddress) (ErrorT String  IO))
interpreteStmt :: Stmt -> InterpreterMonad ()


handleFCall :: VarName -> [CallArg] -> InterpreterMonad ()
handleFCall (VarName name) argsCall =  do
    (memory, functions) <- get
    case (Map.lookup (VarName name) functions) of
        Nothing -> throwError $ "error"
        (Just ((DefFun  varname argsDef typ begin statements end), env)) -> (checkCoherenceTypesArgs varname argsDef argsCall) >>= \_ -> argsToContext argsDef argsCall env >>= \_ -> interpreter statements >>= \_ -> return ()

我没有提供完整的代码来让我的问题更加清晰。 现在,我想在handleFCall interpreter statements函数中修改Reader monad(我的意思是读者中的环境)。怎么做?

P.S。我的尝试:(它没有用,请解释原因)

argsToContext :: [DefArg] -> [CallArg] -> NameAddress -> InterpreterMonad ()
argsToContext xs ys env = do
    (memory, fs) <- get
    (mem, args) <- (argsToContext' xs ys memory Map.empty)
    put ( mem, fs) 
    throwError $ "Tutej "  ++ (show args) ++ " memory " ++ (show mem)
    local (\_ -> (env, args)) ask
    return ()

1 个答案:

答案 0 :(得分:1)

您使用local功能。这是一个简短的例子:

import Control.Monad.Reader
import Control.Monad.State
import Control.Monad.Except

type MyMonad = StateT String (ReaderT Int (ExceptT String IO))

foo :: Int -> MyMonad ()
foo x = do
  env <- ask
  liftIO $ putStrLn $ "x = " ++ show x ++ " and env is: " ++ show env

t1 :: MyMonad ()
t1 = do
  foo 1                        -- env = 13
  local (+20) $ foo 2          -- env = 20+13 = 33
  local (const 42) $ foo 3     -- env = 42
  foo 4                        -- env = 13

example = runExceptT (runReaderT (runStateT t1 "some state") 13)

运行example的输出:

x = 1 and env is: 13
x = 2 and env is: 33
x = 3 and env is: 42
x = 4 and env is: 13
Right ((),"some state")

最初,Reader环境为13. local (+20)调用执行foo 2,Reader环境设置为13 + 20。然后在Reader环境设置为42的情况下执行foo 3。最后,在原始环境中执行foo 4