タイプレベルでリストを作成しようとしていますが、制約を適用する方法を理解するのに問題があります。
私のベースコードは次のとおりです。
data Foo z q = Foo1 (z q)
| Foo2 (z q)
class Qux q -- where ...
class Baz z -- where ...
class Bar a where -- a has kind *->*
type BCtx a q :: Constraint -- using ConstraintKinds to allow constraints on the concrete type
f :: (BCtx a q) => a q -> a q -> a q
g :: (BCtx a q, BCtx a q') => a q -> a q'
instance (Baz z) => Bar (Foo z) where
type BCtx (Foo z) q = (Num (z q), Qux q) -- for example
f (Foo1 x) (Foo1 y) = Foo1 $ x+y -- these functions need access to the type q to do arithmetic mod q
f (Foo1 x) (Foo2 y) = Foo2 $ x-y
-- ...
q
上記のsは素数冪を表すと考えることができます。また、sの型リストを使用して合成数を表現したいと思いqi
ます。私は次のようなものを想像しています:
data QList qi qs = QCons qi qs
| QNil
データで
data FList c q = FNil
| FCons (c (Head q)) (FList c (Tail q))
に(Head q)
対応する必要があり、に対応する必要がqi
あります。のパラメータは(必然的に)aではなく、のリストであることに注意してください。(これは私が提起している設計上の問題の1つであるため、このリストについてこれ以上具体化したくありません)。私は「モジュラスワイズ」で作業したいと思います:(Tail q)
qs
q
FList
(Qux q)
(Qux qi)
FList
instance (Bar c) => Bar (FList c) where
type BCtx (FList c) q = () -- Anything I put here is not enough
f (FCons x xs) (FCons y ys) = FCons (f x y) (f xs ys)
-- the left call to `f` calls a concrete instance, the right call to `f` is a recursive call on the rest of the list
-- ...
これらのコードスニペットをGHCで一緒にコンパイルすると、(モジュロ転写、抽象化、および入力エラー)が発生します。
Could not deduce (BCtx c (Head q), BCtx c (Tail q))
その後
Could not deduce (BCtx c (Head (Tail q)), BCtx c (Tail (Tail q)))
等
このエラーが発生する理由はわかりますが、修正方法はわかりません。
具体的には、とのタイプを期待していますFList c q
。もちろん、私のリストは、すべてのレベルですべてのBCtx制約を満たします。c~Foo z
q~QCons q1 (QCons q2 QNil)
これらの特定のエラーを修正するとコードがコンパイルされるかどうかはわかりませんが、それは始まりです。Barクラス全体は基本的に固定されています(Constraintの種類が必要であり、Barのインスタンスの種類は*-> *である必要があります)。qi
パラメータにアクセスする必要があるため、実存型を使用してジェネリックオブジェクトのリストを作成できるとは思いません。種類を変更してFList
、バーのコレクションでモジュラス単位で作業QList
できるようにします。
御時間ありがとうございます!