可存储的可能实例

时间:2014-08-11 02:16:32

标签: haskell ffi

我正在尝试为Foreign.Storable找到Maybe的实例。 Google从C2HS

中找到了一个实例
instance Storable a => Storable (Maybe a) where
  sizeOf    _ = sizeOf    (undefined :: Ptr ())
  alignment _ = alignment (undefined :: Ptr ())

  peek p = do
             ptr <- peek (castPtr p)
             if ptr == nullPtr
               then return Nothing
               else liftM Just $ peek ptr

  poke p v = do
               ptr <- case v of
                        Nothing -> return nullPtr
                        Just v' -> new v'
               poke (castPtr p) ptr

还有a post关于它如何泄漏内存。是否存在其他地方的现有实例,或者是改进C2HS实例的方法?为什么Foreign.Storable中没有一个实例开始?

1 个答案:

答案 0 :(得分:3)

这是一个潜在的实例available on School of Haskell。我们的想法是存储一个包含0或1的额外字节,指示该值是否存在。

对于单个Storable实例,肯定有更有效的方法。例如,Maybe Bool可以存储在单个字节中而不是两个字节中。但我不认为你可以避免一般情况下的1字节开销。

这是我解决方案的主要部分:

instance Storable a => Storable (Maybe a) where
    sizeOf x = sizeOf (stripMaybe x) + 1
    alignment x = alignment (stripMaybe x)
    peek ptr = do
        filled <- peekByteOff ptr $ sizeOf $ stripMaybe $ stripPtr ptr
        if filled == (1 :: Word8)
            then do
                x <- peek $ stripMaybePtr ptr
                return $ Just x
            else return Nothing
    poke ptr Nothing = pokeByteOff ptr (sizeOf $ stripMaybe $ stripPtr ptr) (0 :: Word8)
    poke ptr (Just a) = do
        poke (stripMaybePtr ptr) a
        pokeByteOff ptr (sizeOf a) (1 :: Word8)