记录语法和总和类型

时间:2016-06-06 07:57:37

标签: haskell types algebraic-data-types

我对Haskell中的和类型有这个问题。

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

T1

据我了解,T2T3是使用记录语法的数据构造函数。似乎T1的定义会随着T2var self = module.exports = { environment: undefined, beforeEach: function (browser, done) { browser.execute(function(data) { return window.navigator.userAgent; }, [], function(result) { self.environment = result.value; console.log("Run against: " + self.environment); done(); }); console.log('the new env is', self.environment); }, }; 中字段数量的增加而增加。我的问题是,如果字段数量很大,如何实际处理这些求和类型构造函数?或者,将sum类型与记录语法混合是一个好主意吗?

1 个答案:

答案 0 :(得分:7)

我不太明白你有什么顾虑,但要回答最后一行中的问题: no ,将sum类型与记录语法混合起来并不是一个好主意。一般来说,记录仍然是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)

现在,任何你能写的解构都会被合理地理解为有意义。

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

另一方面,打开构造函数的层次会变得非常繁琐,但幸运的是现在已经解决了问题:lens libraries允许你非常巧妙地组合访问器/修饰符。

说到已解决的问题:Nikita Volkov提出了一个非常好的概念,可以完全替换问题所在的记录语法。

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