Search code examples
haskelloverloaded-strings

Type error for Query string with postgresql-simple


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?


Solution

  • 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.