【发布时间】:2015-11-03 18:19:23
【问题描述】:
我正在尝试使用 Haskell 中的外部函数接口。我想实现一个简单的测试,看看我是否可以进行相互递归。因此,我创建了以下 Haskell 代码:
module MutualRecursion where
import Data.Int
foreign import ccall countdownC::Int32->IO ()
foreign export ccall countdownHaskell::Int32->IO()
countdownHaskell::Int32->IO()
countdownHaskell n = print n >> if n > 0 then countdownC (pred n) else return ()
请注意,递归情况是对 countdownC 的调用,所以这应该是尾递归的。
在我的 C 代码中,我有
#include <stdio.h>
#include "MutualRecursionHaskell_stub.h"
void countdownC(int count)
{
printf("%d\n", count);
if(count > 0)
return countdownHaskell(count-1);
}
int main(int argc, char* argv[])
{
hs_init(&argc, &argv);
countdownHaskell(10000);
hs_exit();
return 0;
}
这也是尾递归。那我做一个
MutualRecursion: MutualRecursionHaskell_stub
ghc -O2 -no-hs-main MutualRecursionC.c MutualRecursionHaskell.o -o MutualRecursion
MutualRecursionHaskell_stub:
ghc -O2 -c MutualRecursionHaskell.hs
并使用make MutualRecursion 编译。
而且...在运行时,它会在打印8991 后出现段错误。
作为一个确保 gcc 本身可以在相互递归中处理 tco 的测试,我做了
void countdownC2(int);
void countdownC(int count)
{
printf("%d\n", count);
if(count > 0)
return countdownC2(count-1);
}
void countdownC2(int count)
{
printf("%d\n", count);
if(count > 0)
return countdownC(count-1);
}
而且效果很好。它也适用于仅在 C 中和仅在 Haskell 中的单递归情况。
所以我的问题是,有没有办法向 GHC 表明对外部 C 函数的调用是尾递归的?我假设堆栈帧确实来自从 Haskell 到 C 的调用,而不是相反,因为 C 代码很明显是函数调用的返回。
【问题讨论】:
标签: c haskell tail-call-optimization multiple-languages mutual-recursion