消除这个 Lua monad 模仿中的递归
Eliminating recursion in this Lua monad mimicry
我试图在 Lua 中粗略地复制 Parsec,但我在绑定函数 递归 生成时遇到了一些麻烦递归 runParser
s.
function Parser:bind(f)
return new(function(s)
local result = self.runParser(s)
if result.cons() == Result.Success then
return f(result.get()).runParser(result.get(2))
else
return result
end
end)
end
我正在使用制作 ADT 的自定义系统,因此 cons()
和 get()
在 return 值上运行。等效的 Haskell 代码应该是这样的。
m >>= f = Parser $ \s -> case result of
Success a cs -> runParser (f a) cs
_ -> result
where
result = runParser m s
Parser
构造函数(Lua 中的 new
函数)的参数是 runParser
函数。因此,从 runParser
中非尾递归调用不同的 runParser
会生成非常深的调用堆栈,从而导致堆栈溢出。关于删除递归或将其转换为尾递归的任何提示?
Continuation passing 让这个问题很容易解决。
function Parser:bind(f)
return new(function(s, cont)
return self.runParser(s, function(result)
if result.cons() == Result.Success then
return f(result.get()).runParser(result.get(2), cont)
else
return cont(result)
end
end)
end)
end
这样下去,一路都是尾声!诚然,f
有可能自行溢出,但这是用户编程错误的情况,因为 f
根本不应该走得很深。
我试图在 Lua 中粗略地复制 Parsec,但我在绑定函数 递归 生成时遇到了一些麻烦递归 runParser
s.
function Parser:bind(f)
return new(function(s)
local result = self.runParser(s)
if result.cons() == Result.Success then
return f(result.get()).runParser(result.get(2))
else
return result
end
end)
end
我正在使用制作 ADT 的自定义系统,因此 cons()
和 get()
在 return 值上运行。等效的 Haskell 代码应该是这样的。
m >>= f = Parser $ \s -> case result of
Success a cs -> runParser (f a) cs
_ -> result
where
result = runParser m s
Parser
构造函数(Lua 中的 new
函数)的参数是 runParser
函数。因此,从 runParser
中非尾递归调用不同的 runParser
会生成非常深的调用堆栈,从而导致堆栈溢出。关于删除递归或将其转换为尾递归的任何提示?
Continuation passing 让这个问题很容易解决。
function Parser:bind(f)
return new(function(s, cont)
return self.runParser(s, function(result)
if result.cons() == Result.Success then
return f(result.get()).runParser(result.get(2), cont)
else
return cont(result)
end
end)
end)
end
这样下去,一路都是尾声!诚然,f
有可能自行溢出,但这是用户编程错误的情况,因为 f
根本不应该走得很深。