Related to this question, I have a query template that I've constructed using the interpolate
package, which I'm then trying to pass to the query_
/execute_
functions from postgresql-simple
. But the compiler refuses, with the the error
• Couldn't match type ‘[Char]’ with ‘Query’
Expected type: Query
Actual type: String
The notable passage from the doc pages for postgresql-simple is, "To most easily construct a query, enable GHC's OverloadedStrings
language extension and write your query as a normal literal string." So, it would appear that the following should work:
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE OverloadedStrings #-}
import Control.Monad (void)
import Database.PostgreSQL.Simple
import Data.String.Interpolate (i)
-- schema_name.table_name
type Table = String
dropTableIfExistsQuery :: Table -> String
dropTableIfExistsQuery tbl = [i| DROP TABLE IF EXISTS #{tbl} |]
dropTableIfExists :: Connection -> Table -> IO ()
dropTableIfExists conn tbl = void $ execute_ conn $ dropTableIfExistsQuery tbl
But this won't compile, as above:
• Couldn't match type ‘[Char]’ with ‘Query’
Expected type: Query
Actual type: String
• In the second argument of ‘($)’, namely
‘dropTableIfExistsQuery tbl’
In the second argument of ‘($)’, namely
‘execute_ conn $ dropTableIfExistsQuery tbl’
In the expression:
void $ execute_ conn $ dropTableIfExistsQuery tbl
What gives? Why isn't OverloadedStrings
working here?
OverloadedStrings
only affects string literals, not all terms of type String
. If you have a String
which is not a literal, you may explicitly convert it to any instance of IsString
(e.g. Query
) using:
fromString :: IsString a => String -> a
N.B. I don't know enough about Query
and the other libraries you're using to say whether fromString
has the behavior you need; I claim only that it has the type you need.