我使用乙烯基来声明许多不同的记录类型,其中一些有一个名为Content
特定类型的字段LanguageContent
。对于依赖于记录中存在的字段的函数,我想要一个类型:
getContent :: HasContent a => a -> LanguageContent
getContent a = a ^. rlens SContent . unAttr
(给出的函数仅用于说明;有许多函数采用某些东西HasContent
并用它做不同的事情。)
现在我只需要声明HasContent
为一个约束。我可以使用的最接近的Data.Vinyl.Notation
是:
getContent :: (Content ∈ fs) => Rec Attr fs -> LanguageContent
可以声明类型族,但函数不进行类型检查:
type family HasContent c :: Constraint
type instance HasContent (Rec Attr rs) = Content ∈ rs
getContent :: HasContent a => a -> LanguageContent
getContent a = a ^. rlens SContent . unAttr
Could not deduce (a ~ Rec Attr rs0)
from the context (HasContent a)
我可以使用两个有效但不理想rs
的参数进行约束(这是我必须在任何地方重复的参数):
type HasContent c rs = (c ~ Rec Attr rs, Content ∈ rs)
如果没有额外的参数(参见@ChristianConkle 的回答),我会得到:
type HasContent c = (c ~ Rec Attr rs, Content ∈ rs)
Not in scope: type variable ‘rs’
如何声明仅适用于这样的Rec Attr fs
约束Content ∈ fs
?