diff --git a/ChangeLog b/ChangeLog
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,24 @@
+# 0.6.1
+
+- Fixing documentation typos
+- Implementing basic context merging (see
+  <https://github.com/lymar/hastache/issues/31>)
+- `mkGenericContext'` takes an additional `(String -> String)`
+  argument which is applied to record field names, much like aeson's
+  `fieldLabelModifier`
+- Removing unnecessary `utf8-string` dependency
+- Implementing the generic context creation for `Maybe` (see
+  <https://github.com/lymar/hastache/issues/38> and
+  `nestedPolyGenericContextTest` test), `Either`, `()`, and `Version`.
+- `mkReadme` is now officially an executable
+- Big change: custom extensions for generic contexts (should solve
+  #30). See the documentation for `Text.Hastache.Context` and the
+  `genericCustom.hs` example.
+- Making Hastache work with new base-4.8 (see #41)
+
+Thanks to: Tobias Florek, Edsko de Vries, Janne Hellsten, @clinty,
+Stefan Kersten, Herbert Valerio Riedel, and others
+
 # 0.6.0
 
 - Switching from lazy ByteString to lazy Text
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -197,6 +197,65 @@
 No new messages.
 ```
 
+Multiple constructors (in generic context)
+
+```haskell
+#!/usr/local/bin/runhaskell
+-- | Multiple constructors in generic contexts
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE OverloadedStrings  #-}
+import           Data.Data
+import           Data.Monoid
+import           Data.Typeable                 ()
+
+import qualified Data.Text.Lazy    as TL
+import qualified Data.Text.Lazy.IO as TL
+import           Text.Hastache
+import           Text.Hastache.Context
+
+data Hero = SuperHero { name      :: String
+                      , powers    :: [String]
+                      , companion :: String
+                      }
+          | EvilHero  { name   :: String
+                      , minion :: String
+                      }
+          deriving (Show, Data, Typeable)
+
+template :: String
+template = mconcat [
+    "{{#SuperHero}}\n",
+    "Hero: {{name}}\n",
+    " * Powers: {{#powers}}\n",
+    "\n   - {{.}}{{/powers}} \n",
+    " * Companion: {{companion}}\n",
+    "{{/SuperHero}}\n",
+    "{{#EvilHero}}\n",
+    "Evil hero: {{name}}\n",
+    " * Minion: {{minion}}\n",
+    "{{/EvilHero}}"]
+
+render :: Hero -> IO TL.Text
+render = hastacheStr defaultConfig (encodeStr template)
+       . mkGenericContext
+
+main :: IO ()
+main = do let batman = SuperHero "Batman" ["ht","ht"] "Robin"
+          let doctorEvil = EvilHero "Doctor Evil" "Mini-Me"
+          render batman >>= TL.putStrLn
+          render doctorEvil >>= TL.putStrLn
+```
+```
+Hero: Batman
+ * Powers: 
+   - ht
+   - ht 
+ * Companion: Robin
+
+Evil hero: Doctor Evil
+ * Minion: Mini-Me
+```
+
 #### Functions
 
 ```haskell
@@ -243,6 +302,70 @@
 aaa aaabbb aaabbbccc
 ```
 
+#### Custom queries and field renaming
+
+```haskell
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE StandaloneDeriving #-}
+{-# LANGUAGE TypeSynonymInstances #-}
+
+-- Custom extension function for types that are not supported out of
+-- the box in generic contexts
+import Text.Hastache 
+import Text.Hastache.Context 
+
+import qualified Data.Text.Lazy as TL 
+import qualified Data.Text.Lazy.IO as TL 
+
+import Data.Data (Data, Typeable)
+import Data.Decimal
+import Data.Generics.Aliases (extQ)
+
+data DecimalOrInf = Inf | Dec Decimal deriving (Data, Typeable)
+deriving instance Data Decimal
+data Test = Test {n::Int, m::DecimalOrInf} deriving (Data, Typeable)
+
+
+val1 :: Test
+val1 = Test 1 (Dec $ Decimal 3 1500)
+
+val2 :: Test
+val2 = Test 2 Inf
+
+query :: Ext
+query = defaultExt `extQ` f
+  where f Inf = "+inf"
+        f (Dec i) = show i
+
+r "m" = "moo"
+r x   = x
+
+example :: Test -> IO TL.Text
+example v = hastacheStr defaultConfig
+                        (encodeStr template)
+                        (mkGenericContext' r query v)
+
+template = concat [ 
+     "An int: {{n}}\n",
+     "{{#moo.Dec}}A decimal number: {{moo.Dec}}{{/moo.Dec}}",
+     "{{#moo.Inf}}An infinity: {{moo.Inf}}{{/moo.Inf}}"
+     ] 
+
+main = do
+  example val1 >>= TL.putStrLn
+  example val2 >>= TL.putStrLn
+```
+
+```
+An int: 1
+A decimal number: 1.500
+An int: 2
+An infinity: +inf
+```
+
+
 #### Generics big example
 
 ```haskell
@@ -298,3 +421,4 @@
 
  * [Hastache test](https://github.com/lymar/hastache/blob/master/tests/test.hs)
  * Real world example: [README.md file generator](https://github.com/lymar/hastache/blob/master/mkReadme.hs)
+ * [examples/ directory](https://github.com/lymar/hastache/tree/master/examples)
diff --git a/Text/Hastache.hs b/Text/Hastache.hs
--- a/Text/Hastache.hs
+++ b/Text/Hastache.hs
@@ -16,8 +16,8 @@
 Simplest example:
 
 @
-import Text.Hastache 
-import Text.Hastache.Context 
+import           Text.Hastache
+import           Text.Hastache.Context
 import qualified Data.Text.Lazy.IO as TL
 
 main = do 
@@ -41,22 +41,23 @@
 Using Generics:
 
 @
-import Text.Hastache 
-import Text.Hastache.Context 
+{&#45;\# LANGUAGE DeriveDataTypeable, OverloadedStrings \#&#45;}
+
+import           Text.Hastache
+import           Text.Hastache.Context
 import qualified Data.Text.Lazy.IO as TL
-import Data.Data 
-import Data.Generics 
- 
-data Info = Info { 
-    name    :: String, 
-    unread  :: Int 
+import           Data.Data
+
+data Info = Info {
+    name    :: String,
+    unread  :: Int
     } deriving (Data, Typeable)
 
-main = do 
-    res <- hastacheStr defaultConfig (encodeStr template) 
-        (mkGenericContext inf) 
-    TL.putStrLn res 
-  where 
+main = do
+    res <- hastacheStr defaultConfig template
+        (mkGenericContext inf)
+    TL.putStrLn res
+  where
     template = \"Hello, {{name}}!\\n\\nYou have {{unread}} unread messages.\"
     inf = Info \"Haskell\" 100
 @
@@ -71,6 +72,7 @@
     , MuType(..)
     , MuConfig(..)
     , MuVar(..)
+    , composeCtx
     , htmlEscape
     , emptyEscape
     , defaultConfig
@@ -86,12 +88,13 @@
 import Control.Monad.Trans.Maybe (MaybeT(MaybeT), runMaybeT)
 import Data.AEq (AEq,(~==))
 import Data.Functor ((<$>))
-import Data.Int
 import Data.IORef
+import Data.Int
 import Data.Maybe (isJust)
-import Data.Monoid (mappend, mempty)
+import Data.Monoid (Monoid, mappend, mempty)
 import Data.Text hiding (map, foldl1)
 import Data.Text.IO
+import Data.Version (Version)
 import Data.Word
 import Prelude hiding (putStrLn, readFile, length, drop, tail, dropWhile, elem,
     head, last, reverse, take, span, null)
@@ -119,8 +122,24 @@
     Text            -- ^ Variable name
     -> m (MuType m) -- ^ Value
 
+instance (Monad m) => Monoid (MuContext m) where
+    mempty = const $ return MuNothing
+    a `mappend` b = \v -> do
+        x <- a v
+        case x of
+            MuNothing -> b v
+            _ -> return x
+
+-- | Left-leaning compoistion of contexts. Given contexts @c1@ and
+-- @c2@, the behaviour of @(c1 <> c2) x@ is following: if @c1 x@
+-- produces 'MuNothing', then the result is @c2 x@. Otherwise the
+-- result is @c1 x@. Even if @c1 x@ is 'MuNothing', the monadic
+-- effects of @c1@ are still to take place.
+composeCtx :: (Monad m) => MuContext m -> MuContext m -> MuContext m
+composeCtx = mappend
+
 class Show a => MuVar a where
-    -- | Convert to Lazy ByteString
+    -- | Convert to lazy 'Data.Text.Lazy.Text'
     toLText   :: a -> TL.Text
     -- | Is empty variable (empty string, zero number etc.)
     isEmpty   :: a -> Bool 
@@ -163,7 +182,8 @@
 instance MuVar Word64  where {toLText = withShowToText; isEmpty = numEmpty}
 instance MuVar ()      where {toLText = withShowToText}
 
-    
+instance MuVar Version where {toLText = withShowToText }
+
 instance MuVar Char where
     toLText = TL.singleton
 
@@ -212,7 +232,7 @@
     muEscapeFunc        :: TL.Text -> TL.Text, 
         -- ^ Escape function ('htmlEscape', 'emptyEscape' etc.)
     muTemplateFileDir   :: Maybe FilePath,
-        -- ^ Directory for search partial templates ({{> templateName}})
+        -- ^ Directory for search partial templates (@{{> templateName}}@)
     muTemplateFileExt   :: Maybe String,
         -- ^ Partial template files extension
     muTemplateRead      :: FilePath -> m (Maybe Text)
@@ -220,22 +240,23 @@
         --   template could not be found.
     }
 
--- | Convert String to Text
+-- | Convert 'String' to 'Text'
 encodeStr :: String -> Text
 encodeStr = T.pack
 
--- | Convert String to Lazy Text
+-- | Convert 'String' to Lazy 'Data.Text.Lazy.Text'
 encodeStrLT :: String -> TL.Text
 encodeStrLT = TL.pack
 
--- | Convert Text to String
+-- | Convert 'Text' to 'String'
 decodeStr :: Text -> String
 decodeStr = T.unpack
 
--- | Convert Lazy Text to String
+-- | Convert Lazy 'Data.Text.Lazy.Text' to 'String'
 decodeStrLT :: TL.Text -> String
 decodeStrLT = TL.unpack
 
+-- | isMuNothing x = x == MuNothing
 isMuNothing :: MuType t -> Bool
 isMuNothing MuNothing = True
 isMuNothing _ = False
@@ -352,7 +373,7 @@
     (before, after) = breakOn close str
 
 trimCharsTest :: Char -> Bool
-trimCharsTest = (`Prelude.elem` " \t")
+trimCharsTest = (`Prelude.elem` [' ', '\t'])
 
 trimAll :: Text -> Text
 trimAll = dropAround trimCharsTest
diff --git a/Text/Hastache/Context.hs b/Text/Hastache/Context.hs
--- a/Text/Hastache/Context.hs
+++ b/Text/Hastache/Context.hs
@@ -1,5 +1,6 @@
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE CPP #-}
+{-# LANGUAGE RankNTypes #-}
 -- Module:      Text.Hastache.Context
 -- Copyright:   Sergey S Lymar (c) 2011-2013 
 -- License:     BSD3
@@ -14,11 +15,16 @@
       mkStrContext
     , mkStrContextM
     , mkGenericContext
+    , mkGenericContext'
+    , Ext
+    , defaultExt
     ) where 
 
 import Data.Data
 import Data.Generics
 import Data.Int
+import Data.Version (Version)
+import Data.Ratio (Ratio)
 import Data.Word
 
 import qualified Data.ByteString as BS
@@ -41,11 +47,19 @@
 mkStrContextM :: Monad m => (String -> m (MuType m)) -> MuContext m
 mkStrContextM f a = decodeStr a ~> f
 
+type Ext = forall b. (Data b, Typeable b) => b -> String
+
+-- | @defaultExt ==@ 'gshow'
+defaultExt :: Ext
+defaultExt = gshow
+
 {- | 
 Make Hastache context from Data.Data deriving type
 
 Supported field types:
 
+ * ()
+
  * String
  
  * Char
@@ -86,6 +100,12 @@
  
  * Bool
 
+ * Version
+
+ * Maybe @a@ (where @a@ is a supported datatype)
+
+ * Either @a@ @b@ (where @a@ and @b@ are supported datatypes)
+
  * Data.Text.Text -> Data.Text.Text
 
  * Data.Text.Text -> Data.Text.Lazy.Text
@@ -142,7 +162,7 @@
 example = hastacheStr defaultConfig (encodeStr template) 
     (mkGenericContext context)
     where
-    template = concat $ map (++ \"\\n\") [
+    template = unlines [
         \"string: {{stringField}}\",
         \"int: {{intField}}\",
         \"data: {{dataField.someField}}, {{dataField.anotherField}}\",
@@ -199,14 +219,79 @@
 @
 
 -}
-                    
 #if MIN_VERSION_base(4,7,0)
 mkGenericContext :: (Monad m, Data a, Typeable m) => a -> MuContext m
 #else
 mkGenericContext :: (Monad m, Data a, Typeable1 m) => a -> MuContext m
 #endif
-mkGenericContext val = toGenTemp val ~> convertGenTempToContext
-    
+mkGenericContext val = toGenTemp id defaultExt val ~> convertGenTempToContext
+
+{-| 
+
+Like 'mkGenericContext', but apply the first function to record field
+names when constructing the context. The second function is used to
+constructing values for context from datatypes that are nor supported
+as primitives in the library. The resulting value can be accessed
+using the @.DatatypeName@ field:
+
+@
+\{\-\# LANGUAGE DeriveDataTypeable \#\-\}
+\{\-\# LANGUAGE FlexibleInstances \#\-\}
+\{\-\# LANGUAGE ScopedTypeVariables \#\-\}
+\{\-\# LANGUAGE StandaloneDeriving \#\-\}
+\{\-\# LANGUAGE TypeSynonymInstances \#\-\}
+import Text.Hastache 
+import Text.Hastache.Context 
+
+import qualified Data.Text.Lazy as TL 
+import qualified Data.Text.Lazy.IO as TL 
+
+import Data.Data (Data, Typeable)
+import Data.Decimal
+import Data.Generics.Aliases (extQ)
+
+data Test = Test {n::Int, m::Decimal} deriving (Data, Typeable)
+deriving instance Data Decimal
+
+val :: Test
+val = Test 1 (Decimal 3 1500)
+
+q :: Ext
+q = defaultExt \`extQ\` (\(i::Decimal) -> "A decimal: " ++ show i)
+
+r "m" = "moo"
+r x   = x
+
+example :: IO TL.Text
+example = hastacheStr defaultConfig
+                      (encodeStr template)
+                      (mkGenericContext' r q val)
+
+template = concat [ 
+     "{{n}}\\n",
+     "{{moo.Decimal}}"
+     ] 
+
+main = example >>= TL.putStrLn
+@
+
+Result:
+
+@
+1
+A decimal: 1.500
+@
+
+-}
+#if MIN_VERSION_base(4,7,0)
+mkGenericContext' :: (Monad m, Data a, Typeable m) 
+                  => (String -> String) -> Ext -> a -> MuContext m
+#else
+mkGenericContext' :: (Monad m, Data a, Typeable1 m) 
+                  => (String -> String) -> Ext -> a -> MuContext m
+#endif
+mkGenericContext' f ext val = toGenTemp f ext val ~> convertGenTempToContext
+
 data TD m = 
       TSimple (MuType m) 
     | TObj [(String, TD m)] 
@@ -215,63 +300,81 @@
     deriving (Show)
 
 #if MIN_VERSION_base(4,7,0)
-toGenTemp :: (Data a, Monad m, Typeable m) => a -> TD m
+toGenTemp :: (Data a, Monad m, Typeable m) 
+          => (String -> String) -> Ext -> a -> TD m
 #else
-toGenTemp :: (Data a, Monad m, Typeable1 m) => a -> TD m
+toGenTemp :: (Data a, Monad m, Typeable1 m) 
+          => (String -> String) -> Ext -> a -> TD m
 #endif
-toGenTemp a = TObj $ conName : zip fields (gmapQ procField a)
+toGenTemp f g a = TObj $ conName : zip fields (gmapQ (procField f g) a) 
     where
-    fields = toConstr a ~> constrFields
-    conName = (toConstr a ~> showConstr, MuBool True ~> TSimple)
+    fields = toConstr a ~> constrFields ~> map f
+    conName = (toConstr a ~> showConstr, TSimple . MuVariable $ g a)
 
 #if MIN_VERSION_base(4,7,0)
-procField :: (Data a, Monad m, Typeable m) => a -> TD m
+procField :: (Data a, Monad m, Typeable m) 
+          => (String -> String) -> Ext -> a -> TD m
 #else
-procField :: (Data a, Monad m, Typeable1 m) => a -> TD m
+procField :: (Data a, Monad m, Typeable1 m) 
+          => (String -> String) -> Ext -> a -> TD m
 #endif
-procField = 
-    obj
-    `ext1Q` list
-    `extQ` (\(i::String)            -> MuVariable (encodeStr i) ~> TSimple)
-    `extQ` (\(i::Char)              -> MuVariable i ~> TSimple)
-    `extQ` (\(i::Double)            -> MuVariable i ~> TSimple)
-    `extQ` (\(i::Float)             -> MuVariable i ~> TSimple)
-    `extQ` (\(i::Int)               -> MuVariable i ~> TSimple)
-    `extQ` (\(i::Int8)              -> MuVariable i ~> TSimple)
-    `extQ` (\(i::Int16)             -> MuVariable i ~> TSimple)
-    `extQ` (\(i::Int32)             -> MuVariable i ~> TSimple)
-    `extQ` (\(i::Int64)             -> MuVariable i ~> TSimple)
-    `extQ` (\(i::Integer)           -> MuVariable i ~> TSimple)
-    `extQ` (\(i::Word)              -> MuVariable i ~> TSimple)
-    `extQ` (\(i::Word8)             -> MuVariable i ~> TSimple)
-    `extQ` (\(i::Word16)            -> MuVariable i ~> TSimple)
-    `extQ` (\(i::Word32)            -> MuVariable i ~> TSimple)
-    `extQ` (\(i::Word64)            -> MuVariable i ~> TSimple)
-    `extQ` (\(i::BS.ByteString)     -> MuVariable i ~> TSimple)
-    `extQ` (\(i::LBS.ByteString)    -> MuVariable i ~> TSimple)
-    `extQ` (\(i::T.Text)            -> MuVariable i ~> TSimple)
-    `extQ` (\(i::TL.Text)           -> MuVariable i ~> TSimple)
-    `extQ` (\(i::Bool)              -> MuBool i     ~> TSimple)
+procField f g a = 
+    case res a of
+      TUnknown -> TSimple . MuVariable . g $ a          
+      b        -> b
+  where
+    res = obj
+        `ext1Q` list
+        `extQ` (\(i::String)            -> MuVariable (encodeStr i) ~> TSimple)
+        `extQ` (\(i::Char)              -> MuVariable i ~> TSimple)
+        `extQ` (\(i::Double)            -> MuVariable i ~> TSimple)
+        `extQ` (\(i::Float)             -> MuVariable i ~> TSimple)
+        `extQ` (\(i::Int)               -> MuVariable i ~> TSimple)
+        `extQ` (\(i::Int8)              -> MuVariable i ~> TSimple)
+        `extQ` (\(i::Int16)             -> MuVariable i ~> TSimple)
+        `extQ` (\(i::Int32)             -> MuVariable i ~> TSimple)
+        `extQ` (\(i::Int64)             -> MuVariable i ~> TSimple)
+        `extQ` (\(i::Integer)           -> MuVariable i ~> TSimple)
+        `extQ` (\(i::Word)              -> MuVariable i ~> TSimple)
+        `extQ` (\(i::Word8)             -> MuVariable i ~> TSimple)
+        `extQ` (\(i::Word16)            -> MuVariable i ~> TSimple)
+        `extQ` (\(i::Word32)            -> MuVariable i ~> TSimple)
+        `extQ` (\(i::Word64)            -> MuVariable i ~> TSimple)
+        `extQ` (\(i::BS.ByteString)     -> MuVariable i ~> TSimple)
+        `extQ` (\(i::LBS.ByteString)    -> MuVariable i ~> TSimple)
+        `extQ` (\(i::T.Text)            -> MuVariable i ~> TSimple)
+        `extQ` (\(i::TL.Text)           -> MuVariable i ~> TSimple)
+        `extQ` (\(i::Bool)              -> MuBool i     ~> TSimple)
+        `extQ` (\()                     -> MuVariable () ~> TSimple)
+        `extQ` (\(i::Version)           -> MuVariable i ~> TSimple)
+        `extQ` muLambdaTT
+        `extQ` muLambdaTTL
+        `extQ` muLambdaTLTL
+        `extQ` muLambdaBSBS
+        `extQ` muLambdaSS
+        `extQ` muLambdaBSLBS
 
-    `extQ` muLambdaTT
-    `extQ` muLambdaTTL
-    `extQ` muLambdaTLTL
-    `extQ` muLambdaBSBS
-    `extQ` muLambdaSS
-    `extQ` muLambdaBSLBS
-    
-    `extQ` muLambdaMTT
-    `extQ` muLambdaMTTL
-    `extQ` muLambdaMTLTL
-    `extQ` muLambdaMBSBS
-    `extQ` muLambdaMSS
-    `extQ` muLambdaMBSLBS
-    where
+        `extQ` muLambdaMTT
+        `extQ` muLambdaMTTL
+        `extQ` muLambdaMTLTL
+        `extQ` muLambdaMBSBS
+        `extQ` muLambdaMSS
+        `extQ` muLambdaMBSLBS
+
+        `ext1Q` muMaybe
+        `ext2Q` muEither 
+
     obj a = case dataTypeRep (dataTypeOf a) of
-        AlgRep (_:_) -> toGenTemp a
+        AlgRep (_:_) -> toGenTemp f g a
         _ -> TUnknown
-    list a = map procField a ~> TList
+    list a = map (procField f g) a ~> TList
 
+    muMaybe Nothing = TSimple MuNothing
+    muMaybe (Just a) = TList [procField f g a]
+
+    muEither (Left a) = procField f g a
+    muEither (Right b) = procField f g b
+
     muLambdaTT :: (T.Text -> T.Text) -> TD m
     muLambdaTT f = MuLambda f ~> TSimple
 
@@ -302,7 +405,7 @@
 
     muLambdaMTTL :: (T.Text -> m TL.Text) -> TD m
     muLambdaMTTL f = MuLambdaM f ~> TSimple
-        
+
     muLambdaMBSBS :: (BS.ByteString -> m BS.ByteString) -> TD m
     muLambdaMBSBS f = MuLambdaM (f . T.encodeUtf8) ~> TSimple
 
diff --git a/hastache.cabal b/hastache.cabal
--- a/hastache.cabal
+++ b/hastache.cabal
@@ -1,5 +1,5 @@
 name:            hastache
-version:         0.6.0
+version:         0.6.1
 license:         BSD3
 license-file:    LICENSE
 category:        Text
@@ -24,19 +24,34 @@
     README.md
     ChangeLog
 
+executable mkReadme
+  main-is: mkReadme.hs
+  build-depends: hastache, process,
+    base >=4 && <4.9
+    ,bytestring
+    ,mtl
+    ,transformers
+    ,directory
+    ,filepath
+    ,text
+    ,containers
+    ,syb
+    ,blaze-builder
+    ,ieee754
+
+
 library
   exposed-modules:
     Text.Hastache
     Text.Hastache.Context
 
   build-depends:
-    base == 4.*
+    base >=4 && <4.9
     ,bytestring
     ,mtl
     ,transformers
     ,directory
     ,filepath
-    ,utf8-string
     ,text
     ,containers
     ,syb
@@ -54,7 +69,7 @@
 
   build-depends:
     hastache
-   ,base == 4.*
+   ,base >=4 && <4.9
    ,directory
    ,mtl
    ,HUnit
diff --git a/mkReadme.hs b/mkReadme.hs
new file mode 100644
--- /dev/null
+++ b/mkReadme.hs
@@ -0,0 +1,50 @@
+#!/usr/local/bin/runhaskell
+import Text.Hastache 
+import Text.Hastache.Context
+import qualified Data.Text.Lazy as TL
+import qualified Data.Text.Lazy.IO as TL
+import System.Process (readProcess)
+import System.Directory (setCurrentDirectory, getCurrentDirectory)
+import System.FilePath ((</>))
+import Data.List (span, lines, intersperse)
+import Data.Char (isSpace)
+
+main = do 
+    res <- hastacheFile defaultConfig "README.md.ha"
+        (mkStrContext context)
+    TL.writeFile "README.md" res 
+    where 
+    context "example" = MuLambdaM $ \fn -> do
+        cd <- setExampleDir
+        fc <- readFile $ exampleFile fn
+        let { forTC = case span (\t -> trim t /= be) (lines $ trim fc) of
+            (a,[]) -> a
+            (_,a) -> drop 1 a }
+        let explText = concat $ intersperse "\n" forTC
+        
+        setCurrentDirectory cd
+        return $ concat [
+              "```haskell\n"
+            , explText
+            , "\n```"
+            ]
+
+    context "runExample" = MuLambdaM $ \fn -> do
+        cd <- setExampleDir
+        explRes <- readProcess "runhaskell" [exampleFile fn] []
+        setCurrentDirectory cd
+        return $ concat [
+              "```\n"
+            , trim explRes
+            , "\n```"
+            ]
+
+    be = "-- begin example"
+    setExampleDir = do
+        cd <- getCurrentDirectory
+        setCurrentDirectory $ cd </> "examples"
+        return cd
+    exampleFile fn = decodeStr fn ++ ".hs"
+
+trim :: String -> String
+trim = f . f where f = reverse . dropWhile isSpace
diff --git a/tests/test.hs b/tests/test.hs
--- a/tests/test.hs
+++ b/tests/test.hs
@@ -299,7 +299,8 @@
     someMuLambdaBS      :: BS.ByteString -> BS.ByteString,
     someMuLambdaS       :: String -> String,
     someMuLambdaMBS     :: BS.ByteString -> IO BS.ByteString,
-    someMuLambdaMS      :: String -> IO String
+    someMuLambdaMS      :: String -> IO String,
+    someEitherValue     :: Either String Int
     }
     deriving (Data, Typeable)
 
@@ -329,6 +330,7 @@
         \{{#someMuLambdaS}}upper{{/someMuLambdaS}}\n\
         \{{#someMuLambdaMBS}}reverse in IO lambda{{/someMuLambdaMBS}}\n\
         \{{#someMuLambdaMS}}upper in IO lambda{{/someMuLambdaMS}}\n\
+        \{{someEitherValue}}\n\
         \text 2\n\
         \"
     context = SomeData {
@@ -341,7 +343,8 @@
         someMuLambdaBS = BS.reverse,
         someMuLambdaS = map toUpper,
         someMuLambdaMBS = return . BS.reverse,
-        someMuLambdaMS = return . map toUpper
+        someMuLambdaMS = return . map toUpper,
+        someEitherValue = Right 123
         }
 
     testRes = "\
@@ -362,6 +365,7 @@
         \UPPER\n\
         \adbmal OI ni esrever\n\
         \UPPER IN IO LAMBDA\n\
+        \123\n\
         \text 2\n\
         \"
 
@@ -430,6 +434,37 @@
         \Nested variable : NESTED_TWO\n\
         \"
 
+-- Nested generic context with polymorphic datatypes
+data Person = Person { personName :: String } deriving (Data, Typeable)
+data Info = Info { person :: Maybe Person } deriving (Data, Typeable)
+data Infos = Infos { infos :: [Info] } deriving (Data, Typeable)
+
+nestedPolyGenericContextTest = do
+    res <- hastacheStr defaultConfig (encodeStr template) context
+    assertEqualStr resCorrectness (decodeStrLT res) testRes
+    where
+    datum = Infos [Info Nothing, Info $ Just $ Person "Dude", Info $ Just $ Person "Dude2"]
+    template = "Greetings: {{#infos}}{{#person}}Hello, {{personName}}!\n{{/person}}{{/infos}}"
+    context = mkGenericContext datum
+    testRes = "Greetings: Hello, Dude!\nHello, Dude2!\n"
+
+-- Generic context with custom extension
+data MyData = MyData Int deriving (Data, Typeable)
+data TestInfo = TestInfo {n::Int,m::MyData} deriving (Data, Typeable)
+
+testExt :: Ext
+testExt = defaultExt `extQ` (\(MyData i) -> "Data " ++ show i)
+
+genericExtTest = do
+    res <- hastacheStr defaultConfig (encodeStr template) context
+    assertEqualStr resCorrectness (decodeStrLT res) testRes
+    where
+    datum = TestInfo 1 (MyData 0)
+    template = "{{n}}\n{{m.MyData}}"
+    context = mkGenericContext' id testExt datum
+    testRes = "1\nData 0"
+
+
 -- Accessing array item by index
 arrayItemsTest = do
     res <- hastacheStr defaultConfig (encodeStr template)
@@ -503,7 +538,27 @@
         \"
     testRes = "42"
 
+-- Context composition
+compositionTest = do
+    res <- hastacheStr defaultConfig (encodeStr template) $
+        mkGenericContext context 
+        `composeCtx` mempty
+        `composeCtx` mkStrContext context2
 
+    assertEqualStr resCorrectness (decodeStrLT res) testRes
+    where
+    context  = Heroes [Good 4, Evil 2]
+    context2 "Ugly" = MuVariable (3::Int)
+    context2 _      = MuNothing
+    template = "\
+        \{{#heroes}}\
+        \{{#Good}}{{goodness}}{{/Good}}\
+        \{{#Evil}}{{evilness}}{{/Evil}}\
+        \{{#Ugly}}{{Ugly}}{{/Ugly}}\
+        \{{/heroes}}\
+        \"
+    testRes = "4323"
+
 tests = TestList [
       TestLabel "Comments test" (TestCase commentsTest)
     , TestLabel "Variables test" (TestCase variablesTest)
@@ -517,13 +572,18 @@
     , TestLabel "Partials test" (TestCase partialsTest)
     , TestLabel "Generic context test" (TestCase genericContextTest)
     , TestLabel "Multiple constructors in a generic context"
-        (TestCase multipleConstrTest)
+        (TestCase multipleConstrTest)    
     , TestLabel "Nested context test" (TestCase nestedContextTest)
     , TestLabel "Nested generic context test"
                                         (TestCase nestedGenericContextTest)
+
+    , TestLabel "Nested generic context with polymorphic datatypes test"
+                                        (TestCase nestedPolyGenericContextTest)
     , TestLabel "Accessing array item by index" (TestCase arrayItemsTest)
     , TestLabel "Accessing array item by index (generic version)"
         (TestCase arrayItemsTestGeneric)
+    , TestLabel "Composing contexts" (TestCase compositionTest)
+    , TestLabel "Generic contexts with custom extensions" (TestCase genericExtTest)
     ]
 
 main = do
