私はvinylを使用して、いくつかの異なるレコード タイプを宣言しています。その中に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)
機能するが理想的ではない2つのパラメーターを使用して制約を作成できます(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
ですか?