Changes between Version 24 and Version 25 of ForeignFunctionInterface


Ignore:
Timestamp:
Oct 21, 2009 12:01:59 PM (6 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}}}