title: force ambiguous instance with phantom type
body: <p>I'm using <code>mysql-simple</code> and I'm trying to use phantom type to avoid to have to use explicit type signature.</p>
  
  <p>Let's say I'm trying to execute the following query <code>SELECT firstname, lastname FROM users</code>.</p>
  
  <p>I would try something like this : </p>
  
  <pre><code>{-# LANGUAGE OverloadedStrings #-}
  import Database.MySQL.Simple
  
  myQuery :: Query
  myQuery = "SELECT firstname, lastname FROM users"
  
  main = do
      conn &lt;-connect defaultConnectInfo
      rows &lt;- queryT conn myQuery
      mapM_ print rows
  </code></pre>
  
  <p>This doesn't work because the compiler can't deduce the type of <code>rows</code>. The solution is to add a type signature like this :</p>
  
  <pre><code>{-# LANGUAGE OverloadedStrings #-}
  import Database.MySQL.Simple
  
  myQuery :: Query
  myQuery = "SELECT firstname, lastname FROM users"
  
  main = do
      conn &lt;-connect defaultConnectInfo
      rows &lt;- queryT conn myQuery
      mapM_ print (rows :: [(String, String)]) ------&lt;&lt; Here
  </code></pre>
  
  <p>The compiler deduces that each row is <code>(String, String)</code> and everythign works fine.
  This solution is however not satisfying because if I modify <code>myQuery</code> I need to modify the <code>rows</code> type signature. Moreover, this is a simpified example. In the real code , the query comes from a query combinator (which hold the row type), so there is no way to hardcode the row type.</p>
  
  <p>I tried using a <strong>typed</strong> query using a phantom type </p>
  
  <pre><code>{-# LANGUAGE OverloadedStrings #-}
  import Database.MySQL.Simple
  
  
  data QueryT a = QueryT Query  ---------------&lt;&lt; Phantom type
  queryT :: Connection -&gt; QueryT a -&gt; IO [a]
  queryT conn (QueryT q) = query_ conn q
  
  
  myQuery :: QueryT (String, String) ----------&lt;&lt; Query holding it's row type
  myQuery = QueryT $ "SELECT firstname, lastname FROM users"
  
  main = do
      conn &lt;-connect defaultConnectInfo
      rows &lt;- queryT conn myQuery
      mapM_ print rows
  </code></pre>
  
  <p>This doesn't work. I got the following message :</p>
  
  <pre><code>stack.hs:7:26:
  No instance for (Database.MySQL.Simple.QueryResults.QueryResults a)
    arising from a use of `query_'
  Possible fix:
    add (Database.MySQL.Simple.QueryResults.QueryResults
           a) to the context of
      the type signature for queryT :: Connection -&gt; QueryT a -&gt; IO [a]
  In the expression: query_ conn q
  In an equation for `queryT': queryT conn (QueryT q) = query_ conn q
  </code></pre>
  
  <p>If I replace the phantom type by <code>(String, String)</code> in <code>queryT</code> type signature </p>
  
  <pre><code>queryT :: Connection -&gt; QueryT a -&gt; IO [(String, String)]
  </code></pre>
  
  <p>Things work again. So what is the difference ?
  Why the type inference can't infere that rows is of type <code>[(String, String)]</code> ?</p>
  
  <p>(I've tried functional dependencies and type families but that doesn't seem to help either).</p>