There are three options here. The first option is to add
{-# LANGUAGE NoMonomorphismRestriction #-}
to the top of your module file.
The second option is to add an explicit type signature to psqlDriver.
psqlDriver :: (Field field, Table table) => (table -> [field] -> String) -> DatabaseDriver a b
The reason for all of this is a little nuanced, and more details can be found here
The third option is to change the definition of psqlDriver
to
psqlDriver = DatabaseDriver insert select
However, this is truly ambiguous - there is not reason to prefer any particular instance of Table
or Field
over another. Perhaps you mean to define DatabaseDriver
as follows.
data DatabaseDriver table field where
DatabaseDriver :: (Table table, Field field) => {
dbInsert :: table -> [field] -> String
, dbSelect :: table -> [field] -> String
} -> DatabaseDriver table field
If the original definition of DatabaseDriver
is rewritten as an ADT, it is more obvious why.
As it is currently written in the question, the translation to an ADT is
{-# LANGUAGE ExistentialQuantification #-}
data DatabaseDriver a b
= forall table field .
(Table table, Field field) => DatabaseDriver
{ dbInsert :: table -> [field] -> String
, dbSelect :: table -> [field] -> String
}
Notice the nested forall table field
, and how table
and field
have no relationship to a
or b
.
The intended translation is either
data DatabaseDriver table field
= (Table table, Field field) => DatabaseDriver
{ dbInsert :: table -> [field] -> String
, dbSelect :: table -> [field] -> String
}
or most likely
data DatabaseDriver table field
= DatabaseDriver
{ dbInsert :: table -> [field] -> String
, dbSelect :: table -> [field] -> String
}
Having the type class constraints in the definition of DatabaseDriver
does not let you remove the type class constraints from any use of DatabaseDriver
, in particular psqlDriver
. In both of the ADT translations above, the type of psqlDriver
is
psqlDriver :: (Table table, Field field) => DatabaseDriver table field