Haskell状态monad:在序列之后获取更新的状态

Haskell状态monad:在序列之后获取更新的状态,haskell,state,monads,Haskell,State,Monads,作为编译器课程的一部分,我正在haskell中构建一个C#编译器。 我使用的是state monad,问题在于块的代码。我正在使用state包装声明变量的env。在分析一个块时,我想扩展这个状态(因为块内有声明),但之后返回到原始块(因为删除不会超出块)。但是,我想先知道新更新状态的大小。所以我有下面的代码: type EnvState = State Env (Int, Code) type Env = M.Map String Int fStatBlock :: [EnvState] -&

作为编译器课程的一部分,我正在haskell中构建一个C#编译器。 我使用的是state monad,问题在于块的代码。我正在使用state包装声明变量的env。在分析一个块时,我想扩展这个状态(因为块内有声明),但之后返回到原始块(因为删除不会超出块)。但是,我想先知道新更新状态的大小。所以我有下面的代码:

type EnvState = State Env (Int, Code)
type Env = M.Map String Int

fStatBlock :: [EnvState] -> EnvState
fStatBlock block = do origEnv <- get
                      xs      <- sequence block -- prelude sequence
                      newEnv  <- get
                      put origEnv
                      return (M.size newEnv, concatMap snd xs)
type EnvState=状态Env(Int,code)
类型Env=M。映射字符串Int
fStatBlock::[EnvState]->EnvState

fStatBlock block=do origEnv正如Justin L.所建议的,问题可能是
block
没有改变
Env
。下面是您的示例代码,未更改,添加了一些测试代码以生成完整的程序。函数
setValue
生成一个
EnvState
,该函数更改
Env
。在调用
fStatBlock
时使用
setValue
,会导致大小比基于原始
env
的大小大一倍

完成程序

import Control.Monad.State 
import Data.Map as M

type Code = [Int]


-- begin original code ------

type EnvState = State Env (Int, Code)
type Env = M.Map String Int

fStatBlock :: [EnvState] -> EnvState
fStatBlock block = do origEnv <- get
                      xs      <- sequence block -- prelude sequence
                      newEnv  <- get
                      put origEnv
                      return (M.size newEnv, concatMap snd xs)

-- end original code -------


setValue :: String -> Int -> EnvState
setValue name value = state (\env -> ((0,[]), insert name value env))

main = do
    let env = fromList [("x", 5), ("y", 10)]
        fsb = fStatBlock [setValue "a" 15] 
    print $ fst $ fst $ runState fsb env

请插入
序列
函数的定义好吗?如果这是
base
包中的标准函数,那么
块的类型是什么?在需要帮助的函数中添加完整的类型签名总是很有用的(如果上下文中不清楚的话)。我已经更新了代码片段,你是对的,我删除了太多的信息可能
block
根本没有改变
Env
?尝试
runState(sequence block)
,使用带有
块的一些初始映射,您希望更改内容,并确保它确实返回更改的映射。感谢您在回答中付出的努力!我再次查看了代码,发现了我的问题。问题是当我有嵌套块时。如果我有多个级别,那么最上面的一个总是返回第一个封闭块的大小,不管在更深的级别发生什么。通过让fStatBlock的所有参数返回正确的envSize,然后返回
return(最大$map fst xs,concatMap snd xs)
$ ./main 
3