 mallocHost flags = doMalloc undefined
   where
     doMalloc :: Storable a' => a' -> Int -> IO (HostPtr a')
-    doMalloc x n =
-      newHostPtr >>= \hp -> withHostPtr hp $ \p ->
-      cuMemHostAlloc p (n * sizeOf x) flags >>= nothingIfOk >>
-      return hp
+    doMalloc x n = resultIfOk =<< cuMemHostAlloc (n * sizeOf x) flags
 
 {# fun unsafe cuMemHostAlloc
-  { with'* `Ptr a'
-  ,        `Int'
-  , combineBitMasks `[AllocFlag]' } -> `Status' cToEnum #}
-  where with' = with . castPtr
+  { alloca'-        `HostPtr a'   peekHP*
+  ,                 `Int'
+  , combineBitMasks `[AllocFlag]'         } -> `Status' cToEnum #}
+  where
+    alloca'  = F.alloca
+    peekHP p = (HostPtr . castPtr) `fmap` peek p
 
 
 -- |
 -- Free a section of page-locked host memory
 --
 freeHost :: HostPtr a -> IO ()
-freeHost hp = withHostPtr hp $ \p -> (nothingIfOk =<< cuMemFreeHost p)
+freeHost p = nothingIfOk =<< cuMemFreeHost p
 
 {# fun unsafe cuMemFreeHost
-  { castPtr `Ptr a' } -> `Status' cToEnum #}
+  { useHP `HostPtr a' } -> `Status' cToEnum #}
+  where
+    useHP = castPtr . useHostPtr
+
 
 --------------------------------------------------------------------------------
 -- Device Allocation

-- The driver automatically accelerates calls to functions such as `memcpy'
-- which reference page-locked memory.
--
newtype HostPtr a = HostPtr (ForeignPtr a)

withHostPtr :: HostPtr a -> (Ptr a -> IO b) -> IO b
withHostPtr (HostPtr hptr) = withForeignPtr hptr

newHostPtr :: IO (HostPtr a)
newHostPtr = HostPtr `fmap` mallocForeignPtrBytes (sizeOf (undefined :: Ptr ()))

-- |
-- Options for host allocation


-- |
-- Return the device pointer associated with a mapped, pinned host buffer, which
-- was allocated with the 'DeviceMapped' option by 'mallocHost'.
--
-- Currently, no options are supported and this must be empty.
--
getDevicePtr :: [AllocFlag] -> HostPtr a -> IO (DevicePtr a)
getDevicePtr flags hp = resultIfOk =<< cuMemHostGetDevicePointer hp flags

{# fun unsafe cuMemHostGetDevicePointer
  { alloca'-        `DevicePtr a' peekDP*
  , useHP           `HostPtr a'
  , combineBitMasks `[AllocFlag]'         } -> `Status' cToEnum #}
  where
    alloca' = F.alloca
    useHP   = castPtr . useHostPtr
    peekDP  = liftM DevicePtr . peek

