
Hello, I've just modified some Haskell code from the AVL library to explicitly use ghc unboxed Ints in some routines. Unfortunately, I've broken portability by doing this and was considering some cpp magic to restore portability. But IIRC, the use of cpp is discouraged for Haskell library infrastructure. Is that so? If so, what should I use instead? Is cpphs the way to go? Thanks -- Adrian Hey

On Tue, Jul 13, 2004 at 12:02:13PM +0100, Adrian Hey wrote:
I've just modified some Haskell code from the AVL library to explicitly use ghc unboxed Ints in some routines.
Unfortunately, I've broken portability by doing this and was considering some cpp magic to restore portability. But IIRC, the use of cpp is discouraged for Haskell library infrastructure.
Is that so? If so, what should I use instead?
The initial version of the infrastructure may not support cpp, but it should appear later. However: Using any equivalent of #ifdef makes your code hard to maintain: you're not compiling all of it at any given time. Sometimes it's unavoidable, but for unboxing there is often a portable alternative: - to get fields unboxed, add strictness annotations to them and use the UNPACK pragma. - to get return values unboxed (i.e. components -- you can't unbox the whole thing), define a data type with strict fields (as above) and return that. - to get arguments unboxed, add the minimum number of seq's to make GHC believe that the function is strict in those arguments. Unfortunately this involves learning to read Core (or at least interface files), but after a while you'll get a feel for strictness. A more serious problem is that this doesn't work well with higher-order functions.

Ross Paterson
On Tue, Jul 13, 2004 at 12:02:13PM +0100, Adrian Hey wrote:
I've just modified some Haskell code from the AVL library to explicitly use ghc unboxed Ints in some routines.
Unfortunately, I've broken portability by doing this and was considering some cpp magic to restore portability. But IIRC, the use of cpp is discouraged for Haskell library infrastructure.
Is that so? If so, what should I use instead?
The initial version of the infrastructure may not support cpp, but it should appear later.
FWIW, I think it'll be one of the first things we do after the 0.1 release. Should be very easy with hscpp. peace, isaac

Isaac Jones wrote:
Ross Paterson
writes: The initial version of the infrastructure may not support cpp, but it should appear later.
FWIW, I think it'll be one of the first things we do after the 0.1 release. Should be very easy with hscpp.
I would be very happy if 0.1 included (hs)cpp support, otherwise the infrastructure would be useless for me. :-( My OpenGL/GLUT binding depends heavily on preprocessing being available, for three reasons: * I need a mapping from some C types to the corresponding Haskell types, which is figured out by autoconf/configure for the target platform in question. Alas, Foreign.C.Types doesn't cover every C API in the world... * The calling convention for WinDoze DLLs differs when compared to the convention used for the same library on (any?) other platform. (great idea, Bill! :-}. This has to be mirrored in the FFI declarations. Duplicating hundreds of essentially the same declarations is not really an option. * Sometimes a preprocessor is quite handy for syntactic abstractions, e.g. a single OpenGL extension gives rise to 3 Haskell declarations, including one `foreign import "wrapper"'. Not using an abstraction here would replicate the knowledge how extensions are handled into dozens of modules => extremely bad. One tricky macro is a small price to pay to avoid redundancy and improve modularity. Cheers, S.

Sven Panne
I would be very happy if 0.1 included (hs)cpp support, otherwise the infrastructure would be useless for me. :-( My OpenGL/GLUT binding depends heavily on preprocessing being available, for three reasons: (snip)
It won't be useless for you. You can still write a makefile that Setup uses, or you can _maybe_ use something very close to defaultMain, but you just run hscpp before doing much else. Flexibility is one of our big goals :) The basic infrastructure for simple libraries and tools needs to be finished first. As soon as it's finished, we'll make a release which will _hopefully_ fix the interface so we can get some basic packages using it (we've already got xml-rpc packaged, along with HUnit), and learn from them. After that, we'll add more features like cpp support, along with some other preprocessors. peace, isaac

On Tuesday 13 Jul 2004 2:24 pm, Ross Paterson wrote:
Using any equivalent of #ifdef makes your code hard to maintain: you're not compiling all of it at any given time. Sometimes it's unavoidable, but for unboxing there is often a portable alternative: - to get fields unboxed, add strictness annotations to them and use the UNPACK pragma. - to get return values unboxed (i.e. components -- you can't unbox the whole thing), define a data type with strict fields (as above) and return that. - to get arguments unboxed, add the minimum number of seq's to make GHC believe that the function is strict in those arguments. Unfortunately this involves learning to read Core (or at least interface files), but after a while you'll get a feel for strictness. A more serious problem is that this doesn't work well with higher-order functions.
Yes, I've been relying on tricks like this and compiler optimisation up to now, but I've decided a more direct approach is called for, albeit at the expense of using cpp. Squinting at core to find out if the compiler has optimised code the way you want (and trying to figure out what to do about it if not) gets a bit tiresome after a while :-) Regards -- Adrian Hey

Unfortunately, I've broken portability by doing this and was considering some cpp magic to restore portability. But IIRC, the use of cpp is discouraged for Haskell library infrastructure.
Using cpp is preferred to breaking portability. cpp doesn't cause any problem for Hugs (nog NHC, I think).
Is that so? If so, what should I use instead? Is cpphs the way to go?
cpphs aims to be compatible with cpp up to the point where cpp starts doing C-specific things like string splicing, interpreting ' as the start of a character (and whining if the "character" doesn't end), etc. So if your code works with cpp, it ought to work with cpphs. In particular, code like the following should work fine. #if GHC #define FastInt Int# #define plusInt(x,y) ((x)+#(y)) #else #define FastInt Int #define plusInt(x,y) ((x)+(y)) #endif [In practice, I'd leave plusInt curried - I just needed an example of a macro with arguments.] -- Alastair Reid

On Tuesday 13 Jul 2004 2:37 pm, Alastair Reid wrote:
cpphs aims to be compatible with cpp up to the point where cpp starts doing C-specific things like string splicing, interpreting ' as the start of a character (and whining if the "character" doesn't end), etc. So if your code works with cpp, it ought to work with cpphs. In particular, code like the following should work fine.
#if GHC #define FastInt Int# #define plusInt(x,y) ((x)+#(y)) #else #define FastInt Int #define plusInt(x,y) ((x)+(y)) #endif
[In practice, I'd leave plusInt curried - I just needed an example of a macro with arguments.]
Thanks, looks like cpphs is the way to go. I'll give it a try. Regards -- Adrian Hey
participants (5)
-
Adrian Hey
-
Alastair Reid
-
Isaac Jones
-
Ross Paterson
-
Sven Panne