选择什么数据结构来确定通用性但安全性?

时间:2011-05-11 07:49:34

标签: data-structures haskell types

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

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

现在我有3个任务:

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

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

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

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

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

    编辑:为了让您更好地了解,它是将业务数据映射到文本表示形式,如表单和字母。 E.g:

    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映射到那些中间表格数据;我需要将这些表单数据映射到实际的表单文本表示;我需要创建草稿中间表格数据。一方面我讨厌重复这些数据标签,另一方面它给了我安全,我不会在映射时混淆任何标签。是否有银弹?

1 个答案:

答案 0 :(得分:3)

这样的深度结构化数据在Haskell中最常用的表示为嵌套的代数数据类型,就像你所做的那样。为什么?它为数据提供了最多的类型结构和安全性,防止功能将数据放入错误的格式。通过对某些类型进行newtyping可以获得更高的安全性,从而增加每个字段中数据之间的差异。

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

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