diff --git a/casadi-bindings.cabal b/casadi-bindings.cabal
--- a/casadi-bindings.cabal
+++ b/casadi-bindings.cabal
@@ -1,5 +1,5 @@
 name:                casadi-bindings
-version:             2.4.1.1
+version:             2.4.1.2
 synopsis:            mid-level bindings to CasADi
 category:            Numerical, Math
 description:
@@ -53,6 +53,7 @@
                        Casadi.Sparsity
                        Casadi.SX
                        Casadi.SXFunction
+                       Casadi.Viewable
   other-modules:       Casadi.SharedObject
   build-depends:       base >=4.6 && <5,
                        linear,
diff --git a/src/Casadi/CMatrix.hs b/src/Casadi/CMatrix.hs
--- a/src/Casadi/CMatrix.hs
+++ b/src/Casadi/CMatrix.hs
@@ -14,8 +14,10 @@
 import Casadi.Overloading ( Fmod, ArcTan2, SymOrd, Erf )
 import Casadi.Sparsity ( Sparsity )
 import Casadi.Slice ( Slice, slice )
+import Casadi.Viewable ( Viewable )
 
-class (Eq a, Show a, Floating a, Fmod a, ArcTan2 a, SymOrd a, Erf a) => CMatrix a where
+class (Eq a, Show a, Floating a, Fmod a, ArcTan2 a, SymOrd a, Erf a, Viewable a)
+      => CMatrix a where
   vertsplit :: a -> V.Vector Int -> V.Vector a
   vertcat :: V.Vector a -> a
   horzsplit :: a -> V.Vector Int -> V.Vector a
diff --git a/src/Casadi/DMatrix.hs b/src/Casadi/DMatrix.hs
--- a/src/Casadi/DMatrix.hs
+++ b/src/Casadi/DMatrix.hs
@@ -19,6 +19,7 @@
 
 import Casadi.Overloading ( Fmod(..), ArcTan2(..), SymOrd(..), Erf(..) )
 import Casadi.CMatrix ( CMatrix(..) )
+import Casadi.Viewable ( Viewable(..) )
 
 getWith :: Monad m => m Sparsity -> m (V.Vector Double) -> m DMatrix
 getWith get getVector = do
@@ -40,6 +41,13 @@
 
 instance Conjugate DMatrix where
   conjugate = id
+
+instance Viewable DMatrix where
+  vveccat = veccat
+  vvertsplit = vertsplit
+  vsize1 = size1
+  vsize2 = size2
+  vrecoverDimension _ dim = zeros dim
 
 fromSparseData :: Sparsity -> V.Vector Double -> DMatrix
 fromSparseData s d = unsafePerformIO (dmatrix__4 s (fromDVector d))
diff --git a/src/Casadi/MX.hs b/src/Casadi/MX.hs
--- a/src/Casadi/MX.hs
+++ b/src/Casadi/MX.hs
@@ -16,6 +16,7 @@
 import Casadi.Overloading ( Fmod(..), ArcTan2(..), SymOrd(..), Erf(..) )
 import Casadi.CMatrix ( CMatrix(..) )
 import Casadi.DMatrix ()
+import Casadi.Viewable ( Viewable(..) )
 import Casadi.SharedObject ( castSharedObject )
 
 instance Conjugate MX where
@@ -28,6 +29,13 @@
 instance Show MX where
   show x = show (castSharedObject x)
   {-# NOINLINE show #-}
+
+instance Viewable MX where
+  vveccat = veccat
+  vvertsplit = vertsplit
+  vsize1 = size1
+  vsize2 = size2
+  vrecoverDimension _ dim = zeros dim
 
 sym :: String -> IO MX
 sym x = fmap castMX (mx_sym__6 x)
diff --git a/src/Casadi/SX.hs b/src/Casadi/SX.hs
--- a/src/Casadi/SX.hs
+++ b/src/Casadi/SX.hs
@@ -15,6 +15,7 @@
 import Casadi.Overloading ( Fmod(..), ArcTan2(..), SymOrd(..), Erf(..) )
 import Casadi.CMatrix ( CMatrix(..) )
 import Casadi.DMatrix ()
+import Casadi.Viewable ( Viewable(..) )
 
 instance Show SX where
   show x = unsafePerformIO (sx_getDescription x)
@@ -26,6 +27,13 @@
 
 instance Conjugate SX where
   conjugate = id
+
+instance Viewable SX where
+  vveccat = veccat
+  vvertsplit = vertsplit
+  vsize1 = size1
+  vsize2 = size2
+  vrecoverDimension _ dim = zeros dim
 
 ssym :: String -> IO SX
 ssym = sx_sym__6
diff --git a/src/Casadi/Viewable.hs b/src/Casadi/Viewable.hs
new file mode 100644
--- /dev/null
+++ b/src/Casadi/Viewable.hs
@@ -0,0 +1,33 @@
+{-# OPTIONS_GHC -Wall #-}
+
+module Casadi.Viewable
+       ( Viewable(..)
+       ) where
+
+import qualified Data.Vector as V
+
+class Viewable a where
+  vvertsplit :: a -> V.Vector Int -> V.Vector a
+  vveccat :: V.Vector a -> a
+  vsize1 :: a -> Int
+  vsize2 :: a -> Int
+  vrecoverDimension :: a -> (Int, Int) -> a
+
+instance Viewable (V.Vector a) where
+  vsize1 = V.length
+  vsize2 = const 1
+  vveccat = V.concat . V.toList
+  vvertsplit x ks = V.fromList (split x (V.toList ks))
+  -- todo(greg): this doesn't look right
+  vrecoverDimension x _ = x
+
+split :: V.Vector a -> [Int] -> [V.Vector a]
+split v xs@(0:_) = split' v xs
+split _ _ = error "split: first index must be 0"
+
+split' :: V.Vector a -> [Int] -> [V.Vector a]
+split' _ [] = error "can't split with no input"
+split' x [kf]
+  | V.length x == kf = []
+  | otherwise = error "split: last index must be length of vector"
+split' x (k0:k1:ks) = V.slice k0 (k1 - k0) x : split' x (k1:ks)
