首页 > 解决方案 > Haskell 可绑定实体?

问题描述

我看到,在 John Wiley 2004 年的《编程语言设计概念》一书中,有一个可绑定对象的定义:

“可绑定实体是可以绑定到标识符的实体。编程语言在可绑定实体的种类上有所不同:

• C 的可绑定实体是类型、变量和函数过程。

• JAVA 的可绑定实体是值、局部变量、实例和类变量、方法、类和包。

• ADA 的可绑定实体包括类型、值、变量、过程、异常、包和任务。”

我很好奇,Haskell 中有哪些可绑定实体?

标签: haskelltheory

解决方案


Haskell 具有三个命名空间,每个命名空间用于运行时计算、类型和模块。

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

任何单态类型都可以在带有type声明的类型命名空间中命名(请参阅下面的评论,了解我对本声明中令人困惑的细微之处的预测)。datanewtype声明在类型命名空间中创建新名称以构造它们声明的类型。class声明在类型命名空间中为它们创建的约束创建新名称。

module声明在模块命名空间中创建新名称。

GHC 扩展了 Haskell,增加了多种新的方法来绑定名称(几乎都在类型命名空间中);对于这种格式,一个完整的列表可能太大了,但该手册非常好,涵盖了所有内容。

现在,到type. 我预测会出现的一个混淆是:我说只能命名单态类型。但是有人可能会反对我当然可以写,例如

type TypeOfIdMono a = a -> a
id :: TypeOfIdMono a

看起来它已经命名了一个多态类型。我声称 Haskell 使foralls 隐含的倾向反而混淆了这个问题,这TypeOfId a实际上是单态的。有了明确的 foralls,这已经写成:

type TypeOfIdMono a = a -> a
id :: forall a. TypeOfIdMono a

那就是:我们实际上并没有id在这里命名 s 的类型,而是只对as 进行操作的单态函数的类型。id另外说调用者可以选择a——也就是说,函数是多态的。比较这个声明,它在标准 Haskell 中是不允许的(尽管可以通过 GHC 扩展获得,如上所述):

type TypeOfIdPoly = forall a. a -> a
id :: TypeOfIdPoly

在这里,我们确实命名了一个多态类型。

简而言之:可以而且应该区分三个正交概念:“参数化类型”(例如TypeOfIdMono,它需要一个额外的参数)、提到类型变量的类型(例如TypeOfIdMono a)和多态类型(例如TypeOfIdPoly),它们必须具有forall.


推荐阅读