Попробовал написать сериализацию с помощью Data.Binary и наткнулся на бяку при рекурсивных данных.
data A = A {a_unuqId :: Int, a_refs :: [B]}
data B = B {b_unuqId :: Int, b_refs :: [A]}
saveABtoFile :: FilePath -> ([A], [B]) -> IO ()
saveABtoFile = Data.Binary.encodeFile
loadABfromFile :: FilePath -> IO (([A], [B]))
loadABfromFile = Data.Binary.decodeFile
С сохранением всё ясно, вместо сохранения списка ссылок сохраняем список id-ов:
instance Binary A where
put (A i refs) = put i >> put (map b_unuqId refs)
А вот как написать get?
Можно конечно написать как-то так:
instance Binary A where
get = do
i <- get
b_ids <- get
return $ A i (map (\bi -> B bi []) b_ids
loadABfromFile = do
(xa, xb) <- Data.Binary.decodeFile
let xa' = map createA xa
xb' = map createB xb
createA (A i refs) = A i $ map (\b -> fromJast . find (== (b_unuqId b)) $ xb') refs
createB (B i refs) = B i $ map (\a -> fromJast . find (== (a_unuqId a)) $ xa') refs
return (xa', xb')
Но как-то это некрасиво...
Есть ещё какие-нибудь способы?
Или лучше сразу хранить id-ешки и при необходимости шерстить соответствующий список/мап/хешь?
П. С. Нашел ссылки на
несколько библиотек сериализации. Некоторые умеют вроде сами такое разруливать. А
Булатовская по описанию страшно быстрая и автоматом строит инстансы.
Но кроме Data.Binary нет ни одной живой.