diff --git a/src/Data/Params.hs b/src/Data/Params.hs
--- a/src/Data/Params.hs
+++ b/src/Data/Params.hs
@@ -94,8 +94,10 @@
 
     , module Data.Reflection
     , module Data.Proxy
+--     , Sub 
+--     , Dict 
     , module Data.Constraint
-    , module Data.Constraint.Unsafe
+--     , module Data.Constraint.Unsafe
     )
     where
 
diff --git a/src/Data/Params/Monad.hs b/src/Data/Params/Monad.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Params/Monad.hs
@@ -0,0 +1,137 @@
+module Data.Params.Monad
+    where
+
+import Control.Category
+import Prelude hiding ( (.), id, Functor(..), Applicative(..), Monad(..) )
+import qualified Prelude as P
+import GHC.Exts
+
+import Data.Params hiding ( (\\) )
+import Data.Params.Applicative
+import Data.Params.Functor
+
+-------------------------------------------------------------------------------
+-- Monad class
+
+class Applicative lens tfb => Monad lens tfb where
+    join :: tffb ~ CoJoin lens tfb
+         => TypeLens Base lens -> tffb -> tfb
+
+type family CoJoin (lens :: * -> Constraint) t
+type instance CoJoin lens t 
+  = SetParam' 
+      lens 
+      ( SetParam' 
+          ( Objective lens ) 
+          ( GetParam lens t ) 
+          ( GetParam (RemoveObjective lens) t )
+      ) 
+      t
+
+-------------------------------------------------------------------------------
+-- functions
+
+return :: Monad lens t
+  => GetParam lens t 
+  -> TypeLens Base lens
+  -> t
+return = pure 
+
+infixl 1 \\=
+(m \\= f) lens = join lens $ fmap lens f m
+
+infixl 1  \\=-
+infixl 1 -\\=-
+infixl 1 -\\=
+(m  \\=- f) lens = ( m      \\= \a -> f a $ objective lens ) lens
+(m -\\=- f) lens = ( m lens \\= \a -> f a $ objective lens ) lens
+(m -\\=  f) lens = ( m lens \\= \a -> f a                  ) lens
+
+atM lens m = at (removeObjective lens) $ do
+    return $ at (objective lens) $ m
+
+-------------------
+
+
+-- > (\\) :: forall a b ma mb lens.
+-- >   ( b ~ GetParam lens mb 
+-- >   , ma ~ SetParam lens a mb
+-- >   , ma ~ SetParam lens (GetParam lens ma) mb
+-- >   , a ~ GetParam lens ma
+-- >   ) => ma -> mb -> TypeLens Base lens -> mb
+
+(m \\ f) lens = (m \\= \ (_::String) -> f) lens
+
+-- FIXME: The compiler can't figure out the type of (\\) without the String annotation;  GHC bug?
+
+infixl 1 \\
+
+infixl 1  \\-
+infixl 1 -\\-
+infixl 1 -\\
+( m  \\- f ) lens = (      m \\ f (objective lens) ) lens
+( m -\\- f ) lens = ( m lens \\ f (objective lens) ) lens
+( m -\\  f ) lens = ( m lens \\ f                  ) lens
+
+-------------------
+-- do notation
+
+infixl 1 >>=
+(m >>= f) lens = (m -\\=- f) lens
+
+infixl 1 >>
+m >> f = m -\\- f
+
+fail = error 
+
+ifThenElse False _ f = f
+ifThenElse True t _ = t
+
+
+-------------------------------------------------------------------------------
+-- instances
+
+instance Monad (Param_a Base) (Either a b) where
+    join lens (Left (Left a)) = Left a
+    join lens (Left (Right b)) = Right b
+    join lens (Right b) = Right b
+
+instance Monad (Param_b Base) (Either a b) where
+    join lens (Right (Right b)) = Right b
+    join lens (Right (Left a)) = Left a
+    join lens (Left a) = Left a
+
+instance 
+    ( Monad p a
+    , Either (CoJoin p a) b ~ CoJoin (Param_a p) (Either a b) -- follows from the lens laws
+    ) => Monad (Param_a p) (Either a b) 
+        where
+
+    join lens (Left a) = Left $ join (zoom lens) a
+    join lens (Right b) = Right b
+
+instance 
+    ( Monad p b
+    , Either a (CoJoin p b) ~ CoJoin (Param_b p) (Either a b) -- follows from the lens laws
+    ) => Monad (Param_b p) (Either a b) 
+        where
+
+    join lens (Left a) = Left a
+    join lens (Right b) = Right $ join (zoom lens) b
+
+---------------------------------------
+
+instance Monad (Param_a Base) (Maybe a) where
+    join lens Nothing = Nothing 
+    join lens (Just Nothing) = Nothing
+    join lens (Just (Just a)) = Just a
+
+instance 
+    ( Monad p a
+    , Maybe (CoJoin p a) ~ CoJoin (Param_a p) (Maybe a) -- follows from the lens laws
+    ) => Monad (Param_a p) (Maybe a) 
+      where
+
+    join lens Nothing = Nothing
+    join lens (Just a) = Just $ join (zoom lens) a
+
diff --git a/typeparams.cabal b/typeparams.cabal
--- a/typeparams.cabal
+++ b/typeparams.cabal
@@ -1,5 +1,5 @@
 Name:                typeparams
-Version:             0.0.4
+Version:             0.0.5
 Synopsis:            Lens-like interface for type level parameters; allows unboxed unboxed vectors and supercompilation
 Description:         
     This library provides a lens-like interface for working with type parameters. In the code:
@@ -48,6 +48,7 @@
         Data.Params.Frac
         Data.Params.PseudoPrim
         Data.Params.Functor
+        Data.Params.Monad
         Data.Params.Vector
         -- Data.Params.Vector.Storable
         -- Data.Params.Vector.StorableRaw
