
[ sorry for the delay in replying to this one, I'm just trying to clear some of my backlog... ]
I have a feeling this may be a stupid question, but why are the types of these.. newForeignPtr :: Ptr a -> IO () -> IO (ForeignPtr a) addForeignPtrFinalizer :: ForeignPtr a -> IO () -> IO () (second arg being the finalizer)
Won't a finaliser almost always take a pointer to the thing being finalised as an argument? If so it would be more convienient to have newForeignPtr.. newForeignPtr :: Ptr a -> (Ptr a -> IO ()) -> IO (ForeignPtr a) or maybe.. newForeignPtr :: Ptr a -> (ForeignPtr a -> IO ()) -> IO (ForeignPtr a)
I think the reason was simplicity - I seem to recall we originally had the versions you suggested, but realised that it isn't *necessary* for the finalizer to take a Ptr as an argument. Anyway, there's an ongoing discussion on the FFI list about whether having arbitrary Haskell finalizers is really a plausible design, so it may be that the point is moot anyway.
The first of these is easy to implement yourself I suppose.. myNewForeignPtr :: Ptr a -> (Ptr a -> IO ()) -> IO (ForeignPtr a) myNewForeignPtr p fin = newForeignPtr p (fin p)
The second seems to require this bit of weirdness.. myNewForeignPtr :: Ptr a -> (ForeignPtr a -> IO ()) -> IO (ForeignPtr a) myNewForeignPtr p fin = do newfp <- newForeignPtr p (return ()) addForeignPtrFinalizer newfp (fin newfp) return newfp
You can do this more easily using fixIO: myNewForeignPtr p fin = do fixIO (\fp -> newForeignPtr p (fin fp)) Cheers, Simon