【问题标题】:What data structure to pick for genericity but safety?为通用性和安全性选择什么数据结构?
【发布时间】:2011-05-12 00:04:35
【问题描述】:

假设我有一个很长的数据结构定义

data A = A {
  x1 :: String
, x2 :: String
...
, x50 :: String
}

现在我有 3 个任务:

  1. 创建 A 的草稿实例,例如 A { x1 = "this is x1", ... }
  2. 从其他数据结构创建 A 的实例
  3. 从 A 的实例创建另一个数据实例

这三个任务涉及繁琐的标签 x1、...、x50 的复制。 更好的解决方案是通用列表

[
  Foo "x1" aValue1
, Foo "x2" aValue2
...
]

因为它会使遍历和创建草稿变得更加容易(列表定义已经是草稿)。缺点是在此之间映射其他数据结构会更危险,因为您会丢失静态类型检查。

这有意义吗? 有通用但安全的解决方案吗?

编辑:为了让您有更好的想法,它是关于将业务数据映射到表格和字母等文本表示。例如:

data TaxData = TaxData {
  taxId :: String
, income :: Money
, taxPayed :: Money,
, isMarried :: Bool
...
}


data TaxFormA = TaxFormA {
  taxId :: Text
, isMarried :: Text
  ...
}
data TaxFormB = TaxFormB {
  taxId :: Text
, taxPayedRounded :: Text
...
}

这些被转换成文本流,代表实际的形式。如果我一次通过税收数据创建一个表格,明年任何表格字段都会移动,例如成为一个流浪的“0.0”,我不知道它属于哪里。这就是中间数据结构的用途:它使创建草稿数据变得容易。

所以我需要将实际的 TaxData 映射到那些中间表单数据;我需要将这些表单数据映射到实际的表单文本表示;我需要创建草稿中间表单数据。一方面我讨厌重复这些数据标签,另一方面它给了我安全感,我在映射时不会混淆任何标签。有灵丹妙药吗?

【问题讨论】:

  • 数据结构的所有元素是否都属于同一类型(例如列表),它们是否都仅通过索引来区分?标签的数量是否重要?
  • 标签的数量之所以重要,是因为目前我必须在我的代码中复制大量数据标签至少 3 次。而且我在草稿模式下也基本上需要重复标签名称。
  • 使用SYB或Uniplate怎么样?此外,您可能会在 GHC 中使用 RecordWildcards 扩展获得一些里程。 (在这里发布你的大部分程序可能会有所帮助)
  • 如果我理解正确 - 我觉得,您使用 data-type 保存数据标签的解决方案过于静态。为什么不使用 Data.Map 来组织这些标签,将它们映射到 Array 或 List 的索引?
  • @phynfo:列表的缺点是很容易混淆元素的顺序和含义。使用地图,您可能会以与数据结构标签相同的方式重复键。 :(

标签: data-structures haskell types


【解决方案1】:

像这样的深度结构化数据在 Haskell 中最为惯用地表示为嵌套的代数数据类型,正如您所做的那样。为什么?它为数据提供了最大的类型结构和安全性,防止函数将数据放入错误的格式。可以通过新键入一些类型来获得进一步的安全性,以增加每个字段中数据之间的差异。

但是,像这样的非常大的 ADT 可能难以命名和操作。例如,编译器设计中的一个常见情况是指定如此大的 ADT,为了帮助编写编译器代码,我们倾向于使用许多通用编程技巧:SYB、元编程,甚至是 Template Haskell,以生成所有我们需要的样板。

因此,总而言之,我会保留您正在采用的 ADT 方法,但请考虑使用泛型(例如 SYB 或 Template Haskell)来生成您的一些定义和辅助函数。

【讨论】:

    猜你喜欢
    • 2014-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-07
    • 1970-01-01
    • 2014-04-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多