diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -30,12 +30,61 @@
 	$ cabal install express
 
 
+Basics
+------
+
+For types that are [`Show`] instances,
+we can use [`val`] to encode values as [`Expr`]s.
+
+	> let false = val False
+	> :t false
+	false :: Expr
+	> print false
+	False :: Bool
+
+	> let one = val (1 :: Int)
+	> :t one
+	one :: Expr
+	> print one
+	1 :: Int
+
+As seen above, the [`Show`] instance for [`Expr`] produces a string with the
+encoded value and it's type.
+
+For types that aren't [`Show`] instances, like functions,
+we can use [`value`] to encode values as [`Expr`]s.
+
+	> let notE = value "not" not
+	> :t notE
+	notE :: Expr
+	> print notE
+	not :: Bool -> Bool
+
+Using [`:$`] we can apply function valued [`Expr`]s, to other Exprs.
+
+	> let notFalse = notE :$ false
+	> :t notFalse
+	notFalse :: Expr
+	> notFalse
+	not False :: Bool
+
+Using [`evaluate`] and [`eval`] we can evaluate [`Expr`]s back into a regular Haskell value.
+
+	> evaluate notFalse :: Maybe Bool
+	Just True
+	> evaluate notFalse :: Maybe Int
+	Nothing
+	> eval False notFalse
+	True
+	> eval (0::Int) notFalse
+	0
+
+
 Example 1: heterogeneous lists
 ------------------------------
 
 Like with [`Data.Dynamic`], we can use Express to create heterogeneous lists.
 
-For types that are [`Show`] instances, we can use [`val`] to encode values as [`Expr`]s.
 Here, we use applications of [`val`] to create a heterogeneous list:
 
 	> let xs = [val False, val True, val (1::Int), val (2::Int), val (3::Integer), val "123"]
@@ -292,6 +341,7 @@
 [`Expr`]:         https://hackage.haskell.org/package/express/docs/Data-Express.html#t:val
 [`val`]:          https://hackage.haskell.org/package/express/docs/Data-Express.html#v:val
 [`evaluate`]:     https://hackage.haskell.org/package/express/docs/Data-Express.html#v:evaluate
+[`:$`]:           https://hackage.haskell.org/package/express-0.1.1/docs/Data-Express.html#v::-36-
 [`$$`]:           https://hackage.haskell.org/package/express/docs/Data-Express.html#v:-36--36-
 [`Show`]:         https://hackage.haskell.org/package/base/docs/Prelude.html#t:Show
 [`Data.Dynamic`]: https://hackage.haskell.org/package/base/docs/Data-Dynamic.html
diff --git a/express.cabal b/express.cabal
--- a/express.cabal
+++ b/express.cabal
@@ -1,6 +1,6 @@
 -- Cabal file for express
 name: express
-version: 0.1.1
+version: 0.1.2
 synopsis: Dynamically-typed expressions involving applications and variables.
 description:
   Express is a library for manipulating dynamically typed Haskell expressions.
@@ -57,7 +57,7 @@
 source-repository this
   type:           git
   location:       https://github.com/rudymatela/express
-  tag:            v0.1.1
+  tag:            v0.1.2
 
 library
   exposed-modules:     Data.Express
diff --git a/src/Data/Express.hs b/src/Data/Express.hs
--- a/src/Data/Express.hs
+++ b/src/Data/Express.hs
@@ -12,6 +12,48 @@
 -- building, evaluating, comparing, folding, canonicalizing and matching
 -- 'Expr's.
 --
+-- /Basics./
+-- For types that are 'Show' instances,
+-- we can use 'val' to encode values as 'Expr's:
+--
+-- > > let false = val False
+-- > > :t false
+-- > false :: Expr
+-- > > print false
+-- > False :: Bool
+--
+-- As seen above, the 'Show' instance for 'Expr' produces a string with the
+-- encoded value and it's type.
+--
+-- For types that aren't 'Show' instances, like functions,
+-- we can use 'value' to encode values as 'Expr's.
+--
+-- > > let notE = value "not" not
+-- > > :t notE
+-- > notE :: Expr
+-- > > print notE
+-- > not :: Bool -> Bool
+--
+-- Using ':$' we can apply function valued 'Expr's, to other Exprs.
+--
+-- > > let notFalse = notE :$ false
+-- > > :t notFalse
+-- > notFalse :: Expr
+-- > > notFalse
+-- > not False :: Bool
+--
+-- Using 'evaluate' or 'eval' we can evaluate 'Expr's
+-- back into a regular Haskell value.
+--
+-- > > evaluate notFalse :: Maybe Bool
+-- > Just True
+-- > > evaluate notFalse :: Maybe Int
+-- > Nothing
+-- > > eval False notFalse
+-- > True
+-- > > eval (0::Int) notFalse
+-- > 0
+--
 -- /Example:/
 -- Like with "Data.Dynamic", we can use Express to create heterogeneous lists:
 --
@@ -39,7 +81,7 @@
 -- > > mapMaybe evaluate xs :: [String]
 -- > ["123"]
 --
--- If define an heterogeneous list of functions encoded as 'Expr's:
+-- If we define an heterogeneous list of functions encoded as 'Expr's:
 --
 -- > > let fs = [value "not" not, value "&&" (&&), value "abs" (abs :: Int -> Int)]
 -- > > :t fs
diff --git a/src/Data/Express/Core.hs b/src/Data/Express/Core.hs
--- a/src/Data/Express/Core.hs
+++ b/src/Data/Express/Core.hs
@@ -825,26 +825,30 @@
 -- > > values (xx -+- yy)
 -- > [ (+) :: Int -> Int -> Int
 -- > , x :: Int
--- > , y :: Int ]
+-- > , y :: Int
+-- > ]
 --
 -- > > values (xx -+- (yy -+- zz))
 -- > [ (+) :: Int -> Int -> Int
 -- > , x :: Int
 -- > , (+) :: Int -> Int -> Int
 -- > , y :: Int
--- > , z :: Int ]
+-- > , z :: Int
+-- > ]
 --
 -- > > values (zero -+- (one -*- two))
 -- > [ (+) :: Int -> Int -> Int
 -- > , 0 :: Int
 -- > , (*) :: Int -> Int -> Int
 -- > , 1 :: Int
--- > , 2 :: Int ]
+-- > , 2 :: Int
+-- > ]
 --
 -- > > values (pp -&&- true)
 -- > [ (&&) :: Bool -> Bool -> Bool
 -- > , p :: Bool
--- > , True :: Bool ]
+-- > , True :: Bool
+-- > ]
 values :: Expr -> [Expr]
 values e  =  v e []
   where
@@ -859,24 +863,28 @@
 -- > > nubValues (xx -+- yy)
 -- > [ x :: Int
 -- > , y :: Int
--- > , (+) :: Int -> Int -> Int ]
+-- > , (+) :: Int -> Int -> Int
+-- ]
 --
 -- > > nubValues (xx -+- (yy -+- zz))
 -- > [ x :: Int
 -- > , y :: Int
 -- > , z :: Int
--- > , (+) :: Int -> Int -> Int ]
+-- > , (+) :: Int -> Int -> Int
+-- > ]
 --
 -- > > nubValues (zero -+- (one -*- two))
 -- > [ 0 :: Int
 -- > , 1 :: Int
 -- > , 2 :: Int
 -- > , (*) :: Int -> Int -> Int
--- > , (+) :: Int -> Int -> Int ]
+-- > , (+) :: Int -> Int -> Int
+-- > ]
 --
 -- > > nubValues (pp -&&- pp)
 -- > [ p :: Bool
--- > , (&&) :: Bool -> Bool -> Bool ]
+-- > , (&&) :: Bool -> Bool -> Bool
+-- > ]
 nubValues :: Expr -> [Expr]
 nubValues  =  v
   where
@@ -892,18 +900,21 @@
 --
 -- > > consts (xx -+- (yy -+- zz))
 -- > [ (+) :: Int -> Int -> Int
--- > , (+) :: Int -> Int -> Int ]
+-- > , (+) :: Int -> Int -> Int
+-- > ]
 --
 -- > > consts (zero -+- (one -*- two))
 -- > [ (+) :: Int -> Int -> Int
 -- > , 0 :: Int
 -- > , (*) :: Int -> Int -> Int
 -- > , 1 :: Int
--- > , 2 :: Int ]
+-- > , 2 :: Int
+-- > ]
 --
 -- > > consts (pp -&&- true)
 -- > [ (&&) :: Bool -> Bool -> Bool
--- > , True :: Bool ]
+-- > , True :: Bool
+-- > ]
 consts :: Expr -> [Expr]
 consts  =  filter isConst . values
 
@@ -919,7 +930,8 @@
 --
 -- > > nubConsts (pp -&&- true)
 -- > [ True :: Bool
--- > , (&&) :: Bool -> Bool -> Bool ]
+-- > , (&&) :: Bool -> Bool -> Bool
+-- > ]
 nubConsts :: Expr -> [Expr]
 nubConsts  =  c
   where
@@ -932,12 +944,14 @@
 --
 -- > > vars (xx -+- yy)
 -- > [ x :: Int
--- > , y :: Int ]
+-- > , y :: Int
+-- > ]
 --
 -- > > vars (xx -+- (yy -+- xx))
 -- > [ x :: Int
 -- > , y :: Int
--- > , x :: Int ]
+-- > , x :: Int
+-- > ]
 --
 -- > > vars (zero -+- (one -*- two))
 -- > []
@@ -953,11 +967,13 @@
 --
 -- > > nubVars (yy -+- xx)
 -- > [ x :: Int
--- > , y :: Int ]
+-- > , y :: Int
+-- > ]
 --
 -- > > nubVars (xx -+- (yy -+- xx))
 -- > [ x :: Int
--- > , y :: Int ]
+-- > , y :: Int
+-- > ]
 --
 -- > > nubVars (zero -+- (one -*- two))
 -- > []
@@ -974,7 +990,7 @@
 -- Return the arity of the given expression,
 -- i.e. the number of arguments that its type takes.
 --
--- > > arity (val 0)
+-- > > arity (val (0::Int))
 -- > 0
 --
 -- > > arity (val False)
@@ -995,6 +1011,12 @@
 -- Returns the size of the given expression,
 -- i.e. the number of terminal values in it.
 --
+-- > zero       =  val (0 :: Int)
+-- > one        =  val (1 :: Int)
+-- > two        =  val (2 :: Int)
+-- > xx -+- yy  =  value "+" ((+) :: Int->Int->Int) :$ xx :$ yy
+-- > abs' xx    =  value "abs" (abs :: Int->Int) :$ xx
+--
 -- > > size zero
 -- > 1
 --
@@ -1014,6 +1036,14 @@
 -- increases the depth of both its arguments by one.
 -- (cf. 'height')
 --
+-- With
+--
+-- > zero       =  val (0 :: Int)
+-- > one        =  val (1 :: Int)
+-- > two        =  val (2 :: Int)
+-- > xx -+- yy  =  value "+" ((+) :: Int->Int->Int) :$ xx :$ yy
+-- > abs' xx    =  value "abs" (abs :: Int->Int) :$ xx
+--
 -- > > depth zero
 -- > 1
 --
@@ -1037,6 +1067,16 @@
 -- increases the depth of its first argument by two
 -- and of its second argument by one.
 -- (cf. 'depth')
+--
+-- With:
+--
+-- > zero          =  val (0 :: Int)
+-- > one           =  val (1 :: Int)
+-- > two           =  val (2 :: Int)
+-- > const' xx yy  =  value "const" (const :: Int->Int->Int) :$ xx :$ yy
+-- > abs' xx       =  value "abs" (abs :: Int->Int) :$ xx
+--
+-- Then:
 --
 -- > > height zero
 -- > 1
diff --git a/src/Data/Express/Express.hs b/src/Data/Express/Express.hs
--- a/src/Data/Express/Express.hs
+++ b/src/Data/Express/Express.hs
@@ -6,7 +6,23 @@
 --
 -- Defines the 'Express' type class.
 {-# LANGUAGE CPP #-}
-module Data.Express.Express (Express (..)) where
+module Data.Express.Express
+  ( Express (..)
+  , (-:)
+  , (->:)
+  , (->>:)
+  , (->>>:)
+  , (->>>>:)
+  , (->>>>>:)
+  , (->>>>>>:)
+  , (->>>>>>>:)
+  , (->>>>>>>>:)
+  , (->>>>>>>>>:)
+  , (->>>>>>>>>>:)
+  , (->>>>>>>>>>>:)
+  , (->>>>>>>>>>>>:)
+  )
+where
 
 import Data.Express.Core
 import Data.Typeable
@@ -41,7 +57,7 @@
 -- >   expr s@Empty       = value "Empty" (Empty   -: s)
 --
 -- To declare 'expr' it may be useful to use auxiliary type binding operators:
--- '-:', '->:', '->>:', ....
+-- '-:', '->:', '->>:', '->>>:', '->>>>:', '->>>>>:', ...
 --
 -- For types with atomic values, just declare @ expr = val @
 class Typeable a => Express a where
@@ -162,81 +178,84 @@
 
 -- type binding utilities --
 
+-- | Type restricted version of const
+-- that forces its first argument
+-- to have the same type as the second.
+--
+-- >  value -: (undefined :: Ty)  =  value :: Ty
 (-:) :: a -> a -> a
 (-:) = asTypeOf -- const
 infixl 1 -:
 
-(-:>) :: (a -> b) -> a -> (a -> b)
-(-:>) = const
-infixl 1 -:>
-
+-- | Type restricted version of const
+-- that forces the result of its first argument
+-- to have the same type as the second.
+--
+-- >  f ->: (undefined :: Ty)  =  f :: a -> Ty
 (->:) :: (a -> b) -> b -> (a -> b)
 (->:) = const
 infixl 1 ->:
 
-(->:>) :: (a -> b -> c) -> b -> (a -> b -> c)
-(->:>) = const
-infixl 1 ->:>
-
+-- | Type restricted version of const
+-- that forces the result of the result of its first argument
+-- to have the same type as the second.
+--
+-- > f ->>: (undefined :: Ty)  =  f :: a -> b -> Ty
 (->>:) :: (a -> b -> c) -> c -> (a -> b -> c)
 (->>:) = const
 infixl 1 ->>:
 
-(->>:>) :: (a -> b -> c -> d) -> c -> (a -> b -> c -> d)
-(->>:>) = const
-infixl 1 ->>:>
-
+-- | Type restricted version of const
+-- that forces the result of the result of the result of its first argument
+-- to have the same type as the second.
 (->>>:) :: (a -> b -> c -> d) -> d -> (a -> b -> c -> d)
 (->>>:) = const
 infixl 1 ->>>:
 
-(->>>:>) :: (a -> b -> c -> d -> e) -> d -> (a -> b -> c -> d -> e)
-(->>>:>) = const
-infixl 1 ->>>:>
-
+-- | Forces the result type of a 4-argument function.
 (->>>>:) :: (a -> b -> c -> d -> e) -> e -> (a -> b -> c -> d -> e)
 (->>>>:) = const
 infixl 1 ->>>>:
 
-(->>>>:>) :: (a -> b -> c -> d -> e -> f) -> e -> (a -> b -> c -> d -> e -> f)
-(->>>>:>) = const
-infixl 1 ->>>>:>
-
+-- | Forces the result type of a 5-argument function.
 (->>>>>:) :: (a -> b -> c -> d -> e -> f) -> f -> (a -> b -> c -> d -> e -> f)
 (->>>>>:) = const
 infixl 1 ->>>>>:
 
-(->>>>>:>) :: (a->b->c->d->e->f->g) -> f -> (a->b->c->d->e->f->g)
-(->>>>>:>) = const
-infixl 1 ->>>>>:>
-
+-- | Forces the result type of a 6-argument function.
 (->>>>>>:) :: (a->b->c->d->e->f->g) -> g -> (a->b->c->d->e->f->g)
 (->>>>>>:) = const
 infixl 1 ->>>>>>:
 
+-- | Forces the result type of a 7-argument function.
 (->>>>>>>:) :: (a->b->c->d->e->f->g->h) -> h -> (a->b->c->d->e->f->g->h)
 (->>>>>>>:) = const
 infixl 1 ->>>>>>>:
 
+-- | Forces the result type of a 8-argument function.
 (->>>>>>>>:) :: (a->b->c->d->e->f->g->h->i) -> i -> (a->b->c->d->e->f->g->h->i)
 (->>>>>>>>:) = const
 infixl 1 ->>>>>>>>:
 
+-- | Forces the result type of a 9-argument function.
 (->>>>>>>>>:) :: (a->b->c->d->e->f->g->h->i->j) -> j
               -> (a->b->c->d->e->f->g->h->i->j)
 (->>>>>>>>>:) = const
 infixl 1 ->>>>>>>>>:
 
+-- | Forces the result type of a 10-argument function.
 (->>>>>>>>>>:) :: (a->b->c->d->e->f->g->h->i->j->k) -> k
                -> (a->b->c->d->e->f->g->h->i->j->k)
 (->>>>>>>>>>:) = const
 infixl 1 ->>>>>>>>>>:
 
+-- | Forces the result type of a 11-argument function.
 (->>>>>>>>>>>:) :: (a->b->c->d->e->f->g->h->i->j->k->l) -> l
                 -> (a->b->c->d->e->f->g->h->i->j->k->l)
 (->>>>>>>>>>>:) = const
 infixl 1 ->>>>>>>>>>>:
 
+-- | Forces the result type of a 12-argument function.
 (->>>>>>>>>>>>:) :: (a->b->c->d->e->f->g->h->i->j->k->l->m) -> m
                  -> (a->b->c->d->e->f->g->h->i->j->k->l->m)
 (->>>>>>>>>>>>:) = const
diff --git a/src/Data/Express/Express/Derive.hs b/src/Data/Express/Express/Derive.hs
--- a/src/Data/Express/Express/Derive.hs
+++ b/src/Data/Express/Express/Derive.hs
@@ -20,10 +20,15 @@
 import Data.Char
 import Data.List
 import Data.Express.Utils.TH
+import Data.Express.Utils.List
+import Data.Express.Utils.String
 
 -- | Derives an 'Express' instance for the given type 'Name'.
 --
 -- This function needs the @TemplateHaskell@ extension.
+--
+-- If '-:', '->:', '->>:', '->>>:', ... are not in scope,
+-- this will derive them as well.
 deriveExpress :: Name -> DecsQ
 deriveExpress  =  deriveWhenNeededOrWarn ''Express reallyDeriveExpress
 
@@ -52,8 +57,9 @@
                   , v <- vs]
   cs <- typeConstructorsArgNames t
   asName <- newName "x"
+  let withTheReturnTypeOfs = deriveWithTheReturnTypeOfs $ [length ns | (_,ns) <- cs]
   let generalizableExpr = mergeIFns $ foldr1 mergeI
-        [ do retTypeOf <- lookupValN $ "-" ++ replicate (length ns) '>' ++ ":"
+        [ do let retTypeOf = mkName $ "-" ++ replicate (length ns) '>' ++ ":"
              let exprs = [[| expr $(varE n) |] | n <- ns]
              let conex = [| $(varE retTypeOf) $(conE c) $(varE asName) |]
              let root = [| value $(stringE $ showJustName c) $(conex) |]
@@ -62,9 +68,34 @@
                    expr $(asP asName $ conP c (map varP ns)) = $rhs |]
         | (c,ns) <- cs
         ]
-  cxt |=>| generalizableExpr
+  withTheReturnTypeOfs |++| (cxt |=>| generalizableExpr)
 
 -- Not only really derive Express instances,
 -- but cascade through argument types.
 reallyDeriveExpressCascading :: Name -> DecsQ
 reallyDeriveExpressCascading  =  reallyDeriveCascading ''Express reallyDeriveExpress
+
+deriveWithTheReturnTypeOfs :: [Int] -> DecsQ
+deriveWithTheReturnTypeOfs  =
+  fmap concat . mapM deriveWithTheReturnTypeOf . nubSort
+
+deriveWithTheReturnTypeOf :: Int -> DecsQ
+deriveWithTheReturnTypeOf n  =  do
+  mf <- lookupValueName name
+  case mf of
+    Nothing -> reallyDeriveWithTheReturnTypeOf n
+    Just _  -> return []
+  where
+  name  =  "-" ++ replicate n '>' ++ ":"
+
+reallyDeriveWithTheReturnTypeOf :: Int -> DecsQ
+reallyDeriveWithTheReturnTypeOf n  =  do
+  td <- sigD name theT
+  vd <- [d| $(varP name) = const |]
+  return $ td:vd
+  where
+  theT  =  [t| $(theFunT) -> $(last vars) -> $(theFunT) |]
+  theFunT  =  foldr1 funT vars
+  funT t1 t2  =  [t| $(t1) -> $(t2) |]
+  vars  =  map (varT . mkName) . take (n+1) . primeCycle $ map (:"") ['a'..'z']
+  name  =  mkName $ "-" ++ replicate n '>' ++ ":"
diff --git a/src/Data/Express/Instances.hs b/src/Data/Express/Instances.hs
--- a/src/Data/Express/Instances.hs
+++ b/src/Data/Express/Instances.hs
@@ -5,6 +5,14 @@
 -- Maintainer  : Rudy Matela <rudy@matela.com.br>
 --
 -- Defines utilities do deal with instances of typeclasses
+--
+-- Functions provided by this module store the set of instances as a simple
+-- Haskell list.  When storing only a few instances this should be fine in
+-- terms of performance.
+--
+-- If you plan to store hundreds or thousands of instances,
+-- we recommend implementing different versions that use
+-- a more efficient Set/Map storage.
 module Data.Express.Instances
   ( reifyEq
   , reifyOrd
diff --git a/src/Data/Express/Utils/TH.hs b/src/Data/Express/Utils/TH.hs
--- a/src/Data/Express/Utils/TH.hs
+++ b/src/Data/Express/Utils/TH.hs
@@ -27,6 +27,7 @@
   , showJustName
   , typeConstructorsArgNames
   , (|=>|)
+  , (|++|)
   , whereI
   , module Language.Haskell.TH
   )
@@ -229,6 +230,9 @@
   where ac (InstanceD o c ts ds) c' = InstanceD o (c++c') ts ds
         ac d                     _  = d
 #endif
+
+(|++|) :: DecsQ -> DecsQ -> DecsQ
+(|++|) = liftM2 (++)
 
 mergeIFns :: DecsQ -> DecsQ
 mergeIFns qds = do ds <- qds
diff --git a/test/Test.hs b/test/Test.hs
--- a/test/Test.hs
+++ b/test/Test.hs
@@ -9,8 +9,8 @@
 -- It should never be exported in @ express.cabal @.
 module Test
   ( module Test.LeanCheck
-  , module Test.LeanCheck.Utils
   , module Test.LeanCheck.Derive
+  , module Test.LeanCheck.Utils
   , module Data.Express.Fixtures
   , module Data.Express.Utils.List
   , module Data.Express.Utils.Typeable
