haskell 在解释器中获取一元上下文中的状态环境

tquggr8v  于 2022-11-14  发布在  其他
关注(0)|答案(1)|浏览(103)

我想习惯monad转换器的工作,所以我想我应该用ExceptTState写一个简单的解释器,其中我的状态是Map Ident IntIdentString的别名。
我的语法定义如下所示

data BinOp
  = Plus
  | Minus
  | Times
  | Div
  deriving (Eq, Show)

data Stmt 
  = CompoundStmt Stmt Stmt
  | AssignStmt Ident Exp
  | PrintStmt [Exp]
  deriving (Eq, Show)

data Exp 
  = IdentExp Ident
  | NumExp Int
  | OpExp Exp BinOp Exp
  | SeqExp Stmt Exp
  deriving (Eq, Show)

但这并不重要。当我意识到我不知道如何实际获取我的环境时,我开始计算标识符表达式:

interpIdentExp :: (MonadState Env m, MonadError EvalError m) => Ident -> m Int
interpIdentExp ident = do
  env <- get
  fromMaybe (throwError IdNotDefined) (M.lookup ident env)

是我第一次尝试,但env实际上是Map Ident (m Int),而我只想处理普通的Int,我不知道如何使它工作。

zqry0prt

zqry0prt1#

我假设最后一位是印刷错误,Env被定义为Map Ident Int而不是Map Ident (m Int)
应采用以下方法:

interpIdentExp :: (MonadState Env m, MonadError EvalError m) => Ident -> m Int
interpIdentExp ident = do
  env <- get
  maybe (throwError IdNotDefined) return (M.lookup ident env)

尽管有些人可能更喜欢通过写来使状态如何被访问更明显:

interpIdentExp :: (MonadState Env m, MonadError EvalError m) => Ident -> m Int
interpIdentExp ident = do
  mval <- gets (M.lookup ident)
  maybe (throwError IdNotDefined) return mval

就我个人而言,我认为更详细的case语句使错误处理更容易阅读,所以我倾向于:

interpIdentExp :: (MonadState Env m, MonadError EvalError m) => Ident -> m Int
interpIdentExp ident = do
  mval <- gets (M.lookup ident)
  case mval of
    Just val -> return val
    Nothing -> throwError IdNotDefined

相关问题