haskell - 消除这个 Lua monad 模仿中的递归

标签 haskell recursion lua parsec

我正在尝试粗略地复制 Parsec在 Lua 中,我在生成递归 runParser 时遇到了一些麻烦。

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() 函数返回值。等效的 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 不应该深入到全部。

关于haskell - 消除这个 Lua monad 模仿中的递归,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31996183/

相关文章:

haskell - 将 Lens' a b 转换为 Lens' a(也许是 b)

haskell - Cabal/Stack 忽略自定义安装脚本的 ghc-options

java - 为什么这个不复制类,复制内部文件夹

java - 打印哈夫曼树中的正确路径

arrays - 如何将已排序的表索引作为字符串返回?

haskell - 如何定义引用其定义的递归数据类型

haskell - 所有函数类型都形成 `Hask` 的子类别吗?

java - Java 是否支持和优化尾递归调用?

Lua如何将单词对字符串拆分为两个单独的变量?

c++ - LuaPlus:如何让函数返回一个表?