我正在为我正在做的一个小实验测试一些代码,但一开始我遇到了一个我不知道如何解决的障碍。
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 类型也必须是一个类型类吗?