记录语法和总和类型 [英] Record syntax and sum types
问题描述
我对Haskell中的总和类型有疑问.
I have this question about sum types in Haskell.
我想创建一个由两个或多个其他类型组成的求和类型,并且每个类型都可以包含多个字段.一个简单的例子是这样的:
I'd like to create a sum type which is comprised of two or more other types, and each of the types may contain multiple fields. A trivial example would be like this:
data T3 = T1 { a :: Int, b :: Float} | T2 { x :: Char } deriving (Show)
在我的理解中,T1
和T2
是使用记录语法的数据构造函数.似乎T3
的定义将随着T1
或T2
中的字段数的增加而增加.我的问题是,如果字段数很大,如何实际处理这些求和类型构造函数?或者,将求和类型与记录语法混合在一起是个好主意吗?
In my understanding, T1
and T2
are data constructors which use record syntax. It seems that the definition of T3
will grow as the number of fields in T1
or T2
increases. My question is that how to practically handle these sum type constructors if the number of fields are large? Or, is it a good idea to mix sum type with record syntax?
推荐答案
我不太了解您所关注的问题,但是在最后一行回答问题:否,它是将求和类型与记录语法混合不是一个好主意.总体而言,记录仍然是Haskell语言的弱点.他们根本无法很好地处理范围.只要您有一些带有不同记录标签的单独类型,通常就可以了,但是只要出现总和类型或名称冲突,它就会变得很讨厌.
I don't quite understand what concerns you have, but to answer the question in the last line: no, it is rather not a good idea to mix sum types with record syntax. Records in general remain a bit of a weak spot of the Haskell language; they don't handle scoping very well at all. It's usually fine as long as you just have some seperate types with different record labels, but as soon as sum types or name clashes come in it gets rather nasty.
尤其是,Haskell允许您将T1
构造函数的记录字段访问器用于任何T3
类型的值. print $ a (T2 'x')
会在没有警告的情况下进行编译,但在运行时会很难预见错误.
In particular, Haskell permits you to use a record field accessor of the T1
constructor for any value of type T3
– print $ a (T2 'x')
will compile without warnings, but give a rather hard to foresee error at runtime.
在您的示例中,很幸运,您可以轻松避免这种麻烦:
In your example, it fortunately looks like you can easily avoid that kind of trouble:
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)
现在,您可以编写的任何解构方法都将经过类型检查,使其有意义.
Now, any deconstruction you could write will be properly typechecked to make sense.
这种有意义的小型专业子类型† 的结构通常比单个整体类型要好处理,尤其是当您有很多只处理部分数据的函数时结构.
And such a structure of meaningful, small specialised sub-types† is generally better to handle than a single monolithic type, especially if you have many functions that really deal only with part of the data structure.
相反的一面是,解开构造函数的各个层是很繁琐的,但这幸运的是现在已解决了一个问题: lens库使您可以非常整齐地编写访问器/修饰符.
The flip side is that it gets quadratically tedious to unwrap the layers of constructors, but that's fortunately a solved problem now: lens libraries allow you to compose accessor/modifiers very neatly.
谈到已解决的问题: Nikita Volkov 提出了一个非常好的概念替换问题缠身的记录语法.
Speaking of solved problems: Nikita Volkov has come up with a really nice concept for entirely replacing the problem-ridden record syntax.
† 嗯...实际上,这些词在任何适当的意义上都不是子类型,但是您明白我的意思.
这篇关于记录语法和总和类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!