I am experimenting with an external function interface in Haskell. I wanted to implement a simple test to see if I could do mutual recursion. So, I created the following Haskell code:
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 ()
Note that the recursive case is a call to countdownC, so it must be tail recursive.
In my C code, I have
#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; }
Same as tail recursive. So i do
MutualRecursion: MutualRecursionHaskell_stub ghc -O2 -no-hs-main MutualRecursionC.c MutualRecursionHaskell.o -o MutualRecursion MutualRecursionHaskell_stub: ghc -O2 -c MutualRecursionHaskell.hs
and compile with make MutualRecursion .
And ... at startup, it disappears after printing 8991 . Just like a test, to make sure gcc itself can handle tco in mutual recursion, I did
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); }
and it worked pretty well. It also works with single recursion only in C and only in Haskell.
So my question is, is there a way to tell GHC that calling an external C function is tail recursive? I assume that the stack frame comes from a call from Haskell to C, and not vice versa, since the C code very clearly returns a function call.
c haskell tail-call-optimization mutual-recursion multiple-languages
Crazycolorz5
source share