我正在阅读一篇关于依赖类型编程的论文,并看到以下引用:
"[…与Haskell的类型类相比,数据类型[…]是封闭的",在这个意义上,如果不扩展数据类型,就不能向宇宙添加新类型。
我的新手问题是:在什么意义上Haskell类型的类是开放的?它们是如何扩展的?此外,拥有这个属性(开与闭)的类型理论后果是什么?谢谢!
类型类是开放的,因为您可以将任意类型作为它的实例。当你创建类型类时,你指定的是接口,而不是属于它的类型。然后,在任何包含类型类定义的代码中,您可以使用instance TypeClass type of
语法从接口提供必要的函数,从而创建它的类型实例。
给定一个类型类:
class Monoid m where
mempty :: m
mappend :: m -> m -> m
…它(基本上)在底层实现为一个字典类型:
data Monoid m = Monoid
{ mempty :: m
, mappend :: m -> m -> m
}
实例:
instance Monoid [a] where
mempty = []
mappend = (++)
…翻译成字典:
listIsAMonoid :: Monoid [a]
listIsAMonoid = Monoid
{ mempty = []
, mappend = (++)
}
…当你使用列表作为Monoid
时,编译器会参考上面的字典。
这就引出了你的问题:
在什么意义上Haskell类型类是开放的?它们是如何扩展的?
它们与多态值在相同意义上是开放的。我们有一些多态数据类型:
data Monoid m = ...
…我们可以实例化多态m
类型变量为任何类型,我们可以为mempty
和mappend
字段提供合适的值。
Type类是"open"的,因为它们总是可以在"事后"通过添加更多的实例声明来添加更多的类型。这甚至可以在"客户端"代码中完成,仅使用包含类型类的模块。
关键的一点是,我可以编写带有某种类型类约束的代码来操作值,并且相同的代码无需修改就可以用于在编写类型类时不存在的类型。Haskell中的具体数据类型是"封闭的",因此这种情况不会发生。如果我编写的代码对特定数据类型的成员进行操作(即使它是多态的),那么除非您能够修改类型(然后可能需要修改所有使用它的地方),否则您无法使用该代码对我没有想到的新类型进行操作。