title: Polymorphic return types and "rigid type variable" error in Haskell
body: <p>There's a simple record <code>Column v a</code> which holds a <code>Vector</code> from the <code>Data.Vector</code> family (so that <code>v</code> can be <code>Vector.Unboxed</code>, just <code>Vector</code> etc), it's name and type (simple enum-like ADT <code>SupportedTypes</code>). I would like to be able to serialize it using the <code>binary</code> package. To do that, I try to define a <code>Binary</code> instance below.</p>
  
  <p>Now <code>put</code> works fine, however when I try to define deserialization in the <code>get</code> function and want to set a specific type to the <code>rawVector</code> that is being returned based on the <code>colType</code> (<code>U.Vector Int64</code> when it's <code>PInt</code>, <code>U.Vector Double</code> when it's <code>PDouble</code> etc) - I get this error message:</p>
  
  <blockquote>
    <p>Couldn't match type <code>v</code> with <code>U.Vector</code></p>
    
    <p><code>v</code> is a rigid type variable bound by the instance declaration at <code>src/Quark/Base/Column.hs</code>:75:10</p>
    
    <p>Expected type: <code>v a</code></p>
    
    <p>Actual type: <code>U.Vector Int64</code></p>
  </blockquote>
  
  <p>error. </p>
  
  <p>Is there a better way to achieve my goal - deserialize <code>Vector</code>s of different types based on the <code>colType</code> value or am I stuck with defining <code>Binary</code> instance for all possible <code>Vector</code> / primitive type combinations? Shouldn't be the case...</p>
  
  <p>Somewhat new to Haskell and appreciate any help! Thanks!</p>
  
  <pre><code>{-# LANGUAGE OverloadedStrings, TransformListComp, RankNTypes, 
              TypeSynonymInstances, FlexibleInstances, OverloadedLists, DeriveGeneric  #-}
  
  {-# LANGUAGE MultiParamTypeClasses, FlexibleContexts,
           TypeFamilies, ScopedTypeVariables, InstanceSigs #-}
  
  import qualified Data.Vector.Generic as G
  import qualified Data.Vector.Unboxed as U
  
  data Column v a = Column {rawVector :: G.Vector v a =&gt; v a, colName :: Text, colType :: SupportedTypes }
  
  instance (G.Vector v a, Binary (v a)) =&gt; Binary (Column v a) where
  
    put Column {rawVector = vec, colName = cn, colType = ct} = do put (fromEnum ct) &gt;&gt; put cn &gt;&gt; put vec
  
  
    get = do t &lt;- get :: Get Int
           nm &lt;- get :: Get Text
           let pt = toEnum t :: SupportedTypes
           case pt of 
              PInt -&gt; do vec &lt;- get :: Get (U.Vector Int64)
                         return Column {rawVector = vec, colName = nm, colType = pt}
              PDouble -&gt; do vec &lt;- get :: Get (U.Vector Double)
                            return Column {rawVector = vec, colName = nm, colType = pt}
  </code></pre>
  
  <p><strong>UPDATED</strong> Thank you for all the answers below, some pretty good ideas! It's quite clear that what I want to do is impossible to achieve head-on - so that is my answer. But the other suggested solutions are a good reading in itself, thanks a bunch!</p>