【问题标题】:Build a graph structure in haskell在haskell中构建图结构
【发布时间】:2015-12-15 19:49:14
【问题描述】:

我正在对关系数据库的类型信息进行建模。我想构建以下图表:

  1. 顶点是表格。

  2. 对于 A 中作为 B 的外键的每一列,从表 A 到表 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 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 的信息。如果没有找到,则输入数据不一致,是错误的。

这在带有引用的命令式语言中相当简单。但是,我想不出在 Haskell 中解决这个问题的方法。据我了解,这看起来很适合“打结”范式,但我似乎无法理解它。这个函数怎么写?

【问题讨论】:

  • 抱歉,convDBInfo 该怎么办?
  • 对不起,我不清楚。编辑添加信息。
  • 如果知道不会出错,为什么还要返回Either
  • 来自DBInfot 中的lookup 可能是失败(Maybe TableInfo),即使它不会发生。
  • 为什么不用HashMap的foldWithKey

标签: haskell


【解决方案1】:

我们可以通过以下方式打结:

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"

请注意,虽然复杂的数据结构通常不方便使用,因为它们与惰性无限结构无法区分,所以当我们想要打印、序列化或比较它们时,我们必须多加考虑。大多数情况下,显式键控图更易于使用,而且性能也不会差很多。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-12
    • 1970-01-01
    • 1970-01-01
    • 2013-02-04
    相关资源
    最近更新 更多