【发布时间】:2026-01-04 00:55:02
【问题描述】:
我正在尝试在 haskell 中实现简单的命令式语言。
一般来说,我的程序是一个语句列表(如算术表达式、if/then、块语句)。我的评估器有简单的状态:词汇范围堆栈。词法范围只是变量名到值的映射。每次控制流进入函数或块时,我都会推送词法范围,并在控制流离开函数或块时弹出。
但是我在尝试执行return 语句的评估时遇到了问题。
我要做的是在主评估函数中为 return 语句创建一个特殊情况(sources here):
evalStatements :: [Statement] -> Eval MaybeValue
-- nothing to evaluate
evalStatements [] = return Nothing
-- current statement is 'return expr',
-- evaluate expr and skip the rest of statements
evalStatements (ret@(ReturnStatement _expr):_stmts) =
leaveLexEnv -- leave current lexical scope
evalStatement ret >>= return
-- this is last statement in function, eval it and leave lexical scope
evalStatements [stmt] = do
res <- evalStatement stmt
leaveLexEnv -- leave current lexical scope
return res
evalStatements (st:stmts) =
evalStatement st >> evalStatements stmts >>= return
evalStatement :: Statement -> MaybeValue
evalStatement (ExprStatemet expr) = ...
evalStatement (IfThenStatement expr stmt) = ...
但evalStatements 函数中的特殊情况对我来说看起来很难看。而且这种方法不适用于BlockStatement,因为return 语句可以在这个块语句中。
当 return 语句位于多个嵌套块语句中时,另一个问题是恢复词法范围的堆栈。
我想我可以通过在我的评估器中存储一些额外的状态来解决这个问题,但是这种方法看起来不是很好。有些东西告诉我,延续可以在这里帮助我。但我还不太了解延续。
解决此问题的最佳方法是什么?我只需要一个想法,一般概念。
谢谢。
【问题讨论】:
-
根据 monad 法则,
(>>= return)始终是无操作的。您应该删除这些以简化代码。如果它不是空操作,则您的Monad实例Eval已损坏。
标签: haskell continuations interpretation