Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Storable instance of Maybe

Tags:

haskell

ffi

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?

like image 690
crockeea Avatar asked Aug 11 '14 02:08

crockeea


1 Answers

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)
like image 122
Michael Snoyman Avatar answered Nov 06 '22 10:11

Michael Snoyman