Я тестирую код для небольшого эксперимента, который я провожу, но в самом начале я натолкнулся на препятствие, которое я не знаю, как исправить.
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, чтобы я мог наложить ограничения типа на параметры этих функций драйвера, не повторяя их в каждом экземпляре. Планируется, что определенный драйвер базы данных сможет работать с любыми экземплярами полей и таблиц. Может ли это просто не быть сделано, и мой тип DatabaseDriver также должен быть классом типа?