Changes between Version 24 and Version 25 of ForeignFunctionInterface


Ignore:
Timestamp:
Oct 21, 2009 12:01:59 PM (5 years ago)
Author:
chak@…
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • ForeignFunctionInterface

    v24 v25  
    5757 * Some issues have been raised with `Data.Bits`.  However, any helpful changes would be too significant to consider at this stage.  This is a minor problem as a future revision has to overhaul the libraries anyway. 
    5858 
     59=== unsafePerformIO === 
     60 
     61The FFI libraries will include the function `unsafePerformIO` (as in the FFI addendum).  However, we limit the support use of the function purely to implement memory management and memory access during marshalling for foreign functions that ought to get a pure Haskell type.  Specifically, we will use the following wording (or something close): 
     62 
     63  Wrap a pure computation that uses local memory.  The only IO operations permitted in the IO action passed to `unsafePerformIO` are 
     64  (a) local allocation (`alloca`, `allocaBytes` and derived operations such as `withArray` and `withCString`), and 
     65  (b) pointer operations (`Foreign.Storable` and `Foreign.Ptr`) on the pointers to local storage, and 
     66  (c) foreign functions whose only observable effect is to read and/or  write the locally allocated memory. 
     67  This primitive enables the packaging of external entities that are pure functions except that they pass arguments and/or results via pointers.  It is expected that this operation will be replaced in a future revision of Haskell. 
     68 
    5969=== Alignment === 
    6070 
     
    8191 
    8292== Considerations for the future == 
     93 
     94As noted above, we expect that `unsafePerformIO` will be replaced in a future revision (that supports rank-2 types) with a function that safely encapsulates the local state.  A possible implementation would be the following: 
     95{{{ 
     96{-# LANGUAGE RankNTypes, ForeignFunctionInterface, GeneralizedNewtypeDeriving #-} 
     97 
     98module Example where 
     99 
     100import Foreign.C.Types 
     101import qualified Foreign.Marshal.Alloc as F 
     102import qualified Foreign.Ptr as F 
     103import qualified Foreign.Storable as F 
     104import System.IO.Unsafe (unsafePerformIO) 
     105 
     106-- Monad for memory regions, and type of pointers within such regions. 
     107-- Ideally all the implementations would be hidden 
     108 
     109newtype ST s a = UnsafeIOToST { unsafeSTToIO :: IO a } deriving Monad 
     110 
     111newtype STPtr s a = STPtr (F.Ptr a) 
     112 
     113runST :: (forall s. ST s a) -> a 
     114peek :: F.Storable a => STPtr s a -> ST s a 
     115poke :: F.Storable a => STPtr s a -> a -> ST s () 
     116alloca :: F.Storable a => (STPtr s a -> ST s b) -> ST s b 
     117 
     118-- sample implementations 
     119runST act = unsafePerformIO (unsafeSTToIO act) 
     120peek (STPtr p) = UnsafeIOToST (F.peek p) 
     121poke (STPtr p) v = UnsafeIOToST (F.poke p v) 
     122alloca f = UnsafeIOToST (F.alloca (unsafeSTToIO . f . STPtr)) 
     123 
     124-- Example of a wrapping of an otherwise pure function using pass-by-reference 
     125 
     126frexp :: Double -> (Double, Int) 
     127frexp x = runST (alloca $ \ exp_ptr -> do 
     128                fraction <- c_frexp (realToFrac x) exp_ptr 
     129                exponent <- peek exp_ptr 
     130                return (realToFrac fraction, fromIntegral exponent)) 
     131 
     132foreign import ccall "math.h frexp" 
     133        c_frexp :: CDouble -> STPtr s CInt -> ST s CDouble 
     134}}}