[英]Using generic constraint kinds
I can quite validly write a type like this in Haskell: 我可以在Haskell中完全有效地编写如下类型:
(t ~ (a, b)) => t
Which in a roundabout way says that t
is some pair. 以回旋方式表示
t
是某对。
But lets say I want to do this: 但是可以说我想这样做:
type family MyConstraint t :: Constraint
data PairConstraintParam
type instance MyConstraint PairConstraintParam = ...
(t ~ MyConstraint PairConstraintParam) => t
What can I place after the type instance MyConstraint PairConstraintParam =
我可以在
type instance MyConstraint PairConstraintParam =
之后放置什么?
I tried (a,b)
but GHC complained a
and b
were not on the RHS. 我尝试了
(a,b)
但是GHC抱怨a
和b
不在RHS上。 It didn't seem to like forall
s either. 它似乎也不喜欢
forall
。
This may seem like a silly example, there's potentially different constraints for different instances of a class, so hence this roundabout scheme. 这似乎是一个愚蠢的示例,对于一个类的不同实例可能存在不同的约束,因此采用了这种环回方案。 As the constraints affect and depend on parameters to a method in a class, I can't just place them in the instance head.
由于约束影响并依赖于类中方法的参数,因此我不能仅将它们放在实例头中。
I think the equality constraint here doesn't really make sense in that form. 我认为这里的平等约束在那种形式下实际上没有任何意义。
~
should have a sort like k -> k -> Constraint
, so t
in that context would need to have kind Constraint
on the left side, while on the right side you need to end with *
... ~
应该具有类似k -> k -> Constraint
,因此在这种情况下, t
在左侧需要具有种类Constraint
,而在右侧则需要以*
...结尾
However, if I have understood the problem correctly, you need to have existential type for a
and b
; 但是,如果我正确理解了该问题,则需要为
a
和b
具有存在类型; so maybe this is what you want: 所以也许这就是您想要的:
data PairConstraintParam
data ExistentialPair :: * where
Exists :: (a, b) -> ExistentialPair
type family MyConstraint (p :: *) (t :: *) :: Constraint where
MyConstraint PairConstraintParam t = t ~ ExistentialPair
test :: (MyConstraint PairConstraintParam t) => t
test = Exists (1, "hi")
Meaning that "there exist a, b
, such that t ~ (a, b)
" (up to isomorphism). 意思是“存在
a, b
,使得t ~ (a, b)
”(直到同构)。 Of course, you would want to add some more constraints to actually do something useful. 当然,您可能想添加更多约束来实际执行一些有用的操作。
Another variant I can think of is the following: 我可以想到的另一个变体如下:
data ConstraintVariant = PairConstraint
class IsPair p where
instance IsPair (a, b)
type family ConstrainedBy (c :: ConstraintVariant) :: * -> Constraint where
ConstrainedBy PairConstraint = IsPair
data Thing c t where
Thing :: (c t) => t -> Thing c t
test2 :: Thing (ConstrainedBy PairConstraint) (Int, String)
test2 = Thing (1, "hi")
Which lets you recover both the constraint and the underlying type. 这样您就可以同时恢复约束和基础类型。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.