diff --git a/matrices.cabal b/matrices.cabal
--- a/matrices.cabal
+++ b/matrices.cabal
@@ -2,7 +2,7 @@
 -- documentation, see http://haskell.org/cabal/users-guide/
 
 name:                matrices
-version:             0.2.0
+version:             0.3.0
 synopsis:            native matrix based on vector
 description:         This library provide the APIs for creating, indexing,
                      modifying matrices (2d arrays). The underling data
@@ -36,7 +36,7 @@
   -- other-modules:       
 
   build-depends:
-      base >=4.0 && <4.8
+      base >=4.0 && <5
     , vector >=0.9
     , primitive
 
diff --git a/src/Data/Matrix/Generic/Base.hs b/src/Data/Matrix/Generic/Base.hs
--- a/src/Data/Matrix/Generic/Base.hs
+++ b/src/Data/Matrix/Generic/Base.hs
@@ -16,8 +16,12 @@
 module Data.Matrix.Generic.Base
     ( rows
     , cols
+    , dim
     , (!)
     , unsafeIndex
+    , empty
+
+    -- * Conversions
     , matrix
     , flatten
     , fromVector
@@ -28,6 +32,10 @@
     , toList
     , toLists
     , fromLists
+
+    -- * Different matrix types
+    , convert
+
     , tr
     , takeRow
     , takeColumn
@@ -35,10 +43,22 @@
     , ident
     , diag
     , diagRect
+    , takeDiag
     , fromBlocks
     , isSymmetric
     , force
+    , Data.Matrix.Generic.Base.foldl
+
+    -- * Mapping
+    , imap
     , Data.Matrix.Generic.Base.map
+
+    -- * Monadic mapping
+    , Data.Matrix.Generic.Base.mapM
+    , Data.Matrix.Generic.Base.mapM_
+    , Data.Matrix.Generic.Base.forM
+    , Data.Matrix.Generic.Base.forM_
+
     ) where
 
 import Control.Arrow ((***), (&&&))
@@ -54,6 +74,11 @@
 cols :: G.Vector v a => Matrix v a -> Int
 cols (Matrix _ n _ _ _) = n
 
+dim :: G.Vector v a => Matrix v a -> (Int, Int)
+dim (Matrix r c _ _ _) = (r,c)
+{-# INLINE dim #-}
+
+-- TODO: better error message
 (!) :: G.Vector v a => Matrix v a -> (Int, Int) -> a
 (!) (Matrix _ _ tda offset vec) (i, j) = vec G.! idx
   where
@@ -66,9 +91,16 @@
     idx = offset + i * tda + j
 {-# INLINE unsafeIndex #-}
 
+
+--reshape :: G.Vector v a => Matrix v a -> (Int, Int) -> Matrix v a
+
+empty :: G.Vector v a => Matrix v a
+empty = Matrix 0 0 0 0 G.empty
+{-# INLINE empty #-}
+
 matrix :: G.Vector v a => Int -> [a] -> Matrix v a
 matrix ncol xs | n `mod` ncol /= 0 = error "incorrect length"
-               | otherwise = fromVector nrow ncol vec
+               | otherwise = fromVector (nrow,ncol) vec
   where
     vec = G.fromList xs
     nrow = n `div` ncol
@@ -83,8 +115,8 @@
     f i = (G.!) vec $ offset + (i `div` n) * tda + i `mod` n
 {-# INLINE flatten #-}
 
-fromVector :: G.Vector v a => Int -> Int -> v a -> Matrix v a
-fromVector r c = Matrix r c c 0
+fromVector :: G.Vector v a => (Int, Int) -> v a -> Matrix v a
+fromVector (r,c) = Matrix r c c 0
 {-# INLINE fromVector #-}
 
 toList :: G.Vector v a => Matrix v a -> [a]
@@ -100,13 +132,13 @@
 {-# INLINE toRows #-}
 
 toColumns :: G.Vector v a => Matrix v a -> [v a]
-toColumns m = Prelude.map (`takeRow` m) [0 .. c-1]
+toColumns m = Prelude.map (takeColumn m) [0 .. c-1]
   where c = cols m
 {-# INLINE toColumns #-}
 
 fromRows :: G.Vector v a => [v a] -> Matrix v a
 fromRows xs | any (\x -> G.length x /= c) xs = error "inequal length"
-            | otherwise = fromVector r c . G.concat $ xs
+            | otherwise = fromVector (r,c) . G.concat $ xs
   where
     r = length xs
     c = G.length . head $ xs
@@ -122,20 +154,25 @@
 
 -- | doesn't check if the list of list is a valid matrix
 fromLists :: G.Vector v a => [[a]] -> Matrix v a
-fromLists xs = fromVector r c . G.fromList . concat $ xs
+fromLists xs = fromVector (r,c) . G.fromList . concat $ xs
   where
     r = length xs
     c = length .head $ xs
 {-# INLINE fromLists #-}
 
-takeRow :: G.Vector v a => Int -> Matrix v a -> v a
-takeRow i (Matrix _ c tda offset vec) = G.slice i' c vec
+-- | convert different matrix type
+convert :: (G.Vector v a, G.Vector w a) => Matrix v a -> Matrix w a
+convert (Matrix r c tda offset vec) = Matrix r c tda offset . G.convert $ vec
+{-# INLINE convert #-}
+
+takeRow :: G.Vector v a => Matrix v a -> Int -> v a
+takeRow (Matrix _ c tda offset vec) i = G.slice i' c vec
   where
     i' = offset + i * tda
 {-# INLINE takeRow #-}
 
-takeColumn :: G.Vector v a => Int -> Matrix v a -> v a
-takeColumn j (Matrix r _ tda offset vec) = G.create $ GM.new r >>= go idx vec r 0
+takeColumn :: G.Vector v a => Matrix v a -> Int -> v a
+takeColumn (Matrix r _ tda offset vec) j = G.create $ GM.new r >>= go idx vec r 0
   where
     go f vec' r' !i v | i >= r' = return v
                       | otherwise = do GM.unsafeWrite v i $ vec' G.! f i
@@ -143,41 +180,45 @@
     idx i = offset + i * tda + j
 {-# INLINE takeColumn #-}
 
-subMatrix :: G.Vector v a => (Int, Int) -> (Int, Int) -> Matrix v a -> Matrix v a
-subMatrix (ri, rj) (ci, cj) (Matrix _ n tda offset vec) =
-    Matrix m' n' tda offset' vec
+-- | O(1) extract sub matrix
+subMatrix :: G.Vector v a
+          => (Int, Int)  -- ^ upper left corner of the submatrix
+          -> (Int, Int)  -- ^ bottom right corner of the submatrix
+          -> Matrix v a -> Matrix v a
+subMatrix (i,j) (i',j') (Matrix _ n tda offset vec)
+    | m' <= 0 || n' <= 0 = empty
+    | otherwise = Matrix m' n' tda offset' vec
   where
-    m' = rj - ri + 1
-    n' = cj - ci + 1
-    offset' = offset + ri * n + ci
+    m' = i' - i + 1
+    n' = j' - j + 1
+    offset' = offset + i * n + j
 {-# INLINE subMatrix #-}
 
 tr :: G.Vector v a => Matrix v a -> Matrix v a
-tr (Matrix r c tda offset vec) = fromVector c r $ G.generate (r*c) f
+tr (Matrix r c tda offset vec) = fromVector (c,r) $ G.generate (r*c) f
   where
     f i = vec G.! (offset + i `mod` r * tda + i `div` r)
 {-# INLINE tr #-}
 
 ident :: (Num a, G.Vector v a) => Int -> Matrix v a
-ident n = diagRect 0 n n $ replicate n 1
+ident n = diagRect 0 (n,n) $ replicate n 1
 {-# INLINE ident #-}
 
 -- | create a square matrix with given diagonal, other entries default to 0
 diag :: (Num a, G.Vector v a, F.Foldable t)
      => t a  -- ^ diagonal
      -> Matrix v a
-diag d = diagRect 0 n n d
+diag d = diagRect 0 (n,n) d
   where n = length . F.toList $ d
 {-# INLINE diag #-}
 
 -- | create a rectangular matrix with default values and given diagonal
 diagRect :: (G.Vector v a, F.Foldable t)
          => a         -- ^ default value
-         -> Int       -- ^ number of rows
-         -> Int       -- ^ number of columns
+         -> (Int, Int)
          -> t a       -- ^ diagonal
          -> Matrix v a
-diagRect z0 r c d = fromVector r c $ G.create $ GM.replicate n z0 >>= go d c
+diagRect z0 (r,c) d = fromVector (r,c) $ G.create $ GM.replicate n z0 >>= go d c
   where
     go xs c' v = F.foldlM f 0 xs >> return v
       where
@@ -185,11 +226,18 @@
     n = r * c
 {-# INLINE diagRect #-}
 
+-- | extracts the diagonal from a rectangular matrix
+takeDiag :: G.Vector v a => Matrix v a -> v a
+takeDiag mat@(Matrix r c _ _ _) = G.generate n $ \i -> unsafeIndex mat (i,i)
+  where
+    n = min r c
+{-# INLINE takeDiag #-}
+
 fromBlocks :: G.Vector v a
            => a               -- ^ default value
            -> [[Matrix v a]]
            -> Matrix v a
-fromBlocks d ms = fromVector m n $ G.create $ GM.replicate (m*n) d >>= go n ms
+fromBlocks d ms = fromVector (m,n) $ G.create $ GM.replicate (m*n) d >>= go n ms
   where
     go n' xss v = foldM_ f 0 xss >> return v
       where
@@ -200,12 +248,14 @@
                 let c = cols x
                     r = rows x
                     vec = flatten x
-                    step i u = do GM.unsafeWrite v ((cr + i `div` c) * n' + i `mod` c + cc) u
-                                  return (i+1)
+                    step i u = do
+                        GM.unsafeWrite v ((cr + i `div` c) * n' + i `mod` c + cc) u
+                        return (i+1)
                 G.foldM'_ step (0::Int) vec
                 return (max maxR r, cc + c)
     -- figure out the dimension of the new matrix
-    (m, n) = (sum *** maximum) . unzip . Prelude.map ((maximum *** sum) . unzip . Prelude.map (rows &&& cols)) $ ms
+    (m, n) = (sum *** maximum) . unzip . Prelude.map ((maximum *** sum) .
+                unzip . Prelude.map (rows &&& cols)) $ ms
 {-# INLINE fromBlocks #-}
 
 isSymmetric :: (Eq a, G.Vector v a) => Matrix v a -> Bool
@@ -217,9 +267,35 @@
 {-# INLINE isSymmetric #-}
 
 force :: G.Vector v a => Matrix v a -> Matrix v a
-force m@(Matrix r c _ _ _) = fromVector r c . G.force . flatten $ m
+force m@(Matrix r c _ _ _) = fromVector (r,c) . G.force . flatten $ m
 {-# INLINE force #-}
 
+imap :: (G.Vector v a, G.Vector v b) => ((Int, Int) -> a -> b) -> Matrix v a -> Matrix v b
+imap f m@(Matrix r c _ _ _) = fromVector (r,c) $ G.imap f' . flatten $ m
+  where
+    f' i = f (i `div` c, i `mod` c)
+{-# INLINE imap #-}
+
 map :: (G.Vector v a, G.Vector v b) => (a -> b) -> Matrix v a -> Matrix v b
-map f m@(Matrix r c _ _ _) = fromVector r c $ G.map f . flatten $ m
+map f m@(Matrix r c _ _ _) = fromVector (r,c) $ G.map f . flatten $ m
 {-# INLINE map #-}
+
+foldl :: G.Vector v b => (a -> b -> a) -> a -> Matrix v b -> a
+foldl f acc m = G.foldl f acc . flatten $ m
+{-# INLINE foldl #-}
+
+mapM :: (G.Vector v a, G.Vector v b, Monad m) => (a -> m b) -> Matrix v a -> m (Matrix v b)
+mapM f m@(Matrix r c _ _ _) = liftM (fromVector (r,c)) . G.mapM f . flatten $ m
+{-# INLINE mapM #-}
+
+mapM_ :: (G.Vector v a, Monad m) => (a -> m b) -> Matrix v a -> m ()
+mapM_ f = G.mapM_ f . flatten
+{-# INLINE mapM_ #-}
+
+forM :: (G.Vector v a, G.Vector v b, Monad m) => Matrix v a -> (a -> m b) -> m (Matrix v b)
+forM = flip Data.Matrix.Generic.Base.mapM
+{-# INLINE forM #-}
+
+forM_ :: (G.Vector v a, Monad m) => Matrix v a -> (a -> m b) -> m ()
+forM_ = flip Data.Matrix.Generic.Base.mapM_
+{-# INLINE forM_ #-}
diff --git a/src/Data/Matrix/Generic/Mutable.hs b/src/Data/Matrix/Generic/Mutable.hs
--- a/src/Data/Matrix/Generic/Mutable.hs
+++ b/src/Data/Matrix/Generic/Mutable.hs
@@ -1,4 +1,5 @@
 {-# LANGUAGE GADTs #-}
+{-# LANGUAGE Rank2Types #-}
 module Data.Matrix.Generic.Mutable
    ( fromMVector
    , thaw
@@ -11,10 +12,12 @@
    , unsafeRead
    , replicate
    , new
+   , create
    ) where
 
 import Prelude hiding (read, replicate)
 import Control.Monad
+import Control.Monad.ST
 import Data.Matrix.Generic.Types
 import qualified Data.Vector.Generic as G
 import qualified Data.Vector.Generic.Mutable as GM
@@ -24,8 +27,8 @@
 (<$>) :: Monad m => (a -> b) -> m a -> m b
 (<$>) = liftM
 
-fromMVector :: GM.MVector v a => Int -> Int -> v m a -> MMatrix v m a
-fromMVector r c = MMatrix r c c 0
+fromMVector :: GM.MVector v a => (Int, Int) -> v m a -> MMatrix v m a
+fromMVector (r,c) = MMatrix r c c 0
 {-# INLINE fromMVector #-}
 
 thaw :: PrimMonad m => Matrix v a -> m (MMatrix (G.Mutable v) (PrimState m) a)
@@ -69,11 +72,15 @@
 {-# INLINE unsafeRead #-}
 
 replicate :: (PrimMonad m, GM.MVector v a)
-          => Int -> Int -> a -> m (MMatrix v (PrimState m) a)
-replicate r c x = fromMVector r c <$> GM.replicate (r*c) x
+          => (Int, Int) -> a -> m (MMatrix v (PrimState m) a)
+replicate (r,c) x = fromMVector (r,c) <$> GM.replicate (r*c) x
 {-# INLINE replicate #-}
 
 new :: (PrimMonad m, GM.MVector v a)
-    => Int -> Int -> m (MMatrix v (PrimState m) a)
-new r c = fromMVector r c <$> GM.new (r*c)
+    => (Int, Int) -> m (MMatrix v (PrimState m) a)
+new (r,c) = fromMVector (r,c) <$> GM.new (r*c)
 {-# INLINE new #-}
+
+create :: G.Vector v a => (forall s . ST s (MMatrix (G.Mutable v) s a)) -> Matrix v a
+create m = runST $ unsafeFreeze =<< m
+{-# INLINE create #-}
