约束子集高阶约束

时间:2013-07-06 12:27:30

标签: haskell ghc type-constraints existential-type higher-rank-types

使用GHC.Exts.Constraint类型,我有一个广义的存在量化数据结构,如下所示:

data Some :: (* -> Constraint) -> * where
  Specimen :: c a => a -> Some c

(实际上,我的类型比这更复杂;这只是一个简化的例子)

现在,假设我有一个函数,例如,需要Enum约束,我想对Some c采取行动。我需要做的是检查Enum是否隐含c约束:

succSome :: Enum ⊆ c => Some c -> Some c
succSome (Specimen a) = Specimen $ succ a

在这种情况下,我如何实施运算符?有可能吗?

1 个答案:

答案 0 :(得分:5)

首先请注意Enumc本身不是约束:它们有* -> Constraint种,而不是Constraint种。因此,您要使用Enum ⊆ c表达的内容是:c a隐含所有Enum a的{​​{1}}。

第1步(明确证人)

使用a中的:-,我们可以在值级别编码约束Data.Constraint的见证:

d ⊆ c

我们希望在type Impl c d = forall a . c a :- d a 的定义中使用Impl,如下所示:

succSome

但是这会因类型错误而失败,并说GHC无法从succSome :: Impl c Enum -> Some c -> Some c succSome impl (Specimen a) = (Specimen $ succ a) \\ impl 中推断c a0。看起来GHC选择了非常通用的类型c a,然后无法推断出impl :: forall a0 . c a0 :- d a0。对于从c a0中提取的类型变量impl :: c a :- d a,我们更喜欢更简单的a类型。看起来我们必须帮助输入一点推理。

第2步(显式类型注释)

为了向Specimen提供明确的类型注释,我们必须引入impla类型变量(使用c扩展名)。

ScopedTypeVariables

这样可行,但问题并不完全是问题。

第3步(使用类型类)

问题要求使用类型类对succSome :: forall c . Impl c Enum -> Some c -> Some c succSome impl (Specimen (a :: a)) = (Specimen $ succ a) \\ (impl :: c a :- Enum a) 约束进行编码。我们可以通过使用单个方法来实现这一目标:

d ⊆ c

步骤4(使用示例)

要实际使用此功能,我们必须为class Impl c d where impl :: c a :- d a succSome :: forall c . Impl c Enum => Some c -> Some c succSome (Specimen (a :: a)) = (Specimen $ succ a) \\ (impl :: c a :- Enum a) 提供实例。例如:

Impl