Haskell 可绑定实体?
Haskell Bindable entities?
我看到,在 John Wiley 于 2004 年出版的编程语言设计概念一书中,有一个 bindables 的定义:
"A bindable entity is one that may be bound to an identifier.
Programming languages vary in the kinds of entity that are bindable:
• C’s bindable entities are types, variables, and function procedures.
• JAVA’s bindable entities are values, local variables, instance and
class variables, methods, classes, and packages.
• ADA’s bindable entities include types, values, variables,
procedures, exceptions, packages, and tasks."
我很好奇,Haskell中有哪些可绑定实体?
Haskell 有三个命名空间,一个用于运行时计算、类型和模块。
任何表示运行时计算的术语都可以在计算命名空间中命名。 data
和 newtype
声明在计算命名空间中创建新名称,用于构造其新类型的值,如果使用记录语法,则用于从新类型中选择字段。 class
声明在计算命名空间中为其方法创建新名称。
任何单态类型都可以在带有 type
声明的类型命名空间中命名(请参阅下面的评论,了解我对该声明中令人困惑的微妙之处的预测)。 data
和 newtype
声明在类型命名空间中创建新名称以构造它们声明的类型。 class
声明在类型命名空间中为其创建的约束创建新名称。
module
声明在模块命名空间中创建新名称。
GHC扩展了Haskell,添加了多种新的绑定名称的方式(几乎都在类型命名空间中);一个完整的列表对于这种格式来说可能太大了,但是 the manual 非常好并且涵盖了所有内容。
现在,进入 type
的微妙之处。我预测会出现的一种混淆是:我说只能命名单态类型。但是有人可能会反对我当然可以写,例如
type TypeOfIdMono a = a -> a
id :: TypeOfIdMono a
看起来它已经命名了一个多态类型。我声称 Haskell 使 forall
隐含的倾向反而混淆了这个问题,并且 TypeOfId a
实际上是单态的。对于明确的 foralls,这是这样写的:
type TypeOfIdMono a = a -> a
id :: forall a. TypeOfIdMono a
也就是说:我们实际上并没有在这里命名 id
的类型,而是只在 a
上运行的单态函数的类型。 id
还表示调用者可以选择 a
—— 也就是说,该函数是多态的。比较此声明,这在标准 Haskell 中是不允许的(尽管可以通过 GHC 扩展获得,如上所述):
type TypeOfIdPoly = forall a. a -> a
id :: TypeOfIdPoly
这里我们真的命名了一个多态类型
简而言之:可以而且应该区分三个正交概念:"parameterized types"(例如 TypeOfIdMono
需要一个额外的参数),提到类型变量的类型(例如 TypeOfIdMono a
) 和多态类型(例如 TypeOfIdPoly
),它们必须具有 forall
.
我看到,在 John Wiley 于 2004 年出版的编程语言设计概念一书中,有一个 bindables 的定义:
"A bindable entity is one that may be bound to an identifier. Programming languages vary in the kinds of entity that are bindable:
• C’s bindable entities are types, variables, and function procedures.
• JAVA’s bindable entities are values, local variables, instance and class variables, methods, classes, and packages.
• ADA’s bindable entities include types, values, variables, procedures, exceptions, packages, and tasks."
我很好奇,Haskell中有哪些可绑定实体?
Haskell 有三个命名空间,一个用于运行时计算、类型和模块。
任何表示运行时计算的术语都可以在计算命名空间中命名。 data
和 newtype
声明在计算命名空间中创建新名称,用于构造其新类型的值,如果使用记录语法,则用于从新类型中选择字段。 class
声明在计算命名空间中为其方法创建新名称。
任何单态类型都可以在带有 type
声明的类型命名空间中命名(请参阅下面的评论,了解我对该声明中令人困惑的微妙之处的预测)。 data
和 newtype
声明在类型命名空间中创建新名称以构造它们声明的类型。 class
声明在类型命名空间中为其创建的约束创建新名称。
module
声明在模块命名空间中创建新名称。
GHC扩展了Haskell,添加了多种新的绑定名称的方式(几乎都在类型命名空间中);一个完整的列表对于这种格式来说可能太大了,但是 the manual 非常好并且涵盖了所有内容。
现在,进入 type
的微妙之处。我预测会出现的一种混淆是:我说只能命名单态类型。但是有人可能会反对我当然可以写,例如
type TypeOfIdMono a = a -> a
id :: TypeOfIdMono a
看起来它已经命名了一个多态类型。我声称 Haskell 使 forall
隐含的倾向反而混淆了这个问题,并且 TypeOfId a
实际上是单态的。对于明确的 foralls,这是这样写的:
type TypeOfIdMono a = a -> a
id :: forall a. TypeOfIdMono a
也就是说:我们实际上并没有在这里命名 id
的类型,而是只在 a
上运行的单态函数的类型。 id
还表示调用者可以选择 a
—— 也就是说,该函数是多态的。比较此声明,这在标准 Haskell 中是不允许的(尽管可以通过 GHC 扩展获得,如上所述):
type TypeOfIdPoly = forall a. a -> a
id :: TypeOfIdPoly
这里我们真的命名了一个多态类型
简而言之:可以而且应该区分三个正交概念:"parameterized types"(例如 TypeOfIdMono
需要一个额外的参数),提到类型变量的类型(例如 TypeOfIdMono a
) 和多态类型(例如 TypeOfIdPoly
),它们必须具有 forall
.