在haskell中构建图形结构
我正在为关系数据库的类型信息建模。我想构建以下图表:在haskell中构建图形结构,haskell,Haskell,我正在为关系数据库的类型信息建模。我想构建以下图表: 顶点是表 对于A中的每一列,表A到表B之间都存在一条边,该列是B的外键 这是我创建图表的初始数据 newtype TableName = TableName T.Text newtype ColName = ColName T.Text newtype ColType = ColType T.Text type DBInfo = H.HashMap TableName TableInfo type TableInfo = H.HashMap
newtype TableName = TableName T.Text
newtype ColName = ColName T.Text
newtype ColType = ColType T.Text
type DBInfo = H.HashMap TableName TableInfo
type TableInfo = H.HashMap ColName ColInfo
data ColInfo = CISimple ColType
-- Forms the basis for building the graph
| CIFKey ColType TableName -- col type, referenced table
getDBInfo :: IO (DBInfo)
这些是我所期望的图形结构的类型
data SafeColInfo = SCISimple ColType
-- This captures an edge between two tables
| SCIFKey ColType SafeTableInfo
type SafeTableInfo = H.HashMap TableName SafeColInfo
type SafeDBInfo = ..
我想写这个函数:
convDBInfo :: DBInfo -> Either String SafeDBInfo
convDBInfo
应构建上述图表。通过在DBInfo
中查找t
可以找到任何外键(CIFKey ctype t)
中有关t
的信息。如果未找到,则输入数据不一致,是一个错误
这在带有引用的命令式语言中相当简单。然而,在哈斯克尔,我想不出解决这个问题的办法。据我所知,这看起来很适合“打结”的模式,但我似乎无法将我的头围绕它。如何编写此函数?我们可以通过以下方式打结:
convDBInfo :: DBInfo -> SafeDBInfo
convDBInfo dbi = safeDbi where
safeDbi = H.map (H.map go) dbi
go (CIFKey colName tblName) = SCIFKey colName $ safeDbi H.! tblName
go (CISimple colName) = SCISimple colName
我们通过映射输入中的列条目来获得safeDbi
。重要的一点是,我们从go
定义中的safeDbi
中查找表,因此SCIFKey
-s中的表将来自生成的hashmap
例如:
foo :: DBInfo
foo = H.fromList [
("table1", H.fromList [
("col1", CIFKey "a" "table2")
]),
("table2", H.fromList [
("col2", CIFKey "b" "table1")
])
]
bar = convDBInfo foo
SCIFKey _ tbl2 = (bar H.! "table1") H.! "col1"
SCIFKey name _ = tbl2 H.! "col2"
-- name == "b"
请注意,尽管棘手的数据结构通常不便于使用,因为它们与懒惰的无限结构无法区分,所以在打印、序列化或比较它们时,我们必须额外考虑它。大多数情况下,显式键控图形更易于使用,性能也不会差很多。对不起,convDBInfo应该做什么?对不起,我不清楚。编辑以添加信息。如果您知道不会出现错误,为什么需要返回
或?从DBInfo
查找t
可能是失败的(可能是TableInfo
),即使不会发生。为什么不使用HashMap的foldWithKey
?