Я экспериментирую с интерфейсом сторонних функций в 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 очень явно является возвратом вызова функции.