我正在用Haskell中的外部函数接口进行试验。我想实施一个简单的测试,看看我能否做到相互递归。所以,我创建了下面的Haskell代码:在C和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
编译。
And ...运行时,打印后出现段错误8991
。 就像一个测试,以确保海合会本身可以相互递归处理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代码非常清楚地返回了函数调用。
有没有办法来防止双返回地点?例如,我使用模式匹配编写了一个备用例程(对于基本情况为0),但这并没有帮助。一般来说,有没有一种方法可以告诉GHC以一种允许跨越边界递归的方式进行编译? – Crazycolorz5
@ Crazycolorz5调整运行时间是一项非常艰巨的任务。你似乎相信GHC应该把它的运行时间调整到C标准。要弄清楚这是多么困难,请考虑其他方式:修改GCC以便允许多个返回,垃圾回收等。这几乎是不可能的。就目前的GHC而言,甚至在我看来,即使在遥远的将来,你所要求的是非常非常不可能实现的。 – chi