首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用连续性重写代码

用连续性重写代码
EN

Stack Overflow用户
提问于 2014-05-11 14:57:50
回答 1查看 191关注 0票数 5

我有一些评估原始程序的代码。程序是一个语句列表(表达式、块、返回语句)。评估结果是最后一次评估表达式。此外,评估人员应该正确对待return语句(即在return第一次出现后停止评估)。

为了实现这个逻辑,我传递特殊的回调函数(NextStep),它在当前语句之后执行下一个评估步骤。在处理返回语句时,我不调用下一步:

代码语言:javascript
复制
data Statement = 
      Expr Int
    | Block [Statement]
    | Return Int
    deriving (Show, Eq)

data Value = 
      Undefined
    | Value Int
    deriving (Show, Eq)

type NextStep = Value -> Value

evalStmt :: Statement -> NextStep -> Value
evalStmt (Expr val) next = 
    let res = Value val
    in next res
evalStmt (Block stmts) next = evalBlock stmts next
evalStmt (Return val) next = Value val

evalBlock :: [Statement] -> NextStep -> Value
evalBlock [] next = next Undefined
evalBlock [st] next = evalStmt st next
evalBlock (st:rest) next = evalStmt st $ \ _ -> evalBlock rest next

evalProgram stmts = evalBlock stmts id

prog1 = [Expr 1, Block [Return 3, Expr 2], Expr 4] 
evalProg1 = evalProgram prog1 -- result will be Value 3

问题是,我如何用连续monad重写这段代码?我想摆脱evalStmtevalBlock函数中显式传递的evalBlock回调。有可能吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-05-11 15:36:04

翻译相当机械。

请记住,在延续monad中,return将值输入到延续中。

代码语言:javascript
复制
evalStmt :: Statement -> Cont Value Value
evalStmt (Expr val) = 
    let res = Value val
    in return res
evalStmt (Block stmts) = evalBlock stmts
evalStmt (Return val) = cont $ \_ -> Value val

evalBlock :: [Statement] -> Cont Value Value
evalBlock [] = return Undefined
evalBlock [st] = evalStmt st
evalBlock (st:rest) = evalStmt st >> evalBlock rest

evalProgram :: [Statement] -> Value
evalProgram stmts = runCont (evalBlock stmts) id

为了模拟早期的返回,我们忽略了给Return val的延续,只返回我们拥有的值。

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23594116

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档