我对Haskell中的和类型有这个问题。
我想创建一个由两个或多个其他类型组成的和类型,每个类型可能包含多个字段。一个简单的例子是这样的:
T1
据我了解,T2
和T3
是使用记录语法的数据构造函数。似乎T1
的定义会随着T2
或var 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类型与记录语法混合是一个好主意吗?
答案 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提出了一个非常好的概念,可以完全替换问题所在的记录语法。
† 嗯......实际上这些不是任何正确意义上的子类型,但你明白我的意思。