[英]Constraint subset higher-order constraint
Using the GHC.Exts.Constraint
kind, I have a generalized existentially quantified data structure like this: 使用GHC.Exts.Constraint
类型,我有一个广义的存在量化数据结构,如下所示:
data Some :: (* -> Constraint) -> * where
Specimen :: c a => a -> Some c
(In reality, my type is more complex than this; this is just a reduced example) (实际上,我的类型比这更复杂;这只是一个简化的例子)
Now, let's say that I have a function which, for example, requires the Enum
constraint, that I want to act on Some c
's. 现在,假设我有一个函数,例如,需要Enum
约束,我想对Some c
。 What I need to do is to check whether the Enum
constraint is implied by c
: 我需要做的是检查c
是否隐含Enum
约束:
succSome :: Enum ⊆ c => Some c -> Some c
succSome (Specimen a) = Specimen $ succ a
How would I implement the ⊆
operator in this case? 在这种情况下,我如何实现⊆
运算符? Is it possible? 可能吗?
First note that Enum
and c
are not constraints by themselves: They have kind * -> Constraint
, not kind Constraint
. 首先请注意, Enum
和c
本身不是约束:它们具有类型* -> Constraint
,而不是类型Constraint
。 So what you want to express with Enum ⊆ c
is: ca
implies Enum a
for all a
. 所以你想用Enum ⊆ c
express Enum ⊆ c
表达的是: ca
意味着Enum a
for a
。
With :-
from Data.Constraint
, we can encode a witness of the constraint d ⊆ c
at the value level: 随着:-
从Data.Constraint
,我们可以编码约束的见证d ⊆ c
在价值层面:
type Impl c d = forall a . c a :- d a
We would like to use Impl
in the definition of succSome
as follows: 我们想在succSome
的定义中使用Impl
,如下所示:
succSome :: Impl c Enum -> Some c -> Some c
succSome impl (Specimen a) = (Specimen $ succ a) \\ impl
But this fails with a type error, saying that GHC cannot deduce c a0
from ca
. 但这种类型错误失败了,说GHC不能从ca
推断c a0
。 Looks like GHC chooses the very general type impl :: forall a0 . c a0 :- d a0
看起来GHC选择了非常通用的类型impl :: forall a0 . c a0 :- d a0
impl :: forall a0 . c a0 :- d a0
and then fails to deduce c a0
. impl :: forall a0 . c a0 :- d a0
然后无法推导出c a0
。 We would prefer the simpler type impl :: ca :- da
for the type variable a
that was extracted from the Specimen
. 对于从Specimen
中提取的类型变量a
,我们更喜欢更简单的类型impl :: ca :- da
。 Looks like we have to help type inference along a bit. 看起来我们必须帮助类型推断。
In order to provide an explicit type annotation to impl
, we have to introduce the a
and c
type variables (using the ScopedTypeVariables
extension). 为了向impl
提供显式类型注释,我们必须引入a
和c
类型变量(使用ScopedTypeVariables
扩展)。
succSome :: forall c . Impl c Enum -> Some c -> Some c
succSome impl (Specimen (a :: a)) = (Specimen $ succ a) \\ (impl :: c a :- Enum a)
This works, but it is not exactly what the questions asks for. 这是有效的,但这并不是问题所要求的。
The questions asks for encoding the d ⊆ c
constraint with a type class. 这些问题要求使用类型类对d ⊆ c
约束进行编码。 We can achieve this by having a class with a single method: 我们可以通过使用单个方法创建一个类:
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)
To actually use this, we have to provide instances for Impl
. 要实际使用它,我们必须为Impl
提供实例。 For example: 例如:
instance Impl Integral Enum where
impl = Sub Dict
value :: Integral a => a
value = 5
specimen :: Some Integral
specimen = Specimen value
test :: Some Integral
test = succSome specimen
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.