I'm trying to find an instance of Foreign.Storable
for Maybe
. Google turned up an instance from 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
but also a post about how it leaks memory. Is there an existing instance somewhere else, or a way to improve the C2HS instance? Why isn't there an instance in Foreign.Storable
to begin with?
Here's a potential instance, available on School of Haskell. The idea is to store an extra byte containing either a 0 or 1, indicating whether the value exists or not.
There are certainly more efficient approaches for individual Storable
instance. For example, a Maybe Bool
could be stored in a single byte instead of two bytes. But I don't think you can avoid the 1-byte overhead in the general case.
Here's the main part of my solution:
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With