简体   繁体   English

使用通用约束种类

[英]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抱怨ab不在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 ; 但是,如果我正确理解了该问题,则需要为ab具有存在类型; 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM