Сериализуемое представление типа данных для проверки соответствия клиент-сервер
Для сервер-клиентского приложения мне нужен способ автоматически проверять соответствие структур данных, используемых для связи. Чтобы достичь этого, мне нужно сравнить сериализуемые представления этих структур данных. Что я в основном ожидаю, так это то, что построит дерево представления типов с примитивными типами в качестве листьев.
Например, тип Artist
из следующей модели данных:
data Artist = Artist Text Genre
data Genre = Jazz | Metal
будет представлен как что-то вроде:
DataType
"Artist"
[
Constructor
"Artist"
[
AbstractType "Data.Text.Text",
DataType
"Genre"
[
Constructor "Jazz" [],
Constructor "Metal" []
]
]
]
Есть ли библиотека, которая реализует такую функциональность, и есть ли лучшие подходы к этой проблеме? Например, как они подходят к этому в Cloud Haskell?
3 ответа
Я только что выпустил библиотеку структуры типов, которая подходит именно к проблеме, заявленной в теме. Он создает представление данных типа, проходя все типы, на которые ссылается, вплоть до примитивов. Таким образом, он транзитивно фиксирует изменения для всех задействованных типов, которые могут даже поступать из разных библиотек.
Полученный график имеет Hashable
Например, он может быть использован для выполнения сопоставления. Например, с его помощью можно создать хеш-версию.
Теперь, так как реализация использует классы типов с реализациями CAF, построение данных представления должно быть выполнено в O(1). Я должен упомянуть, однако, что я не тестировал это.
Кстати, поскольку типы могут быть рекурсивными, библиотека не может быть реализована так, как ожидалось в вопросе, потому что иначе она создаст бесконечное дерево. Вместо этого библиотека представляет структуру данных в виде графика. На самом деле этот граф представлен в виде словаря ребер, поскольку лучшего способа представить неизменный граф не существует.
Как пользоваться
Вот сеанс GHCi, показывающий, как предполагается использовать библиотеку:
λ>import TypeStructure
Построение графа представления структуры типа:
λ>graph (undefined :: Int)
(Type_Con ("GHC.Types","Int"),[(("GHC.Types","Int"),Declaration_ADT [] [("I#",[Type_Con ("GHC.Prim","Int#")])]),(("GHC.Prim","Int#"),Declaration_Primitive)])
Графики разных типов гарантированно будут разными:
λ>graph (undefined :: Int) /= graph (undefined :: Integer)
True
Графики значений одного типа гарантированно будут одинаковыми:
λ>graph True == graph False
True
Получение хеша типовой структуры:
λ>import Data.Hashable
λ>hash $ graph (undefined :: Int)
3224108341943761557
Хэши разных типов не должны быть равны:
λ>(hash $ graph (undefined :: Int)) /= (hash $ graph (undefined :: Integer))
True
Наша универсальная библиотека сериализации делает это (в противном случае это аналогичная функция cereal
или же binary
). Ищите функцию typeSign
, По умолчанию encode
/ decode
пара не делает подписи типа, но encodeLive
будет, или вы можете подписать типы данных самостоятельно.
В качестве решения на основе SYB есть библиотека typehash, которая генерирует хеши структуры типов с использованием Data
пример.