 --
 type DevicePtr a = ForeignPtr a
 
-withDevicePtr :: DevicePtr a -> (Ptr a -> IO b) -> IO b
-withDevicePtr =  withForeignPtr
-
-newDevicePtr   :: Ptr () -> IO (DevicePtr ())
+withDevicePtr :: DevicePtr a -> (Ptr b -> IO c) -> IO c
+withDevicePtr =  withForeignPtr . castForeignPtr
+
+newDevicePtr   :: Ptr a -> IO (DevicePtr a)
 newDevicePtr p =  (doAutoRelease free_) >>= \f -> newForeignPtr f p
 
 --

-- requirements are met. The actual allocation pitch is returned
--
malloc3D :: (Int64,Int64,Int64)         -- ^ allocation (width,height,depth) in bytes
         -> IO (Either String (DevicePtr (),Int64))
malloc3D = moduleErr "malloc3D" "not implemented yet"



memset2D ptr (width,height) pitch symbol = nothingIfOk `fmap` cudaMemset2D ptr pitch symbol width height

{# fun unsafe cudaMemset2D
    { withDevicePtr* `DevicePtr a' ,
      cIntConv       `Int64'       ,
                     `Int'         ,
      cIntConv       `Int64'       ,
      cIntConv       `Int64'       } -> `Status' cToEnum #}


-- |
-- Initialise the elements of a 3D array to a given value
--
memset3D :: DevicePtr a                 -- ^ The device memory
         -> (Int64,Int64,Int64)         -- ^ The (width,height,depth) of the array in bytes
         -> Int64                       -- ^ The allocation pitch, as returned by 'malloc3D'
         -> Int                         -- ^ Value to set for each byte
