对于服务器 - 客户端应用程序,我需要一种方法来自动检查用于通信的数据结构的一致性。为此,我需要比较这些数据结构的可序列化表示。我基本上期望的是构造一个类型表示树,其基本类型为叶子。
,例如,来自以下数据模型的类型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中解决这个问题?
答案 0 :(得分:2)
我刚刚发布了一个type-structure库,它完全接近主题中声明的问题。它构造一个类型的数据表示,同时遍历它引用的所有类型到基元。因此,它可以传递地捕获所涉及的所有类型的变化,甚至可能来自不同的库。
生成的图形具有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
答案 1 :(得分:1)
我们的通用序列化库beamable执行此操作(否则它与cereal
或binary
的功能类似)。寻找函数typeSign
。默认的encode
/ decode
对不会进行类型签名,但会encodeLive
,或者您可以自行签署数据类型。
答案 2 :(得分:1)
作为基于SYB的解决方案,有一个typehash库,它使用Data
实例生成类型结构的哈希值。