【问题标题】:Singleton types in HaskellHaskell 中的单例类型
【发布时间】:2013-04-07 16:36:47
【问题描述】:

作为对各种依赖类型形式化技术进行调查的一部分,我看到一篇论文提倡使用单例类型(有一个居民的类型)作为支持依赖类型编程的一种方式。

根据这个来源,在 Haskell 中,由于引入的类型/值同构,在使用单例类型时,运行时值和编译时类型之间存在分离。

我的问题是:在这方面,单例类型与类型类或引用/具体化结构有何不同?

我还特别感谢一些关于使用单例类型的类型理论重要性/优势以及它们可以在多大程度上模拟一般依赖类型的直观解释。

【问题讨论】:

  • 也许应该删除singleton 标签?它似乎以 OOP 为重点,我认为这个问题的答案与该主题无关。
  • 好的,我修好了。谢谢你的提醒。下次我会多注意,标签是否与我想到的意思一致。
  • 单例类型的一个(理论上)用途是为参数化的某些结果(“免费定理”)启用一种简单的证明技术。见cs.cornell.edu/talc/papers/param-abstract.html

标签: haskell dependent-type type-theory singleton-type


【解决方案1】:

正如您所描述的,单例类型是只有一个值的类型(我们暂时忽略)。因此,单例类型的值具有表示该值的唯一类型。依赖类型理论 (DTT) 的关键在于类型可以依赖于值(或者,换句话说,值可以参数化类型)。允许类型依赖于类型的类型理论可以使用单例类型来让类型依赖于单例值。相比之下,类型类提供 ad hoc 多态性,其中值可以依赖于类型(与 DTT 相反,其中类型依赖于值)。

Haskell 中一个有用的技术是定义一类相关的单例类型。经典的例子是自然数:

data S n = Succ n 
data Z = Zero

class Nat n 
instance Nat Z
instance Nat n => Nat (S n)

如果没有向Nat 添加更多实例,Nat 类描述了其值/类型是归纳定义的自然数的单例类型。请注意,ZeroZ 的唯一居民,但例如 S Int 类型有很多居民(它不是单例); Nat 类将 S 的参数限制为单例类型。直观地说,任何具有多个数据构造函数的数据类型都不是单例类型。

给定上面,我们可以写出依赖类型的后继函数:

succ :: Nat n => n -> (S n)
succ n = Succ n 

在类型签名中,类型变量n 可以被视为一个值,因为Nat n 约束将n 限制为表示自然数的单例类型类。 succ 的返回类型取决于这个值,其中S 由值n 参数化。

任何可以归纳定义的值都可以被赋予唯一的单例类型表示。

一种有用的技术是使用 GADT 将非单例类型参数化为单例类型(即使用值)。例如,这可以用于给出归纳定义的数据类型的形状的类型级表示。经典的例子是一个大小列表:

data List n a where
   Nil :: List Z a 
   Cons :: Nat n => a -> List n a -> List (S n) a

这里的自然数单例类型通过其长度参数化列表类型。

考虑到多态 lambda 演算,上面的 succ 有两个参数,n 类型,然后是 n 类型的值参数。因此,这里的单例类型提供了一种Π-type,其中succ :: Πn:Nat . n -> S(n),其中Haskell 中succ 的参数提供了依赖产品参数n:Nat(作为类型参数传递)和参数值。

【讨论】:

  • 很好的答案,但提及较新的DataKinds 内容也可能会有所帮助。此外,具有 MPTC 和 fundeps 类型类的 re: 类型类也用于特定类型 - 取决于 - 类型(与参数类型构造函数相反)。因此,即使只是偶然的情况,那里也存在微弱的联系。
  • 是的,关于DataKinds 和 MPCTs/fundeps 还有很多话要说。我试图保持简短。一定有一个很好的关于所有这些技术的教程吗?
  • GHC 似乎比扩展获取详细教程更快地获取新扩展...无论如何,我提出 DataKinds 是因为它附带了更高级的单例内容,并且因为它旨在替换像你的示例这样的东西Nat 类。 MPTC 和fundeps 是完全不同的蠕虫。
  • 感谢您的精彩回答!现在事情更清楚了:)
猜你喜欢
  • 1970-01-01
  • 2016-08-12
  • 2015-09-07
  • 1970-01-01
  • 1970-01-01
  • 2012-03-14
  • 1970-01-01
  • 2015-09-06
  • 1970-01-01
相关资源
最近更新 更多