title: Is there any way to extend Data.Vector to accept 2D indices, without having to almost rewrite the whole library?
body: <p>My program needs a Matrix type that works exactly the same as the Vector types on Hackage, except using 2D points instead of Ints for indexing. I've started creating such extension, which shows below:</p>
  
  <pre><code>module Data.Matrix.Mutable where
  
  import Control.Monad.Primitive
  import Control.Monad.ST
  import Linear
  import qualified Data.Vector.Unboxed.Mutable as MUV
  import qualified Data.Vector.Unboxed as UV
  
  data MMatrix s t = MMatrix { dim :: V2 Int, buffer :: MUV.MVector s t }
  
  indexToPos :: Int -&gt; Int -&gt; V2 Int
  indexToPos width index = V2 (quot index width) (mod index width)
  
  posToIndex :: Int -&gt; V2 Int -&gt; Int
  posToIndex width (V2 x y) = y * width + x
  
  width :: MMatrix s t -&gt; Int
  width  (MMatrix (V2 w _) _) = w
  
  height :: MMatrix s t -&gt; Int
  height (MMatrix (V2 _ h) _) = h
  
  new :: (PrimMonad m, MUV.Unbox t) =&gt; V2 Int -&gt; m (MMatrix (PrimState m) t)
  new (dim@(V2 w h)) = return . MMatrix dim =&lt;&lt; MUV.new (w * h)
  
  write :: (PrimMonad m, MUV.Unbox t) =&gt; MMatrix (PrimState m) t -&gt; V2 Int -&gt; t -&gt; m ()
  write matrix pos val = MUV.write (buffer matrix) (posToIndex (width matrix) pos) val
  
  read :: (PrimMonad m, MUV.Unbox t) =&gt; MMatrix (PrimState m) t -&gt; V2 Int -&gt; m t
  read matrix pos = MUV.read (buffer matrix) (posToIndex (width matrix) pos)
  </code></pre>
  
  <p>On the progress, I've noticed I'm forced to manually write a wrapper for every single function for every single vector type. That process is not only tedious, but has high maintenance costs, since any change on their API will need an equally big change on my code. In a dynamic language, the solution is much simpler: overwrite the "read" and "write" functions on a Vector base type. Example (in JavaScript):</p>
  
  <pre><code>Matrix = clone(Vector);
  Matrix.read = function(x,y){
      return Vector.read.call(this, this.width * y + x);
  };
  Matrix.set = function(x,y,val){
      return Vector.write.call(this, this.width * y + x, val);
  };
  </code></pre>
  
  <p>From now on, Matrix works exactly like Vector, except indexed by 2D points, as intended. What is the equivalent strategy on Haskell (using typeclasses, I guess)?</p>