私が行っている小さな実験のためにいくつかのコードをテストしていますが、最初は修正方法がわからない障害にぶつかりました。
data DatabaseDriver a b where
DatabaseDriver :: (Table table, Field field) => {
dbInsert :: table -> [field] -> String
, dbSelect :: table -> [field] -> String
} -> DatabaseDriver a b
class Table a where
tableName :: a -> String
class Field a where
fieldName :: a -> String
fieldValue :: a -> String
psqlDriver = DatabaseDriver insert select
where
insert t fs = "insert into " ++ tableName t ++ " (" ++ fieldNames fs ++ ") values (" ++ fieldValues fs ++ ")"
select t fs = "select " ++ fieldNames fs ++ " from " ++ tableName t
fieldNames = joinComma fieldName
fieldValues = joinComma fieldValue
joinComma f = foldl (\a n -> a ++ ", " ++ n) "" . map f
わかりました、これはいくつかのテスト コードです。ドライバー関数はこれよりもはるかに複雑になりますが、このテストでも、「制約内の型変数 'a0' があいまいです: (フィールド a0) は、'fieldName の使用に起因します」というエラーが発生します。 '.したがって、コンパイラは fieldName がフィールドに適用されていることを確認しますが、ここではより具体的な型が必要なようです.関数を多態性のままにしておくと、pgsqlDriver が具体的なクラスではなくなると思いますか?
しかし、これらの関数はポリモーフィックであるという考えになります。これが、ここで GADT を使用することを選択した理由です。そのため、これらのドライバー関数のパラメーターに型の制約を課すことができ、インスタンス化のたびにパラメーターを繰り返す必要がありません。計画では、定義されたデータベース ドライバーが任意の Field および Table インスタンスで機能する可能性があります。これは単純に実行できず、私の DatabaseDriver 型も型クラスにする必要がありますか?