Elm 中的堆栈溢出和其他问题

问题描述 投票:0回答:1

免责声明:我在reddit上问了同样的问题(link

我正在 Elm 中重写 Haskell 应用程序(由我的学生使用)来训练自己的语言能力,并启用部署为静态 Web 应用程序以简化托管。我遇到了一个奇怪的问题:函数

runTrace
似乎抛出了堆栈溢出错误(RangeError:超出最大调用堆栈大小),这是意外的,因为该函数是尾递归的。更奇怪的是,启用该功能的日志记录完全解决了该错误。我很难理解为什么会发生这种情况或如何解决它。此外,当我尝试在 Ellie 上运行代码时,即使启用了日志记录,它也无法工作(OutputUncaught TypeError 中抛出异常:无法读取未定义的属性(读取“init”)。

  • 下面是带有和不带有日志记录的相关代码片段。
  • 作为参考,我已将所有内容合并到一个无组织的文件中,可以从此链接下载。

带有日志记录的代码:

runTrace : ComputationModel model state input output -> model -> input -> ( List state, output )
runTrace cm instance input =
    let
        runTrace_ acc state =
            case cm.update instance state of
                Err newState ->
                    (log <| "newState: " ++ Debug.toString newState) <|
                        runTrace_ (\trace -> acc (newState :: trace)) newState

                Ok output ->
                    ( acc [], output )
    in
    runTrace_ identity <| cm.init instance input

且无需登录:

runTrace : ComputationModel model state input output -> model -> input -> ( List state, output )
runTrace cm instance input =
    let
        runTrace_ acc state =
            case cm.update instance state of
                Err newState ->
                    runTrace_ (\trace -> acc (newState :: trace)) newState

                Ok output ->
                    ( acc [], output )
    in
    runTrace_ identity <| cm.init instance input
elm
1个回答
0
投票

问题不在于

runTrace_
本身不是尾递归,而是您创建的累加器函数没有从 TCO 中受益。

当您添加日志记录时,它使

runTrace_
不是尾部调用,因此我假设(尽管我不确定具体如何)这必须在某种程度上展开堆栈。

这个版本似乎工作得很好:

runTrace : ComputationModel model state input output -> model -> input -> ( List state, output )
runTrace cm instance input =
    let
        runTrace_ acc state =
            case cm.update instance state of
                Err newState ->
                    runTrace_ (newState :: acc) newState

                Ok output ->
                    ( acc, output )
    in
    runTrace_ [] <| cm.init instance input
© www.soinside.com 2019 - 2024. All rights reserved.