Je teste un peu de code pour une petite expérience que je fais mais au début j'ai rencontré un barrage routier que je ne vois pas comment réparer.Type ambigu pour les membres de la fonction polymorphe GADT
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, donc c'est un code de test, les fonctions du pilote obtiendraient beaucoup plus compliqué que cela, mais même dans ce test, je l'erreur « dans la contrainte « a0 » Type Ambigu variable: (Champ a0) Le compilateur voit donc que fieldName est appliqué à un champ mais apparemment il veut un type plus concret Ici, je suppose que le fait que les fonctions restent polymorphes fait que pgsqlDriver n'est pas une classe concrète?
Mais l'idée serait que ces fonctions soient polymorphes, c'est pourquoi j'ai choisi d'utiliser un GADT ici, donc je pourrais mettre des contraintes de type sur les paramètres de ces fonctions pilotes sans avoir à les répéter dans chaque instanciation . Le plan serait que le pilote de base de données défini pourrait fonctionner avec toutes les instances de champ et de table. Cela ne peut-il simplement pas être fait et mon type DatabaseDriver devrait également être une classe de type?
Aucun de ces éléments ne semble fonctionner pour moi. Le pragma No restrictions mono nettoie les erreurs mais il montre toujours une erreur sur la définition et ajoute une signature qui ne nettoie pas. Mais je remarque que vous donnez une signature d'une fonction alors que psqlDriver n'est en fait qu'un enregistrement. Je pense que les enregistrements ne peuvent pas avoir de fonctions polymorphes car cela les rendrait "polymorphes" ce qui n'a pas de sens (je suppose?) Pour un type de données. – Jason
Comme écrit actuellement, 'psqlDriver' n'est pas un enregistrement, mais une fonction. Il nécessite encore un deuxième argument, 'dbSelect'. Les enregistrements peuvent définitivement être polymorphes. Si vous voulez que 'psqlDriver' soit de type' forall a b. DatabaseDriver a b', vous devrez fournir un deuxième argument, éventuellement nommé 'select' (bien que ce nom n'ait pas d'importance, et je ne choisisse ce nom qu'en raison du nom actuel du premier argument' insert'). – ScootyPuff
Je vois maintenant ce qui était prévu et j'ai modifié la réponse. – ScootyPuff