对于服务器 - 客户端应用程序,我需要一种方法来自动检查用于通信的数据结构的一致性.为此,我需要比较这些数据结构的可序列化表示.我基本上期望的是构造一个类型表示树,其基本类型为叶子.
例如,Artist
以下数据模型中的类型:
data Artist = Artist Text Genre
data Genre = Jazz | Metal
Run Code Online (Sandbox Code Playgroud)
将表示为:
DataType
"Artist"
[
Constructor
"Artist"
[
AbstractType "Data.Text.Text",
DataType
"Genre"
[
Constructor "Jazz" [],
Constructor "Metal" []
]
]
]
Run Code Online (Sandbox Code Playgroud)
是否有任何库实现了这样的功能,有没有更好的方法来解决这个问题?例如,他们如何在Cloud Haskell中解决这个问题?
我刚刚发布了一个类型结构库,它完全解决了主题中声明的问题。它构造类型的数据表示,同时遍历它引用的所有类型直至基元。因此,它可以传递捕获所有涉及的类型的更改,这些更改甚至可能来自不同的库。
\n生成的图有一个Hashable
实例,因此它也可以用于执行匹配。例如,可以用它生成一个“版本”散列。
现在,由于实现使用带有 CAF 实现的类型类,因此表示数据的构造应该在 O(1) 内完成。但我必须指出,我还没有对它进行基准测试。
\n顺便说一句,由于类型可以递归,因此该库无法按照问题中预期的方式实现,因为否则它将构造一个无限树。相反,该库将数据结构表示为图形。事实上,该图本身表示为边字典,因为没有更好的方法来表示不可变图。
\n这是一个 GHCi 会话,显示了应该如何使用该库:
\n\xce\xbb>import TypeStructure \n
Run Code Online (Sandbox Code Playgroud)\n类型结构表示图的构建:
\n\xce\xbb>graph (undefined :: Int)\n(Type_Con ("GHC.Types","Int"),[(("GHC.Types","Int"),Declaration_ADT [] [("I#",[Type_Con ("GHC.Prim","Int#")])]),(("GHC.Prim","Int#"),Declaration_Primitive)])\n
Run Code Online (Sandbox Code Playgroud)\n不同类型的图保证是不同的:
\n\xce\xbb>graph (undefined :: Int) /= graph (undefined :: Integer)\nTrue\n
Run Code Online (Sandbox Code Playgroud)\n相同类型的值的图保证是相同的:
\n\xce\xbb>graph True == graph False\nTrue \n
Run Code Online (Sandbox Code Playgroud)\n获取类型结构的哈希值:
\n\xce\xbb>import Data.Hashable\n\xce\xbb>hash $ graph (undefined :: Int)\n3224108341943761557\n
Run Code Online (Sandbox Code Playgroud)\n不同类型的哈希值不应该相等:
\n\xce\xbb>(hash $ graph (undefined :: Int)) /= (hash $ graph (undefined :: Integer))\nTrue\n
Run Code Online (Sandbox Code Playgroud)\n