Haskell 中多态类型的真实类型是隐式通用量化类型吗?
Are the real Type of Polymorphic Types in Haskell implicitly universally quantified Type?
我正在尝试澄清一些 Haskell 概念。通过数据声明定义类型时,例如:
data DatumType a b = Datum a b
一直想知道类型是DatumType
还是隐式forall a. DatumType a b
.
因为确实有 ExplicitForAll
λ> :set -XExplicitForAll
λ> :k forall a. Maybe a
forall a. Maybe a :: *
λ> :k forall a b . DatumType a b
forall a b . DatumType a b :: *
λ> :k DatumType
DatumType :: * -> * -> *
我们可以看到forall a b. DatumType a b
的种类是proper type i.e. *
然而,DatumType 本身只是一个类型构造函数。
因此这意味着多态类型如[a]是TYPE(即*)并且该类型的全名是forall a. [a]
换句话说,我要确认 Haskell 中 多态类型 的类型声明总是缩写形式,并且完整类型名称总是带有隐含的 forall a. ....
也就是说,在 data Mytype a
中,类型不是 Mytype
,也不是 Mytype a
,而是 forall a. Mytype a
,而 Mytype
是类型构造函数。
这个解释正确吗?
EDIT1(跟随@Daniel Wagner 的回答)
我想我会编辑问题,以解释所有澄清的内容来自何处。假设在学习和试验类型 类 时,我对实例 Eq (a,b) 感到困惑。为什么不用instance Eq(,),答案不只是因为在实现中需要引用类型变量。 Eq 只能在适当的类型上定义,任何可能的对实际上都是一个类型,一个多态类型。那么问题来了,但是我们在写 data (,) a b = (,) ab 的时候定义的是什么。我是在定义 (,) 还是 forall a b. (a,b).
Edit2(跟随@Ben 回答)
推动我正规化的 material 之一
:set -XExplicitForAll
上面的实验是从这里 A Gentle Introduction to Haskell, Version 98 - 2 Values, Types, and Other Goodies
摘录的以下语句
Haskell also incorporates polymorphic types---types that are universally quantified in some way over all types. Polymorphic type expressions essentially describe families of types. For example, (forall a)[a] is the family of types consisting of, for every type a, the type of lists of a. Lists of integers (e.g. [1,2,3]), lists of characters (['a','b','c']), even lists of lists of integers, etc., are all members of this family.
声明
data DatumType a b = Datum a b
声明一个新类型,DatumType
,属于* -> * -> *
。它还声明 一个 个新术语 Datum
,类型为 forall a b. a -> b -> DatumType a b
。
在正常情况下,类型签名确实隐式地普遍量化了它们在顶层提到的所有类型变量。但是数据声明不是类型签名,所以你的问题的某些部分没有意义。
在打开扩展的情况下,类型变量也可能是单态的,而不是普遍量化的。例如,
{-# LANGUAGE ScopedTypeVariables #-}
foo :: forall a. Monoid a => a -> a
foo x = mconcat xs where
xs :: [a]
xs = [x, mempty, x]
在此代码段中,所有量词都已明确显示。在 where 块内,xs
具有单态类型 [a]
,其中 a
是一个由封闭类型范围绑定的类型变量,如果插入额外的量词,代码将无法编译:
foo :: forall a. Monoid a => a -> a
foo x = mconcat xs where
xs :: forall a. [a]
xs = [x, mempty, x]
-- type error: can't match type a and type a0, whoops
有了这些信息,希望您的每个陈述的真实状态都更加清楚,但让我们一次一个地浏览它们:
I have been wondering if the type is DatumType
or implicitly forall a. DatumType a b
.
无法回答。什么类型的? DatumType
和 forall a. DatumType a b
都是合法的 type-level 表达式。
This would mean that polymorphic type such as [a] are TYPE and that the full name of the type is forall a. [a]
.
有时。量词的插入不是局部过程,而是整个类型签名的全局过程。它们隐式地浮动到顶层。所以,这是两种不同的类型:
-- these are all the same with ScopedTypeVariables off
forall a. [a] -> ()
forall a. ([a] -> ())
[a] -> ()
-- this is a different type from the ones above
(forall a. [a]) -> ()
所以如果在正常情况下,un-extended Haskell,你写了类型签名 x :: [a]
,那么 [a]
确实是 shorthand for forall a. [a]
;但是如果你写了签名 f :: [a] -> ()
,那么 [a]
将 而不是 shorthand for forall a. [a]
,因为 forall
必须从箭头的参数浮动到整个类型。
In other word, what i am after is to confirm that type declaration in haskell for polymorphic type are always in an abbreviated form, and that the full type name is always with an implicit forall a. ...
.
是的。
That is, in data Mytype a
the type is not Mytype
neither just Mytype a
, but forall a. Mytype a
, ...
类别错误。 data Mytype a
不是类型签名,所以没有类型。如果我要从这样的声明中挑出一个类型来调用“类型”,它将是单独的 Mytype
,因为这是声明创建的唯一类型。
...while Mytype
is a type constructor.
是的。
翻译成英文的定义data DatumType a b = Datum a b
是这样的:
假设有一个名为 DatumType
的新类型构造函数和一个名为 Datum
的新数据构造函数,这样对于所有类型 a
和 b
,Datum
应用于 a
类型的值和 b
类型的值导致 DatumType a b
.
类型的值
I have been wondering if the type is DatumType
or implicitly forall a. DatumType a b
.
我认为理解这里的障碍是术语“类型”可以有两种不同的含义,具体取决于上下文:
- A type 是存在于 type-level
的任何实体
- 一个类型具体就是那些type-level实体可以作为term的类型;
Type
(也称为 *
)之类的任何东西,并且只有这样的东西
这两个定义的出现基本上是因为我们使用短语“type of”来描述术语级别的事物与类型级别的事物之间的关系 - 因此将不能参与的事物包括在内似乎很奇怪“类型”意义上的关系。然而,类型表达式中存在很多不能直接参与这种关系的东西,我们想谈论它们而不必一直使用像“类型级实体”这样笨拙的短语。作为一个社区,我们似乎没有比在不同时间在这两种意义上使用“类型”更好的解决方案,并希望从上下文中清楚。
所以很明显 DatumType
不是定义 2 的类型;它需要应用于两个类型参数才能在术语级别产生某种类型。如果那是我们的想法,那么我可以理解为什么您会倾向于认为数据声明定义的“类型”是 forall a b. DatumType a b
.
但是我认为这可能是一种令人困惑的思考方式。单独使用 forall a b. DatumType a b
是可以在 所有 形式的 DatumType _ _
类型中使用的术语类型;这种类型的唯一值是 Datum undefined undefined
之类的东西。相反,当您看到 DatumType a b
时,forall a b
通常会更远;例如 Datum
构造函数本身的类型(如果你使用 GADT 语法定义它,你会写的)可以写成 Datum :: forall a b. a -> b -> DatumType a b
.
所以说“数据声明定义的类型是forall a b. DatumType a b
很奇怪。数据声明定义了整个家族类型,其中类型forall a b. DatumType a b
是一个非常有限(而且相当无用)的例子。我会说“对于所有类型 a
和 b
,数据声明定义了一个类型 DatumType a b
”;范围所涉及的“for all”概念的范围比您在单个类型表达式中用 forall
关键字可以表达的范围更广,因此我将其从正式类型表达式中移至英文描述中。
当然,如果我们专注于“类型”的定义 1,那么事情更更容易解释。数据声明只是定义了一个 DatumType
类型 * -> * -> *
.
这就引出了一个问题:哪种观点正确?
也许令人不满意的是,这两种观点之间并没有什么有趣的事情发生。 这两件事都发生了:我们得到了一个新的类型构造函数DatumType
,它具有种类* -> * -> *
,并且对于所有类型a
和b
DatumType a b
是一些术语的类型。这就是* -> * -> *
的意思。只有当你试图识别“the 类型”而没有意识到术语类型在这两种意义上都经常使用时,才会出现这种困境,所以如果你不清楚自己在哪个意义上你使用你会绊倒。
有些上下文说没有种类 *
的东西不是类型,因此 DatumType
不是真正的类型。其他人谈论 DatumType
作为一种类型。然而,这纯粹是我们选择使用的术语的不同;无论哪种方式 DatumType :: * -> * -> *
都是存在的东西,并且它在任何一种观点中的作用都是相同的。纠结于某个特定 type-level 实体是否是一种类型 不是 事情如何运作的问题,这只是英语语言用法的问题。
所以回到你的一些更具体的问题:
Hence this would mean that polymorphic type such as [a]
are TYPE (i.e. *) and that the full name of the type is forall a. [a]
In other word, what i am after is to confirm that type declaration in haskell for polymorphic type are always in an abbreviated form, and that the full type name is always with an implicit forall a. ....
正如我提到的,我认为这不太正确。是的,类型级别的 []
需要一个参数来生成 type-of-terms; [] :: * -> *
。所以根据定义 2,[]
不是类型。然而,说完整列表类型是“真正的”forall a. [a]
并不是真的正确,因为它是通用多态列表的特定类型表达式(只能是空列表的类型,或充满底部的列表值,或 是 底部值的列表)。特别是,[True, False]
是类型 [Bool]
的成员,并且 不是 类型 forall a. [a]
.
的成员
相反,[]
只是一个 type-level-种类 * -> *
的实体。你是否称之为类型取决于你。伊特呃,它不是任何术语的类型,无论哪种方式,它都是可以在类型表达式中使用的有效内容(前提是它们kind-check)。
That is, in data Mytype a
the type is not Mytype
neither just Mytype a
, but forall a. Mytype a
, while Mytype
is a type constructor.
确实Mytype
是类型构造函数。 (在“类型”一词的任一定义中;即使我们乐于称呼所有 type-level 实体类型,“类型构造函数”仍然是一个特定的类别,拥有它是一个很好的术语,因为无论某物是“类型构造函数”不能仅通过查看其种类来确定,就像您不能仅通过查看其类型来确定某物是否是数据构造函数一样)
确实Mytype a
本身没有意义;它必须在类型变量 a
在范围内的范围内使用。
认为 forall a. Mytype a
是“由 [=61= 定义的类型”的正确思考方式是不正确的。对于 any 类型 a
Mytype a
是一个类型;forall a. Mytype a
是一个 特定的 类型表达式,它不包括我们可以使用 Mytype
类型构造函数形成的大多数类型.
所以任何时候你想使用 Mytype a
都会有一个 forall
某处(显式或隐式)。但它通常会比立即包含 Mytype a
更远;像 someFunc :: forall a. a -> Bool -> MyType a
.
OP 对另一个答案发表了评论,我认为解决这个问题会很有见地:
I think I will edit the question, to explain where the all thingy of clarification is coming from. Let’s just say that while learning and experimenting with type classes, I was confused about instance Eq (a,b)
. Why not instance Eq (,)
, and the answer is not just because one need to refer to the type variable in the implementation. Eq
can only be defined on a proper type, and any possible pair is actually a type, a polymorphic type. Then came the question, but what are we defining when we write data (,) a b = (,) a b
. Am I defining (,)
or forall a b. (a,b)
.
请记住,使类型成为 Eq
的实例意味着您可以比较该类型的 值 是否相等。
当你说 instance Eq (a, b)
时,它实际上意味着 instance forall a b. Eq (a, b)
;在英语中“对于所有类型 a
和 b
,类型 (a, b)
是 class Eq
的成员。这意味着您可以选择任何两种类型例如,对它们应用 (,)
类型构造函数,结果类型将是一些使用值,您可以比较是否相等。(这当然不是真的,我们真正使用的实例更像是 instance forall a b. (Eq a, Eq b) => Eq (a, b)
, 因为我们需要 Eq a
和 Eq b
)
instance Eq (,)
是错误的,因为它说“类型构造函数 (,) 是 class Eq
的成员”。 “可以比较 (,)
的值是否相等”没有意义,因为 (,)
不是那种可以有值的东西。
但是(,)
仍然是存在的东西!直接就是data (,) a b = (,) a b
定义的东西。这只是一种 * -> * -> *
类型的东西,我们不能为其创建 Eq
实例。短语“Eq
can only be defined on a proper type”使用的是“type”的定义,它只包括种类为 *
的东西,但请记住,这个定义“不是一个正确的类型”并不意味着“不是真实的东西”,它只是意味着我们选择(至少在那个特定的句子中)使用具有狭义含义的“类型”一词。 class Eq
是 定义的 作为成员的东西 *
,仅此而已。其他 classes 可以定义为具有不同种类的事物作为成员;如果他们有种类 * -> * -> *
的成员,那么 (,)
本身可以是那些 class 的实例。例如,查看 Bifunctor
的实例列表。 Eq
实例必须是 Eq (a, b)
而不是 Eq (,)
的事实确实 不是 暗示 (,)
不是“真的”存在于类型级别的有效实体。
我正在尝试澄清一些 Haskell 概念。通过数据声明定义类型时,例如:
data DatumType a b = Datum a b
一直想知道类型是DatumType
还是隐式forall a. DatumType a b
.
因为确实有 ExplicitForAll
λ> :set -XExplicitForAll
λ> :k forall a. Maybe a
forall a. Maybe a :: *
λ> :k forall a b . DatumType a b
forall a b . DatumType a b :: *
λ> :k DatumType
DatumType :: * -> * -> *
我们可以看到forall a b. DatumType a b
的种类是proper type i.e. *
然而,DatumType 本身只是一个类型构造函数。
因此这意味着多态类型如[a]是TYPE(即*)并且该类型的全名是forall a. [a]
换句话说,我要确认 Haskell 中 多态类型 的类型声明总是缩写形式,并且完整类型名称总是带有隐含的 forall a. ....
也就是说,在 data Mytype a
中,类型不是 Mytype
,也不是 Mytype a
,而是 forall a. Mytype a
,而 Mytype
是类型构造函数。
这个解释正确吗?
EDIT1(跟随@Daniel Wagner 的回答)
我想我会编辑问题,以解释所有澄清的内容来自何处。假设在学习和试验类型 类 时,我对实例 Eq (a,b) 感到困惑。为什么不用instance Eq(,),答案不只是因为在实现中需要引用类型变量。 Eq 只能在适当的类型上定义,任何可能的对实际上都是一个类型,一个多态类型。那么问题来了,但是我们在写 data (,) a b = (,) ab 的时候定义的是什么。我是在定义 (,) 还是 forall a b. (a,b).
Edit2(跟随@Ben 回答)
推动我正规化的 material 之一
:set -XExplicitForAll
上面的实验是从这里 A Gentle Introduction to Haskell, Version 98 - 2 Values, Types, and Other Goodies
Haskell also incorporates polymorphic types---types that are universally quantified in some way over all types. Polymorphic type expressions essentially describe families of types. For example, (forall a)[a] is the family of types consisting of, for every type a, the type of lists of a. Lists of integers (e.g. [1,2,3]), lists of characters (['a','b','c']), even lists of lists of integers, etc., are all members of this family.
声明
data DatumType a b = Datum a b
声明一个新类型,DatumType
,属于* -> * -> *
。它还声明 一个 个新术语 Datum
,类型为 forall a b. a -> b -> DatumType a b
。
在正常情况下,类型签名确实隐式地普遍量化了它们在顶层提到的所有类型变量。但是数据声明不是类型签名,所以你的问题的某些部分没有意义。
在打开扩展的情况下,类型变量也可能是单态的,而不是普遍量化的。例如,
{-# LANGUAGE ScopedTypeVariables #-}
foo :: forall a. Monoid a => a -> a
foo x = mconcat xs where
xs :: [a]
xs = [x, mempty, x]
在此代码段中,所有量词都已明确显示。在 where 块内,xs
具有单态类型 [a]
,其中 a
是一个由封闭类型范围绑定的类型变量,如果插入额外的量词,代码将无法编译:
foo :: forall a. Monoid a => a -> a
foo x = mconcat xs where
xs :: forall a. [a]
xs = [x, mempty, x]
-- type error: can't match type a and type a0, whoops
有了这些信息,希望您的每个陈述的真实状态都更加清楚,但让我们一次一个地浏览它们:
I have been wondering if the type is
DatumType
or implicitlyforall a. DatumType a b
.
无法回答。什么类型的? DatumType
和 forall a. DatumType a b
都是合法的 type-level 表达式。
This would mean that polymorphic type such as [a] are TYPE and that the full name of the type is
forall a. [a]
.
有时。量词的插入不是局部过程,而是整个类型签名的全局过程。它们隐式地浮动到顶层。所以,这是两种不同的类型:
-- these are all the same with ScopedTypeVariables off
forall a. [a] -> ()
forall a. ([a] -> ())
[a] -> ()
-- this is a different type from the ones above
(forall a. [a]) -> ()
所以如果在正常情况下,un-extended Haskell,你写了类型签名 x :: [a]
,那么 [a]
确实是 shorthand for forall a. [a]
;但是如果你写了签名 f :: [a] -> ()
,那么 [a]
将 而不是 shorthand for forall a. [a]
,因为 forall
必须从箭头的参数浮动到整个类型。
In other word, what i am after is to confirm that type declaration in haskell for polymorphic type are always in an abbreviated form, and that the full type name is always with an implicit
forall a. ...
.
是的。
That is, in
data Mytype a
the type is notMytype
neither justMytype a
, butforall a. Mytype a
, ...
类别错误。 data Mytype a
不是类型签名,所以没有类型。如果我要从这样的声明中挑出一个类型来调用“类型”,它将是单独的 Mytype
,因为这是声明创建的唯一类型。
...while
Mytype
is a type constructor.
是的。
翻译成英文的定义data DatumType a b = Datum a b
是这样的:
假设有一个名为 DatumType
的新类型构造函数和一个名为 Datum
的新数据构造函数,这样对于所有类型 a
和 b
,Datum
应用于 a
类型的值和 b
类型的值导致 DatumType a b
.
I have been wondering if the type is
DatumType
or implicitlyforall a. DatumType a b
.
我认为理解这里的障碍是术语“类型”可以有两种不同的含义,具体取决于上下文:
- A type 是存在于 type-level 的任何实体
- 一个类型具体就是那些type-level实体可以作为term的类型;
Type
(也称为*
)之类的任何东西,并且只有这样的东西
这两个定义的出现基本上是因为我们使用短语“type of”来描述术语级别的事物与类型级别的事物之间的关系 - 因此将不能参与的事物包括在内似乎很奇怪“类型”意义上的关系。然而,类型表达式中存在很多不能直接参与这种关系的东西,我们想谈论它们而不必一直使用像“类型级实体”这样笨拙的短语。作为一个社区,我们似乎没有比在不同时间在这两种意义上使用“类型”更好的解决方案,并希望从上下文中清楚。
所以很明显 DatumType
不是定义 2 的类型;它需要应用于两个类型参数才能在术语级别产生某种类型。如果那是我们的想法,那么我可以理解为什么您会倾向于认为数据声明定义的“类型”是 forall a b. DatumType a b
.
但是我认为这可能是一种令人困惑的思考方式。单独使用 forall a b. DatumType a b
是可以在 所有 形式的 DatumType _ _
类型中使用的术语类型;这种类型的唯一值是 Datum undefined undefined
之类的东西。相反,当您看到 DatumType a b
时,forall a b
通常会更远;例如 Datum
构造函数本身的类型(如果你使用 GADT 语法定义它,你会写的)可以写成 Datum :: forall a b. a -> b -> DatumType a b
.
所以说“数据声明定义的类型是forall a b. DatumType a b
很奇怪。数据声明定义了整个家族类型,其中类型forall a b. DatumType a b
是一个非常有限(而且相当无用)的例子。我会说“对于所有类型 a
和 b
,数据声明定义了一个类型 DatumType a b
”;范围所涉及的“for all”概念的范围比您在单个类型表达式中用 forall
关键字可以表达的范围更广,因此我将其从正式类型表达式中移至英文描述中。
当然,如果我们专注于“类型”的定义 1,那么事情更更容易解释。数据声明只是定义了一个 DatumType
类型 * -> * -> *
.
这就引出了一个问题:哪种观点正确?
也许令人不满意的是,这两种观点之间并没有什么有趣的事情发生。 这两件事都发生了:我们得到了一个新的类型构造函数DatumType
,它具有种类* -> * -> *
,并且对于所有类型a
和b
DatumType a b
是一些术语的类型。这就是* -> * -> *
的意思。只有当你试图识别“the 类型”而没有意识到术语类型在这两种意义上都经常使用时,才会出现这种困境,所以如果你不清楚自己在哪个意义上你使用你会绊倒。
有些上下文说没有种类 *
的东西不是类型,因此 DatumType
不是真正的类型。其他人谈论 DatumType
作为一种类型。然而,这纯粹是我们选择使用的术语的不同;无论哪种方式 DatumType :: * -> * -> *
都是存在的东西,并且它在任何一种观点中的作用都是相同的。纠结于某个特定 type-level 实体是否是一种类型 不是 事情如何运作的问题,这只是英语语言用法的问题。
所以回到你的一些更具体的问题:
Hence this would mean that polymorphic type such as
[a]
are TYPE (i.e. *) and that the full name of the type is forall a. [a]In other word, what i am after is to confirm that type declaration in haskell for polymorphic type are always in an abbreviated form, and that the full type name is always with an implicit
forall a. ....
正如我提到的,我认为这不太正确。是的,类型级别的 []
需要一个参数来生成 type-of-terms; [] :: * -> *
。所以根据定义 2,[]
不是类型。然而,说完整列表类型是“真正的”forall a. [a]
并不是真的正确,因为它是通用多态列表的特定类型表达式(只能是空列表的类型,或充满底部的列表值,或 是 底部值的列表)。特别是,[True, False]
是类型 [Bool]
的成员,并且 不是 类型 forall a. [a]
.
相反,[]
只是一个 type-level-种类 * -> *
的实体。你是否称之为类型取决于你。伊特呃,它不是任何术语的类型,无论哪种方式,它都是可以在类型表达式中使用的有效内容(前提是它们kind-check)。
That is, in
data Mytype a
the type is notMytype
neither justMytype a
, butforall a. Mytype a
, whileMytype
is a type constructor.
确实Mytype
是类型构造函数。 (在“类型”一词的任一定义中;即使我们乐于称呼所有 type-level 实体类型,“类型构造函数”仍然是一个特定的类别,拥有它是一个很好的术语,因为无论某物是“类型构造函数”不能仅通过查看其种类来确定,就像您不能仅通过查看其类型来确定某物是否是数据构造函数一样)
确实Mytype a
本身没有意义;它必须在类型变量 a
在范围内的范围内使用。
认为 forall a. Mytype a
是“由 [=61= 定义的类型”的正确思考方式是不正确的。对于 any 类型 a
Mytype a
是一个类型;forall a. Mytype a
是一个 特定的 类型表达式,它不包括我们可以使用 Mytype
类型构造函数形成的大多数类型.
所以任何时候你想使用 Mytype a
都会有一个 forall
某处(显式或隐式)。但它通常会比立即包含 Mytype a
更远;像 someFunc :: forall a. a -> Bool -> MyType a
.
OP 对另一个答案发表了评论,我认为解决这个问题会很有见地:
I think I will edit the question, to explain where the all thingy of clarification is coming from. Let’s just say that while learning and experimenting with type classes, I was confused about
instance Eq (a,b)
. Why notinstance Eq (,)
, and the answer is not just because one need to refer to the type variable in the implementation.Eq
can only be defined on a proper type, and any possible pair is actually a type, a polymorphic type. Then came the question, but what are we defining when we writedata (,) a b = (,) a b
. Am I defining(,)
orforall a b. (a,b)
.
请记住,使类型成为 Eq
的实例意味着您可以比较该类型的 值 是否相等。
当你说 instance Eq (a, b)
时,它实际上意味着 instance forall a b. Eq (a, b)
;在英语中“对于所有类型 a
和 b
,类型 (a, b)
是 class Eq
的成员。这意味着您可以选择任何两种类型例如,对它们应用 (,)
类型构造函数,结果类型将是一些使用值,您可以比较是否相等。(这当然不是真的,我们真正使用的实例更像是 instance forall a b. (Eq a, Eq b) => Eq (a, b)
, 因为我们需要 Eq a
和 Eq b
)
instance Eq (,)
是错误的,因为它说“类型构造函数 (,) 是 class Eq
的成员”。 “可以比较 (,)
的值是否相等”没有意义,因为 (,)
不是那种可以有值的东西。
但是(,)
仍然是存在的东西!直接就是data (,) a b = (,) a b
定义的东西。这只是一种 * -> * -> *
类型的东西,我们不能为其创建 Eq
实例。短语“Eq
can only be defined on a proper type”使用的是“type”的定义,它只包括种类为 *
的东西,但请记住,这个定义“不是一个正确的类型”并不意味着“不是真实的东西”,它只是意味着我们选择(至少在那个特定的句子中)使用具有狭义含义的“类型”一词。 class Eq
是 定义的 作为成员的东西 *
,仅此而已。其他 classes 可以定义为具有不同种类的事物作为成员;如果他们有种类 * -> * -> *
的成员,那么 (,)
本身可以是那些 class 的实例。例如,查看 Bifunctor
的实例列表。 Eq
实例必须是 Eq (a, b)
而不是 Eq (,)
的事实确实 不是 暗示 (,)
不是“真的”存在于类型级别的有效实体。