Sun, 19 Aug 2001 23:14:59 +1000, Manuel M. T. Chakravarty <chak@cse.unsw.edu.au> pisze:
* I am still not convinced that we need `Storable.destruct'. For deallocating special purpose structures that need a deep traversal, shouldn't we just use a custom function?
Without destruct code like with haskellValue $ \ptr -> do just use ptr, no allocation nor deallocation would be correct in 99% of cases, except that for some types it leaks memory (when the only reasonable implementation of poke is not idempotent wrt. allocated memory). These cases include char* inside a struct, assumed to point to a memory private to this struct. Yes, it can be called by hand, just as C++ destructors could be called by hand. But places where it should be called are automatically predictable, as long as it is well defined which memory is initialized and which is not. Since with* functions automatically call poke, they should automatically call something which undoes side effects of poke. You might avoid Storable instances for such types and only use opaque ForeignPtrs to heap-allocated objects. In this case, if all the allocation and deallocation is handled by foreign code, destruct is not needed. It makes sense however for more complex types which are made instances of Storable, i.e. where memory allocation is done by Haskell. I imagine that allocation in Haskell will be especially good idea now when Simon Marlow made alloca faster than malloc. A Haskell-C++ interfacing tool would hook destructors to destruct.
* I am also not really convinced about `MarshalUtils.withMany'. There may be situations, where such a function is handy, but should it really be in the standard libraries?
It's not so easily written by hand. Explicit recursion is needed, AFAIK it can't be simply written in terms of foldr, mapM etc. So it requires a variable definition, and thus would be written in this very form where needed, instead of "inlined". It's the mapM of the continuation monad, where the monad is /\a. (a -> res) -> res and thus can't be made instance of class Monad without wrapping in a newtype. FFI uses the "(a -> IO b) -> IO b" type pattern much.
Moreover, it isn't really marshalling specific - it is JAFL (Just Another Function on Lists).
Yes, but it's not available elsewhere.
PtrDiff ~~~~~~~ Maybe after all, `PtrDiff' wasn't that bad an idea. To assume that a pointer difference fits into an `Int' (what we do at the moment) is pretty dodgy. Remember that all that H98 requires of an `Int' is that it has >=30 bits. IMHO, this is pretty weak for a general representation of a pointer difference.
Haskell already uses Int for these kinds of lengths: array indices are mapped to Int, default implementations of list functions use Int for measuring lengths. On 64-bit processors Int is 64-bit (or 63-bit when targeting OCaml etc.), so the need of handling objects larger than a gigabyte in 32-bit architectures is temporary, if at all. Haskell has the advantage over C that there is no temptation to express all sized integer types as {char,short,int,long}, so there is no reason for Int to be too small. On 32-bit processors C implementations generally don't allow objects larger than 32 bits anyway.
The annoying thing about our old use of `PtrDiff' was that it made `plusPtr' a pain to use (as we had to cast the offset to a `PtrDiff' first). A simple solution would be
plusPtr :: Integral i => Ptr a -> i -> Ptr b
It would make "ptr `plusPtr` 1" use Integer by default (with a warning with -Wall). What about peekArray etc.? It's not clear where to stop. -- __("< Marcin Kowalczyk * qrczak@knm.org.pl http://qrczak.ids.net.pl/ \__/ ^^ SYGNATURA ZASTÊPCZA QRCZAK