记录语法和总和类型

liu*_*tao 1 haskell types algebraic-data-types

我有关于Haskell中的和类型的这个问题.

我想创建一个由两个或更多其他类型组成的和类型,每个类型可能包含多个字段.一个简单的例子是这样的:

data T3 = T1 { a :: Int, b :: Float} | T2 { x :: Char } deriving (Show)
Run Code Online (Sandbox Code Playgroud)

在我的理解,T1并且T2是其使用记录语法数据构造.看来,定义T3将成长为中域的数量T1T2增加.我的问题是,如果字段数量很大,如何实际处理这些求和类型构造函数?或者,将sum类型与记录语法混合是一个好主意吗?

lef*_*out 9

我不太明白你有什么顾虑,但在最后一行回答这个问题:,将和类型与记录语法混合起来并不是一个好主意.一般来说,记录仍然是Haskell语言的一个弱点; 他们根本不能很好地处理范围.它通常很好,只要你有一些单独的类型与不同的唱片标签,但一旦总和类型或名称冲突进来它变得相当讨厌.

特别是,Haskell允许您T1为任何类型的值使用构造函数的记录字段访问器T3- print $ a (T2 'x')将在没有警告的情况下编译,但在运行时很难预见错误.

在您的示例中,幸运的是,您可以轻松避免这种麻烦:

data T3 = T3_1 T1 | T3_2 T2
           deriving (Show)
data T1 = T1 { a :: Int
             , b :: Float}
           deriving (Show)
data T2 = T2 { x :: Char }
           deriving (Show)
Run Code Online (Sandbox Code Playgroud)

现在,任何你可以编写的解构都会被合理地改编成有意义的.

这种有意义的小型专用子类型的结构通常比单个单一类型更好处理,特别是如果你有许多功能只能真正处理部分数据结构.

另一方面是打开构造函数层的方形繁琐,但幸运的是现在解决了一个问题:镜头库允许你非常巧妙地组合访问器/修饰符.

说到已解决的问题:Nikita Volkov提出了一个非常好的概念,完全取代了问题缠身的记录语法.


嗯...实际上这些都不是任何正确意义上的亚型,但你明白我的意思.