可存储的可能实例

cro*_*eea 6 haskell ffi

我正在尝试找到一个Foreign.Storablefor 的实例Maybe.谷歌发现了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
Run Code Online (Sandbox Code Playgroud)

还有一篇关于它如何泄漏记忆的帖子.是否存在其他地方的现有实例,或者是改进C2HS实例的方法?为什么一Foreign.Storable开始没有实例?

Mic*_*man 5

这是一个潜在的例子,可在 School of Haskell 上找到。这个想法是存储一个包含 0 或 1 的额外字节,指示该值是否存在。

对于个别实例当然有更有效的方法Storable。例如,aMaybe 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)
Run Code Online (Sandbox Code Playgroud)