Съхраняем екземпляр на Може би

Опитвам се да намеря екземпляр на 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

но също и публикация за това как изтича памет. Има ли съществуващ екземпляр някъде другаде или начин за подобряване на екземпляра на C2HS? Защо няма екземпляр в Foreign.Storable като начало?


person crockeea    schedule 11.08.2014    source източник
comment
Ако сте съгласни с третирането на Nothing като точно еквивалентно на nullPtr, можете лесно да напишете това без изтичане. В противен случай не виждам начин да напиша това, без да правя ръчно управление на паметта (или да загубя полиморфизъм).   -  person John L    schedule 11.08.2014
comment
@JohnL Това ми се струва разумно. Защо не бих искал да го направя? Всъщност не извиквам C с никакви Maybe стойности, всичко това е временно нещо само в Haskell.   -  person crockeea    schedule 11.08.2014
comment
Хм, мисля, че сбърках, този подход не изглежда толкова лесен, колкото очаквах. Мисля, че имам подход, който работи, но защо се нуждаете от Storable за временни данни в Haskell?   -  person John L    schedule 11.08.2014


Отговори (1)


Ето един потенциален екземпляр, наличен в 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)
person Michael Snoyman    schedule 11.08.2014
comment
Можете ли да обясните защо това е по-добро от екземпляра на C2HS? - person crockeea; 11.08.2014
comment
Екземплярът на C2HS съхранява указател към данните, от които се нуждаете, така че имате лост за ненасочване и допълнителна памет за указателя (пълна машинна дума). Този подход избягва допълнителната индиректност, запазва всички данни в една и съща област в паметта и вместо допълнителна машинна дума на елемент, имате допълнителен байт на елемент. - person Michael Snoyman; 12.08.2014