How to find out the C type signature corresponding to a Haskell function type in FFI?

Hi - I've got a Haskell module with the following ffi import: foreign import ccall duma_init :: Int -> IO Int However my problem is that I've got no idea what the type signature for the corresponding C function should be, and when I compile the above module with ghc -fglasgow-exts -fffi --make it doesn't create any stubs either. I've tried looking at the wiki but that only seems to give specific examples. I'm trying to find what the mapping is between Haskell function signatures and C signatures is in general. Any ideas? Also, I really wanted to be able to use () -> IO () but () doesn't seem to be allowed in FFI... A third point is, how would I pass an arbitrary monad instead of just using IO? Thanks, Brian.

Hello Brian, Tuesday, March 7, 2006, 7:35:27 PM, you wrote: BH> foreign import ccall duma_init :: Int -> IO Int int duma_init(int); BH> I've tried looking at the wiki but that only seems to give specific BH> examples. I'm trying to find what the mapping is between Haskell function BH> signatures and C signatures is in general. Any ideas? see official FFI documentation - http://www.cse.unsw.edu.au/~chak/haskell/ffi/ffi.pdf and excellent paper "Tackling the awkward squad: monadic input/output, concurrency, exceptions, and foreign-language calls in Haskell" (http://research.microsoft.com/Users/simonpj/papers/marktoberdorf/marktoberdo...) BH> Also, I really wanted to be able to use () -> IO () but () doesn't seem to BH> be allowed in FFI... void f(void); foreign import ccall f :: IO () BH> A third point is, how would I pass an arbitrary monad instead of just using BH> IO? if you are sure what you do, you can even declare C function as pure: foreign import ccall duma_init :: Int -> Int -- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com

Bulat Ziganshin wrote:
Hello Brian,
Tuesday, March 7, 2006, 7:35:27 PM, you wrote:
foreign import ccall duma_init :: Int -> IO Int
int duma_init(int);
Also, I really wanted to be able to use () -> IO () but () doesn't seem to be allowed in FFI...
void f(void);
foreign import ccall f :: IO ()
Thanks Bulat for these function prototypes (+ the links you posted). I'd thought that it would be complicated to deal with the IO monad but I see from these prototypes that it's not so complicated after all... :-) Best regards, Brian.

On Tue, Mar 07, 2006 at 04:35:27PM -0000, Brian Hulley wrote:
A third point is, how would I pass an arbitrary monad instead of just using IO?
What for? IO is the monad that most closely matches the imperative, C semantics. That's why FFI only supports the IO monad (and pure functions). Other monads (you say arbitrary) may use rather complicated machinery to implement their semantics (HOFs, laziness, algebraic data types). I don't think it's a good idea to try implementing their actions in C (if that's what you want). Why do you need that? Best regards Tomasz -- I am searching for programmers who are good at least in (Haskell || ML) && (Linux || FreeBSD || math) for work in Warsaw, Poland

On Tue, Mar 07, 2006 at 07:57:50PM +0100, Tomasz Zielonka wrote:
On Tue, Mar 07, 2006 at 04:35:27PM -0000, Brian Hulley wrote:
A third point is, how would I pass an arbitrary monad instead of just using IO?
What for? IO is the monad that most closely matches the imperative, C semantics. That's why FFI only supports the IO monad (and pure functions). Other monads (you say arbitrary) may use rather complicated machinery to implement their semantics (HOFs, laziness, algebraic data types). I don't think it's a good idea to try implementing their actions in C (if that's what you want).
Why do you need that?
I tend to wrap FFI imports with functions that can be called in any MonadIO monad. I sometimes think I should suggest the FFI should be able to do this itself, but given I'm generally needing to convert types, allocate memory etc in these functions too the gain would be fairly minimal. Thanks Ian

Tomasz Zielonka wrote:
On Tue, Mar 07, 2006 at 04:35:27PM -0000, Brian Hulley wrote:
A third point is, how would I pass an arbitrary monad instead of just using IO?
What for? IO is the monad that most closely matches the imperative, C semantics. That's why FFI only supports the IO monad (and pure functions). Other monads (you say arbitrary) may use rather complicated machinery to implement their semantics (HOFs, laziness, algebraic data types). I don't think it's a good idea to try implementing their actions in C (if that's what you want).
Why do you need that?
I'm writing a library in C++ that will provide a GUI application framework, where the Haskell main function will simply describe the initial GUI configuration and supply callback functions. The C++ library will then just sit in a windows event loop calling the relevant Haskell callbacks. The question arises as to how to store and modify the application's state without having to make too many assumptions in advance as to how this state should be represented, so it seems natural for the callbacks to have a signature like mycallback :: GUIMonad m => EventInfo -> m EventResult 'm' will have to combine a state monad with the IO monad (so I can use IORef etc if needed). Of course I could just use IO by itself eg return IO (State, EventResult) but this seems a bit messy... There are some elements of the monad that C++ code will need to know about (to make use of the EventResult), but it would be nice to also have some elements that are private to the Haskell side so that different kinds of app framework can be used (eg apps based on a dependency graph architecture) without having to re-write my C++ DLL... Also, it might be nice to prevent the callback functions from doing any input, and like O'Haskell, just provide some sort of O monad although I'm not worried about this at the moment. Regards, Brian.

Hello Brian, Wednesday, March 8, 2006, 12:03:27 AM, you wrote: BH> mycallback :: GUIMonad m => EventInfo -> m EventResult BH> 'm' will have to combine a state monad with the IO monad (so I can use IORef BH> etc if needed). as Ian Lynagh wrote, it's no problem if your monad is IO-based. if FFI by itself don't support this, you can add "liftIO" wrappers: foreign import f :: IO () f_wrapper :: GUIMonad m => m () f_wrapper = liftIO f -- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com

"Brian Hulley"
I've got a Haskell module with the following ffi import:
foreign import ccall duma_init :: Int -> IO Int
However my problem is that I've got no idea what the type signature for the corresponding C function should be,
HsInt duma_init(HsInt arg); Or use int on the C side and CInt on the Haskell side. fromIntegral can be used for converting integers in Haskell. -- __("< Marcin Kowalczyk \__/ qrczak@knm.org.pl ^^ http://qrnik.knm.org.pl/~qrczak/

Hello Marcin, Thursday, March 9, 2006, 2:20:00 AM, you wrote:
foreign import ccall duma_init :: Int -> IO Int
MQK> HsInt duma_init(HsInt arg); MQK> Or use int on the C side and CInt on the Haskell side. MQK> fromIntegral can be used for converting integers in Haskell. for small "home" projects you can even use "Int" and "int" which would work in most of Haskell implementations -- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com

Am Donnerstag, 9. März 2006 08:46 schrieb Bulat Ziganshin:
Thursday, March 9, 2006, 2:20:00 AM, you wrote:
foreign import ccall duma_init :: Int -> IO Int
MQK> HsInt duma_init(HsInt arg); MQK> Or use int on the C side and CInt on the Haskell side. MQK> fromIntegral can be used for converting integers in Haskell.
for small "home" projects you can even use "Int" and "int" which would work in most of Haskell implementations
Uh, oh... :-( This is roughly as "safe" as assuming that short, int, long, and long long are of the same size, so this is highly discouraged. The rationale behind the FFI addendum is as follows: * If you want to use a given C API, use the types from Foreign.C.Types on the Haskell side in the foreign imports. * If the C API is under your control, you have basically two options: Either use Foreign.C.Types as above, or use the types/preprocessor #defines in the HsFFI.h header to bind to basic Haskell types. Which option is better suited depends on what you are trying to achieve. This should be easy enough to use and everything else is not guaranteed to work... Cheers, S.

Sven Panne wrote:
Am Donnerstag, 9. März 2006 08:46 schrieb Bulat Ziganshin:
Thursday, March 9, 2006, 2:20:00 AM, you wrote:
foreign import ccall duma_init :: Int -> IO Int
MQK> HsInt duma_init(HsInt arg); MQK> Or use int on the C side and CInt on the Haskell side. MQK> fromIntegral can be used for converting integers in Haskell.
for small "home" projects you can even use "Int" and "int" which would work in most of Haskell implementations
Uh, oh... :-( This is roughly as "safe" as assuming that short, int, long, and long long are of the same size, so this is highly discouraged. The rationale behind the FFI addendum is as follows:
* If you want to use a given C API, use the types from Foreign.C.Types on the Haskell side in the foreign imports.
* If the C API is under your control, you have basically two options: Either use Foreign.C.Types as above, or use the types/preprocessor #defines in the HsFFI.h header to bind to basic Haskell types. Which option is better suited depends on what you are trying to achieve.
This should be easy enough to use and everything else is not guaranteed to work...
Yes, and to give a concrete example: HsInt and int are different types on x86_64 (and most other 64-bit C implementations). Cheers, Simon

Hello Simon, Thursday, March 9, 2006, 5:08:09 PM, you wrote:
for small "home" projects you can even use "Int" and "int" which would work in most of Haskell implementations
SM> Yes, and to give a concrete example: HsInt and int are different types SM> on x86_64 (and most other 64-bit C implementations). yes, it's better to use "Int" and "long" types :) -- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com
participants (7)
-
Brian Hulley
-
Bulat Ziganshin
-
Ian Lynagh
-
Marcin 'Qrczak' Kowalczyk
-
Simon Marlow
-
Sven Panne
-
Tomasz Zielonka