我正在尝试找到一个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开始没有实例?
这是一个潜在的例子,可在 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)