I'm testing some code for a little experiment I'm doing but right at the beginning I've hit a roadblock that I don't see how to fix.
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
Ok, so this is some test code, the driver functions would get much more complicated than this but even in this test I get the error "Ambiguous type variable 'a0' in the constraint: (Field a0) arising from a use of `fieldName'. So the compiler does see that fieldName is applied to a field but apparently it wants a more concrete type here. I guess having the functions remain polymorphic makes pgsqlDriver not a concrete class?
But the idea would be that these functions are polymorphic. That's the reason I chose to use a GADT here, so I could put type constraints on the parameters to these driver functions without having to repeat them in every instantiation. The plan would be that the defined database driver could work with any Field and Table instances. Can this simply not be done and my DatabaseDriver type would also have to be a type class?