[Haskell] Бинарная сериализация
От: Tonal- Россия www.promsoft.ru
Дата: 03.02.10 09:43
Оценка:
Попробовал написать сериализацию с помощью 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 нет ни одной живой.
Re: [Haskell] Бинарная сериализация
От: lomeo Россия http://lomeo.livejournal.com/
Дата: 05.02.10 10:24
Оценка: 3 (1)
Здравствуйте, Tonal-, Вы писали:

T>Но как-то это некрасиво...

T>Есть ещё какие-нибудь способы?

Мне кажется, здесь подойдёт подход с data-reify. Подробнее я описал в своём ЖЖ, сорри
http://lomeo.livejournal.com/47444.html
Re: [Haskell] Бинарная сериализация
От: Tonal- Россия www.promsoft.ru
Дата: 05.02.10 11:22
Оценка: 2 (1)
Раскопки натолкнули на PicklerCombinators но найти живых библиотек не удалось.
Кроме того, нашел в составе Leksah-а модуль Data.Binary.Shared который умеет работать с совмещением данных.
Он оборачивает работу с монадами Put и Get в монаду состояния — так что на его примере можно написать свои трансформации.

Но как-то всё это грустно — нет готовых простых решений для задачи сериализации состояний.
Data.Binary — это всё же низкоуровневый разбор бинарных форматов.
Аналог в python-е — это модуль struct.
А вот аналогов pickle или хотя бы marshal пока не наблюдается...

П. С. Нашел несколько интересных ссылок:
Обсуждение бинарного ввода/вывода.
Обсуждение аннотаций,
Serialized из GHC API 6.12.1
Data.Generics.Serialization — ещё не смотрел.
Страничка Булата — есть живые ссылки на Streams/AltBinary (Булат, поправь ссылки на странице описания)
Re[2]: [Haskell] Бинарная сериализация
От: lomeo Россия http://lomeo.livejournal.com/
Дата: 05.02.10 12:15
Оценка:
Здравствуйте, Tonal-, Вы писали:

Ты решил, что будешь делать со следующим случаем?
a = A 1 [b]
b = B 2 [a]

Ни одна из библиотек сериализаций, насколько я знаю, не предусматривает циклической зависимости (например, по StableName).
Re: [Haskell] Бинарная сериализация
От: Кодт Россия  
Дата: 05.02.10 12:49
Оценка:
Здравствуйте, Tonal-, Вы писали:

T>Попробовал написать сериализацию с помощью Data.Binary и наткнулся на бяку при рекурсивных данных.

T>data A = A {a_unuqId :: Int, a_refs :: [B]}
T>data B = B {b_unuqId :: Int, b_refs :: [A]}


Позвольте, высокомудрые сэры, мне, скудному умом и бедному практикой хаскелла, влезть в вашу преинтересную беседу.

Сериализация рекурсивных данных может быть сделана 2 способами.
1) обход вглубь: запись вариантных структур: либо литерал со всем его потрохами, либо идентификатор ранее записанного литерала
2) обход вширь: запись литералов, заменяя потроха на идентификаторы грядущих литералов (в очереди на запись)

Десериализация, соответственно, выглядит так
1) если встретили литерал — добавляем в словарь и углубляемся в чтение; если метку — читаем из словаря
2) читаем промежуточные структуры (литералы с метками потрохов), собирая весь словарь; затем углубляемся, заменяя метки на реальные значения
Перекуём баги на фичи!
Re[2]: [Haskell] Бинарная сериализация
От: lomeo Россия http://lomeo.livejournal.com/
Дата: 05.02.10 13:29
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Позвольте, высокомудрые сэры, мне, скудному умом и бедному практикой хаскелла, влезть в вашу преинтересную беседу.

К>Сериализация рекурсивных данных может быть сделана 2 способами.

Это всё понятно. Руками Tonal- сначала и сделал. Но при наличие таких мощных библиотек как, например, uniplate — так делать обидно.
Re[2]: [Haskell] Бинарная сериализация
От: novitk США  
Дата: 17.02.10 19:12
Оценка:
Здравствуйте, lomeo, Вы писали:

L>Мне кажется, здесь подойдёт подход с data-reify. Подробнее я описал в своём ЖЖ, сорри


Красиво! Интересно можно ли построить полностью сопряженное решение — (un)reifyGraph...
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.