具有两个以上选项的 Tuple 或 Either 相反的名称是什么?

What is the name for the contrary of Tuple or Either with more than two options?

有一个元组作为任意数量类型的乘积,并且有一个 Either 作为两种类型的总和。任意数量类型的 Sum 的名称是什么,像这样

data Thing a b c d ... = Thing1 a | Thing2 b | Thing3 c | Thing4 d | ...

有没有标准的实现?

HaXml 包中有一些带有 OneOfNTwoOfN, .. 构造函数的预定义版本。

这样的类型通常称为 sumvariantuniontagged union类型。由于此功能是 Haskell 中 data 类型的 built-in 功能,因此没有在 Haskell 代码中广泛使用的名称。报告仅称它们为 "algebraic datatypes"(通常缩写为 ADT),因此这是您在评论中最常看到的名称,但此名称包括只有一个数据构造函数的类型,它们只是简单意义上的求和类型.

在提出反对使用此类类型的建议之前,让我解释一下背景。

Either是sum类型,pair或2-tuple是product类型。总和和乘积可以存在于任意多个基础类型(集合)中。但是,在 Haskell 中,只有元组具有各种开箱即用的大小。 Either 另一方面,可以(任意)嵌套来实现:Either Foo (Either Bar Baz).

当然很容易定义例如类型 Either3Either4 等,本着三元组、四元组等的精神。

data Either3 a  b  c = Left     a |     Middle b     | Right     c
data Either4 a b c d = LeftMost a | Left b | Right c | RightMost d

...如果你真的想要的话。或者你可以找到一个图书馆这样做,但我怀疑你可以用任何标准称它为 "standard"...

但是,如果您确实定义了自己的泛型求和和求积类型,它们将完全同构于任何在结构上等效的类型,无论它在哪里定义。这意味着您可以相对轻松地很好地调整您的代码以与使用替代定义的任何其他代码交互。

此外,它甚至很有可能是有益的,因为这样你就可以为你的求和和乘积类型赋予更有意义的描述性名称,而不是使用通用元组和任何一个。事实上,有些人建议使用自定义类型,因为它本质上增加了静态类型安全性。这也适用于 non-sum/product 类型,例如:

employment :: Bool  -- so which one is unemplyed and which one is employed?

data Empl = Employed | Unemployed
employment' :: Empl  -- no ambiguity

person :: (Name, Age)  -- yeah but when you see ("Erik", 29), is it just some random pair of name and age, or does it represent a person?

data Person = Person { name :: Name, age :: Age }
person' :: Person  -- no ambiguity

——在上面,Person 确实编码了一种产品类型,但附加了更多的含义。你也可以做 newtype Person = Person (Name, Age),而且它实际上是相当等价的。所以我总是更喜欢一个漂亮的 intention-revealing 自定义类型。 Either 和自定义总和类型也是如此。

所以基本上,Haskell 为您提供了使用非常清晰易读的语法快速构建您自己的自定义类型所需的所有工具,因此我们最好不要使用元组等原始类型。但是,很高兴了解这种同构,例如在泛型编程的上下文中。如果您想了解更多相关信息,可以 google "scrap your boilerplate" 和 "template your boilerplate" 以及“(数据类型)泛型编程”。


P.S。之所以分别称为sum和product类型,是因为它们分别对应set-union(sum)和set-product。因此,产品类型 (a, b) 描述的集合中值的数量(或唯一实例,如果你愿意的话)是 a 中值的数量与 a 中值的数量的乘积=23=]。例如 (Bool, Bool) 正好有 2*2 个值:(True, True)(False, False)(True, False)(False, True).

但是 Either Bool Bool 有 2+2 个值,Left TrueLeft FalseRight TrueRight False。所以它恰好是相同的数字,但显然不是一般情况。

当然,这也适用于我们的自定义 Person 产品类型,所以同样,没有理由使用 Either 和元组。

在一般上下文中,这通常使用 Either

归纳完成
data (:+:) f g a = L1 (f a) | R1 (g a)

后者在 GHC.Generics 中定义,以匹配它处理事情的有趣方式。

事实上,通用方法是将每个代数数据类型分解为 (:+:)

data (:*:) f g a = f a :*: f a

以及一些额外的东西。也就是把所有的东西都变成二进制的和和二进制的积。

在更具体的上下文中,对于比对更大的事物或具有比 Either 更多选项的事物,您几乎总是最好使用自定义代数数据类型,正如其他人所讨论的那样。稍微大一点的元组(三元组,也许是四元组)对局部 one-off 结构很有用,但很难看出你如何使用更大的通用总和类型作为 one-offs.