记录语法和总和类型 [英] Record syntax and sum types

查看:84
本文介绍了记录语法和总和类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对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)

在我的理解中,T1T2是使用记录语法的数据构造函数.似乎T3的定义将随着T1T2中的字段数的增加而增加.我的问题是,如果字段数很大,如何实际处理这些求和类型构造函数?或者,将求和类型与记录语法混合在一起是个好主意吗?

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 T3print $ 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆