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 有三个命名空间,一个用于运行时计算、类型和模块。

任何表示运行时计算的术语都可以在计算命名空间中命名。 datanewtype 声明在计算命名空间中创建新名称,用于构造其新类型的值,如果使用记录语法,则用于从新类型中选择字段。 class 声明在计算命名空间中为其方法创建新名称。

任何单态类型都可以在带有 type 声明的类型命名空间中命名(请参阅下面的评论,了解我对该声明中令人困惑的微妙之处的预测)。 datanewtype 声明在类型命名空间中创建新名称以构造它们声明的类型。 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.