Allocation & Marshalling Question (again)

Wolfgang Thaller wolfgang.thaller at gmx.net
Wed May 28 05:51:19 EDT 2003


> So excuse me if this seems half baked, but am I the only one who
> thinks the type signatures of utilities like this..
>  allocaBytes :: Int -> (Ptr a -> IO b) -> IO b
> ..are rather inconvenient?
>
> Wouldn't..
>  allocaBytes :: Int -> (Ptr a -> b) -> b
> ..be more useful?

Why? What could the pure function you're passing to allocaBytes do with 
the pointer?
When would the storage be freed again? The original allocaBytes frees 
it after the IO action has finished, but before returing itself. How 
would that apply to the pure version?

>
> To get around this I defined an operator..
>  infixl 0 <+
>  (<+) :: (Ptr a -> b) -> ((Ptr a -> IO b) -> IO b) -> b
>  f <+ alloc = unsafePerformIO $ alloc $ \p -> return $ f p

What can f do with the pointer, outside the IO monad, without using 
unsafePerformIO itself?
Also, if you're passing alloca or allocaBytes for the alloc parameter, 
how do you make sure that 'f' has been _completely_ evaluated before 
alloca deallocates the storage again?

> Possible explanations that occur to me are..
> 1- It's technically impossible.
> 2- It's unnecessary because FFI users can define their own 
> contraptions like
>    <+ if they want them, assuming the use of unsafePerformIO in this 
> context
>    really is safe (and unsafePerformIO is available).
> 3- It's undesirable because the existing forms are better in some way.
> 4- It's undesirable because it would break existing code (not true 
> AFAICS).

5- because this use of unsafePerformIO is highly dangerous (I think it 
will lead to segfaults sooner or later) and should be avoided at all 
costs.
Also,
6- because a pure function cannot do anything useful with a pointer, 
IMHO.

Cheers,

Wolfgang




More information about the FFI mailing list