diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,31 @@
 # Changelog for typed-encoding
 
+
+## Unreleased changes
+
+## 0.2.0.0
+  - breaking:
+    - Data.TypedEncoding.Instances modules reorganized
+    - Data.TypedEncoding.Internal.Class modules reorganized
+    - Data.TypedEncoding.Internal.Utils module renamed
+    - Several TypeAnnotations friendly changes:
+       * Removed polymorphic kinds in most places
+       * Changed typeclass name from `Subset` to `Superset`
+       * flipped type parameters on FlattenAs, HasA typeclass functions
+       * Removed Proxy parameters from several methods (few methods have a '_' backward compatible version which still has them)
+  - new functionality:
+    - `ToEncString` - class allowing to convert types to `Enc` encoded strings
+    - `FromEncString` - class reverses ToEncString
+    - `CheckedEnc` untyped version of `Enc` containing valid encoding
+    - `SomeEnc` existentially quantified version of `Enc` 
+    - `UncheckedEnc` for working with not validated encoding
+    - `RecreateExUnkStep` constructor added to RecreateEx
+    -  utility `IsStringR` - reverse to `IsString` class
+    -  utility `SymbolList` class
+  - docs: 
+    - ToEncString example
+
+
 ## 0.1.0.0
  - initial release
  
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
 Type level annotations, string transformations, and other goodies that make programming strings safer.
 
 ## Motivation
-I have recently spent a lot of time troubleshooting various `Base64`, `quoted-printable`, and `Utf8` encoding issues.  
+I have recently spent a lot of time troubleshooting various `Base64`, `quoted-printable`, and `UTF-8` encoding issues.  
 I decided to write a library that will help avoiding issues like these.
 
 This library allows to specify and work with types like
@@ -15,11 +15,19 @@
 myData :: Enc '["enc-B64", "r-UTF8"] ByteString
 ```
 
+It allows to define precise string content annotations like:
+
+```Haskell
+mydata :: Enc '["r-IpV4"] Text
+```
+
 and provides ways for 
    - encoding
    - decoding
    - recreation (encoding validation)
    - type conversions
+   - converting types to encoded strings
+   - typesafe conversion of encoded strings to types
 
 ... but this approach seems to be a bit more...
 
@@ -38,7 +46,7 @@
 ## Examples 
 
 Please see `Examples.TypedEncoding` it the module list.
- 
+
 ## Dependencies on other encoding libs
 
 Currently it uses
diff --git a/src/Data/TypedEncoding.hs b/src/Data/TypedEncoding.hs
--- a/src/Data/TypedEncoding.hs
+++ b/src/Data/TypedEncoding.hs
@@ -1,10 +1,7 @@
 {-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE DataKinds #-}
 
 -- |
--- Main Module in typed-encoding. 
---
 -- = Overview
 --
 -- This library allows to specify and work with types like
@@ -27,6 +24,13 @@
 -- upper = ...
 -- @
 --
+-- or define precise types to use with 'toEncString' and 'fromEncString'
+-- 
+-- @
+-- date :: Enc '["r-date-%d/%b/%Y:%X %Z"] Text
+-- date = toEncString ...
+-- @
+--
 -- Primary focus of type-encodings is to provide type safe
 --
 -- * /encoding/
@@ -37,6 +41,13 @@
 -- of string-like data (@ByteString@, @Text@) that is subject of some
 -- encoding or formatting restrictions.
 --
+-- as well as
+--
+-- * /toEncString/ 
+-- * /fromEncString/ 
+--
+-- conversions.
+--
 -- = Groups of annotations
 --
 -- typed-encoding uses type annotations grouped into semantic categories
@@ -67,14 +78,16 @@
 -- 
 -- = Usage
 --
--- To use this library import this module and one or more "instance" modules.
+-- To use this library import this module and one or more /instance/ module.
 --
 -- Here is list of instance modules available in typed-encoding library itself
 --
--- * "Data.TypedEncoding.Instances.Base64"
--- * "Data.TypedEncoding.Instances.ASCII" 
--- * "Data.TypedEncoding.Instances.UTF8" 
--- * "Data.TypedEncoding.Instances.Encode.Sample" 
+-- * "Data.TypedEncoding.Instances.Enc.Base64"
+-- * "Data.TypedEncoding.Instances.Restriction.Common" 
+-- * "Data.TypedEncoding.Instances.Restriction.ASCII" 
+-- * "Data.TypedEncoding.Instances.Restriction.UTF8" 
+-- * "Data.TypedEncoding.Instances.Do.Sample" 
+-- * "Data.TypedEncoding.Instances.ToEncString.Common" 
 -- 
 -- This list is not intended to be exhaustive, rather separate libraries
 -- can provide instances for other encodings and transformations.
@@ -92,25 +105,36 @@
     module Data.TypedEncoding
     -- * Classes
     , module Data.TypedEncoding.Internal.Class
+    -- * Combinators
+    , module Data.TypedEncoding.Internal.Combinators
     -- * Types
     , Enc
+    , CheckedEnc
     , EncodeEx(..)
     , RecreateEx(..)
     , UnexpectedDecodeEx(..)
-    -- * Combinators
+    , EncAnn 
+    -- * Existentially quantified version of @Enc@ and basic combinators
+    , module Data.TypedEncoding.Internal.Types.SomeEnc
+    -- * Types and combinators for not verfied encoding 
+    , module Data.TypedEncoding.Internal.Types.UncheckedEnc
+    -- * Basic @Enc@ Combinators
     , getPayload 
     , unsafeSetPayload
     , fromEncoding
     , toEncoding
+    -- * Basic @CheckedEnc@ Combinators  
+    , unsafeCheckedEnc
+    , getCheckedPayload
+    , getCheckedEncPayload
+    , toCheckedEnc
+    , fromCheckedEnc
+    -- * Other Basic Combinators     
+    , recreateErrUnknown
  ) where
 
-import           Data.TypedEncoding.Internal.Types (Enc
-                                              , RecreateEx(..)
-                                              , UnexpectedDecodeEx(..)
-                                              , EncodeEx(..)
-                                              , getPayload
-                                              , unsafeSetPayload
-                                              , toEncoding
-                                              , fromEncoding
-                                               )
+import           Data.TypedEncoding.Internal.Types
+import           Data.TypedEncoding.Internal.Types.SomeEnc
+import           Data.TypedEncoding.Internal.Types.UncheckedEnc
 import           Data.TypedEncoding.Internal.Class
+import           Data.TypedEncoding.Internal.Combinators
diff --git a/src/Data/TypedEncoding/Instances/ASCII.hs b/src/Data/TypedEncoding/Instances/ASCII.hs
deleted file mode 100644
--- a/src/Data/TypedEncoding/Instances/ASCII.hs
+++ /dev/null
@@ -1,119 +0,0 @@
-{-# LANGUAGE DataKinds #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE TypeOperators #-}
-{-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE OverloadedStrings #-}
-
--- | Strings can move to 'Enc "r-ASCII' only if they contain only ascii characters.
--- they always decode back
--- >>> :set -XOverloadedStrings -XMultiParamTypeClasses -XDataKinds
--- >>> encodeFAll . toEncoding () $ "Hello World" :: Either EncodeEx (Enc '["r-ASCII"] () T.Text)
--- Right (MkEnc Proxy () "Hello World")
---
--- >>> encodeFAll . toEncoding () $ "\194\160" :: Either EncodeEx (Enc '["r-ASCII"] () T.Text)
--- Left (EncodeEx "r-ASCII" (NonAsciiChar '\194'))
-module Data.TypedEncoding.Instances.ASCII where
-
-import           Data.TypedEncoding.Instances.Support
-
-import           Data.Proxy
-import           Data.Functor.Identity
-import           GHC.TypeLits
-
-import qualified Data.ByteString as B
-import qualified Data.ByteString.Lazy as BL
-import qualified Data.Text as T
-import qualified Data.Text.Lazy as TL
-import qualified Data.Text.Encoding as TE 
-import qualified Data.Text.Lazy.Encoding as TEL 
-
-import qualified Data.ByteString.Char8 as B8
-import qualified Data.ByteString.Lazy.Char8 as BL8
-
-import           Data.Char
-import           Data.TypedEncoding.Internal.Utils (explainBool)
-import           Data.TypedEncoding.Unsafe (withUnsafe)
-import           Control.Arrow
-
--- tst = encodeFAll . toEncoding () $ "Hello World" :: Either EncodeEx (Enc '["r-ASCII"] () T.Text)
--- tst2 = encodeFAll . toEncoding () $ "\194\160" :: Either EncodeEx (Enc '["r-ASCII"] () T.Text)
--- tst3 = encodeFAll . toEncoding () $ "\194\160" :: Either EncodeEx (Enc '["r-ASCII"] () B.ByteString)
-
------------------
--- Conversions --
------------------
-
-byteString2TextS :: Enc ("r-ASCII" ': ys) c B.ByteString -> Enc ("r-ASCII" ': ys) c T.Text 
-byteString2TextS = withUnsafe (fmap TE.decodeUtf8)
-
-byteString2TextL :: Enc ("r-ASCII" ': ys) c BL.ByteString -> Enc ("r-ASCII" ': ys) c TL.Text 
-byteString2TextL = withUnsafe (fmap TEL.decodeUtf8)
-
-text2ByteStringS :: Enc ("r-ASCII" ': ys) c T.Text -> Enc ("r-ASCII" ': ys) c B.ByteString 
-text2ByteStringS = withUnsafe (fmap TE.encodeUtf8)
-
-text2ByteStringL  :: Enc ("r-ASCII" ': ys) c TL.Text -> Enc ("r-ASCII" ': ys) c BL.ByteString 
-text2ByteStringL  = withUnsafe (fmap TEL.encodeUtf8)
-
-
--- | allow to treat ASCII encodings as UTF8 forgetting about B64 encoding
--- 
--- >>> let Right tstAscii = encodeFAll . toEncoding () $ "Hello World" :: Either EncodeEx (Enc '["r-ASCII"] () T.Text)
--- >>> displ (inject (Proxy :: Proxy "r-UTF8") tstAscii)
--- "MkEnc '[r-UTF8] () (Text Hello World)"
-instance Subset "r-ASCII" "r-UTF8" where
-
------------------
--- Encondings  --
------------------
-
-data NonAsciiChar = NonAsciiChar Char deriving (Eq, Show)
-
-prxyAscii = Proxy :: Proxy "r-ASCII"
-
-instance EncodeF (Either EncodeEx) (Enc xs c Char) (Enc ("r-ASCII" ': xs) c Char) where
-    encodeF = implEncodeF prxyAscii (\c -> explainBool NonAsciiChar (c, isAscii c))    
-instance Applicative f => DecodeF f (Enc ("r-ASCII" ': xs) c Char) (Enc xs c Char) where
-    decodeF = implTranP id 
-
-instance EncodeF (Either EncodeEx) (Enc xs c T.Text) (Enc ("r-ASCII" ': xs) c T.Text) where
-    encodeF = implEncodeF prxyAscii (encodeImpl T.partition T.head T.null)
-instance (RecreateErr f, Applicative f) => RecreateF f (Enc xs c T.Text) (Enc ("r-ASCII" ': xs) c T.Text) where
-    checkPrevF = implCheckPrevF (asRecreateErr prxyAscii . encodeImpl T.partition T.head T.null)
-instance Applicative f => DecodeF f (Enc ("r-ASCII" ': xs) c T.Text) (Enc xs c T.Text) where
-    decodeF = implTranP id 
-
-instance EncodeF (Either EncodeEx) (Enc xs c TL.Text) (Enc ("r-ASCII" ': xs) c TL.Text) where
-    encodeF = implEncodeF prxyAscii (encodeImpl TL.partition TL.head TL.null)
-instance (RecreateErr f, Applicative f) => RecreateF f (Enc xs c TL.Text) (Enc ("r-ASCII" ': xs) c TL.Text) where 
-    checkPrevF = implCheckPrevF (asRecreateErr prxyAscii . encodeImpl TL.partition TL.head TL.null)
-instance Applicative f => DecodeF f (Enc ("r-ASCII" ': xs) c TL.Text) (Enc xs c TL.Text) where
-    decodeF = implTranP id 
-
-instance EncodeF (Either EncodeEx) (Enc xs c B.ByteString) (Enc ("r-ASCII" ': xs) c B.ByteString) where
-    encodeF = implEncodeF prxyAscii (encodeImpl (\p -> B8.filter p &&& B8.filter (not . p)) B8.head B8.null)
-instance (RecreateErr f, Applicative f) => RecreateF f (Enc xs c B.ByteString) (Enc ("r-ASCII" ': xs) c B.ByteString) where
-    checkPrevF = implCheckPrevF (asRecreateErr prxyAscii . encodeImpl (\p -> B8.filter p &&& B8.filter (not . p)) B8.head B8.null)
-instance Applicative f => DecodeF f (Enc ("r-ASCII" ': xs) c B.ByteString) (Enc xs c B.ByteString) where
-    decodeF = implTranP id 
-
-instance EncodeF (Either EncodeEx) (Enc xs c BL.ByteString) (Enc ("r-ASCII" ': xs) c BL.ByteString) where
-    encodeF = implEncodeF prxyAscii (encodeImpl (\p -> BL8.filter p &&& BL8.filter (not . p)) BL8.head BL8.null)
-instance (RecreateErr f, Applicative f) => RecreateF f (Enc xs c BL.ByteString) (Enc ("r-ASCII" ': xs) c BL.ByteString) where
-    checkPrevF = implCheckPrevF (asRecreateErr prxyAscii . encodeImpl (\p -> BL8.filter p &&& BL8.filter (not . p)) BL8.head BL8.null)
-instance Applicative f => DecodeF f (Enc ("r-ASCII" ': xs) c BL.ByteString) (Enc xs c BL.ByteString) where
-    decodeF = implTranP id 
-
-encodeImpl :: 
-   ((Char -> Bool) -> a -> (a, a))
-   -> (a -> Char)
-   -> (a -> Bool)
-   -> a
-   -> Either NonAsciiChar a
-encodeImpl partitionf headf nullf t = 
-                 let (tascii, nonascii) = partitionf isAscii t 
-                 in if nullf nonascii 
-                    then Right tascii
-                    else Left . NonAsciiChar $ headf nonascii 
-
diff --git a/src/Data/TypedEncoding/Instances/Base64.hs b/src/Data/TypedEncoding/Instances/Base64.hs
deleted file mode 100644
--- a/src/Data/TypedEncoding/Instances/Base64.hs
+++ /dev/null
@@ -1,155 +0,0 @@
-{-# LANGUAGE DataKinds #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE TypeOperators #-}
-{-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE FlexibleContexts #-}
-
-
-module Data.TypedEncoding.Instances.Base64 where
-
-import           Data.TypedEncoding
-import           Data.TypedEncoding.Instances.Support
-
-import           Data.Proxy
-import           Data.Functor.Identity
-import           GHC.TypeLits
-
-import qualified Data.ByteString as B
-import qualified Data.ByteString.Lazy as BL
-import qualified Data.Text as T
-import qualified Data.Text.Lazy as TL
-import qualified Data.Text.Encoding as TE 
-import qualified Data.Text.Lazy.Encoding as TEL 
-
-import qualified Data.ByteString.Base64 as B64
-import qualified Data.ByteString.Base64.Lazy as BL64
-
-import qualified Data.ByteString.Base64.URL as B64URL
-import qualified Data.ByteString.Base64.URL.Lazy as BL64URL
-
--- $setup
--- >>> :set -XScopedTypeVariables -XKindSignatures -XMultiParamTypeClasses -XDataKinds -XPolyKinds -XPartialTypeSignatures -XFlexibleInstances
--- >>> import Test.QuickCheck
--- >>> import Test.QuickCheck.Instances.Text()
--- >>> import Test.QuickCheck.Instances.ByteString()
-
-
------------------
--- Conversions --
------------------
-
--- | Type-safer version of Byte-string to text conversion that prevent invalid UTF8 bytestrings
--- to be conversted to B64 encoded Text.
-byteString2TextS :: Enc ("enc-B64" ': "r-UTF8" ': ys) c B.ByteString -> Enc ("enc-B64" ': ys) c T.Text 
-byteString2TextS = withUnsafeCoerce (TE.decodeUtf8)
-
-byteString2TextL :: Enc ("enc-B64" ': "r-UTF8" ': ys) c BL.ByteString -> Enc ("enc-B64" ': ys) c TL.Text 
-byteString2TextL = withUnsafeCoerce (TEL.decodeUtf8)
-
--- | Converts encoded text to ByteString adding "r-UTF8" annotation.
--- The question is why "r-UTF8", not for example, "r-UTF16"?
--- No reason, there maybe a diffrent combinator for that in the future or one that accepts a proxy.
-text2ByteStringS :: Enc ("enc-B64" ': ys) c T.Text -> Enc ("enc-B64" ': "r-UTF8" ': ys) c B.ByteString 
-text2ByteStringS = withUnsafeCoerce (TE.encodeUtf8)
-
-text2ByteStringL  :: Enc ("enc-B64" ': ys) c TL.Text -> Enc ("enc-B64" ': "r-UTF8" ': ys) c BL.ByteString 
-text2ByteStringL  = withUnsafeCoerce (TEL.encodeUtf8)
-
-
--- | B64 encoded bytestring can be converted to Text as "enc-B64-nontext" preventing it from 
--- being B64-decoded directly to Text
-byteString2TextS' :: Enc ("enc-B64" ': ys) c B.ByteString -> Enc ("enc-B64-nontext" ': ys) c T.Text 
-byteString2TextS' = withUnsafeCoerce (TE.decodeUtf8)
-
-byteString2TextL' :: Enc ("enc-B64" ': ys) c BL.ByteString -> Enc ("enc-B64-nontext" ': ys) c TL.Text 
-byteString2TextL' = withUnsafeCoerce (TEL.decodeUtf8)
-
-text2ByteStringS' :: Enc ("enc-B64-nontext" ': ys) c T.Text -> Enc ("enc-B64" ': ys) c B.ByteString 
-text2ByteStringS' = withUnsafeCoerce (TE.encodeUtf8)
-
-text2ByteStringL'  :: Enc ("enc-B64-nontext" ': ys) c TL.Text -> Enc ("enc-B64" ': ys) c BL.ByteString 
-text2ByteStringL'  = withUnsafeCoerce (TEL.encodeUtf8)
-
-acceptLenientS :: Enc ("enc-B64-len" ': ys) c B.ByteString -> Enc ("enc-B64" ': ys) c B.ByteString 
-acceptLenientS = withUnsafeCoerce (B64.encode . B64.decodeLenient)
-
-acceptLenientL :: Enc ("enc-B64-len" ': ys) c BL.ByteString -> Enc ("enc-B64" ': ys) c BL.ByteString 
-acceptLenientL = withUnsafeCoerce (BL64.encode . BL64.decodeLenient)
-
--- | allow to treat B64 encodings as ASCII forgetting about B64 encoding
--- 
---
--- >>> let tstB64 = encodeAll . toEncoding () $ "Hello World" :: Enc '["enc-B64"] () B.ByteString
--- >>> displ (flattenAs (Proxy :: Proxy "r-ASCII") tstB64 :: Enc '["r-ASCII"] () B.ByteString)
--- "MkEnc '[r-ASCII] () (ByteString SGVsbG8gV29ybGQ=)"
-instance FlattenAs "enc-B64-nontext" "r-ASCII" where
-instance FlattenAs "enc-B64" "r-ASCII" where
-
-
------------------
--- Encodings   --
------------------
-
-prxyB64 = Proxy :: Proxy "enc-B64"
-
-instance Applicative f => EncodeF f (Enc xs c B.ByteString) (Enc ("enc-B64" ': xs) c B.ByteString) where
-    encodeF = implEncodeP B64.encode 
-        
--- | Effectful instance for corruption detection.
--- This protocol is used, for example, in emails. 
--- It is a well known encoding and hackers will have no problem 
--- making undetectable changes, but error handling at this stage
--- could verify that email was corrupted.
-instance (UnexpectedDecodeErr f, Applicative f) => DecodeF f (Enc ("enc-B64" ': xs) c B.ByteString) (Enc xs c B.ByteString) where
-    decodeF = implDecodeF (asUnexpected prxyB64 . B64.decode) 
-
-instance (RecreateErr f, Applicative f) => RecreateF f (Enc xs c B.ByteString) (Enc ("enc-B64" ': xs) c B.ByteString) where
-    checkPrevF = implCheckPrevF (asRecreateErr prxyB64 .  B64.decode) 
-
-instance Applicative f => RecreateF f (Enc xs c B.ByteString) (Enc ("enc-B64-len" ': xs) c B.ByteString) where
-    checkPrevF = implTranP (id) 
-
-instance Applicative f => EncodeF f  (Enc xs c BL.ByteString) (Enc ("enc-B64" ': xs) c BL.ByteString) where
-    encodeF = implEncodeP BL64.encode 
-
-instance (UnexpectedDecodeErr f, Applicative f) => DecodeF f  (Enc ("enc-B64" ': xs) c BL.ByteString) (Enc xs c BL.ByteString) where
-    decodeF = implDecodeF (asUnexpected prxyB64 . BL64.decode)
-
-instance (RecreateErr f, Applicative f) => RecreateF f (Enc xs c BL.ByteString) (Enc ("enc-B64" ': xs) c BL.ByteString) where
-    checkPrevF = implCheckPrevF (asRecreateErr prxyB64 .  BL64.decode) 
-
-instance Applicative f => RecreateF f (Enc xs c BL.ByteString) (Enc ("enc-B64-len" ': xs) c BL.ByteString) where
-    checkPrevF = implTranP (id) 
-
--- B64URL currently not supported
--- instance Applicative f => EncodeF f (Enc xs c B.ByteString) (Enc ("enc-B64URL" ': xs) c B.ByteString) where
---     encodeF = implEncodeP B64URL.encode 
--- instance DecodeF (Either String) (Enc ("enc-B64URL" ': xs) c B.ByteString) (Enc xs c B.ByteString) where
---     decodeF = implDecodeF B64URL.decode 
--- instance DecodeF Identity (Enc ("enc-B64URL" ': xs) c B.ByteString) (Enc xs c B.ByteString) where
---     decodeF = implTranP B64URL.decodeLenient 
-
--- instance Applicative f => EncodeF f (Enc xs c BL.ByteString) (Enc ("enc-B64URL" ': xs) c BL.ByteString) where
---     encodeF = implEncodeP BL64URL.encode 
--- instance DecodeF (Either String) (Enc ("enc-B64URL" ': xs) c BL.ByteString) (Enc xs c BL.ByteString) where
---     decodeF = implDecodeF BL64URL.decode 
--- instance DecodeF Identity (Enc ("enc-B64URL" ': xs) c BL.ByteString) (Enc xs c BL.ByteString) where
---     decodeF = implTranP BL64URL.decodeLenient 
-
-instance Applicative f => EncodeF f (Enc xs c T.Text) (Enc ("enc-B64" ': xs) c T.Text) where
-    encodeF = implEncodeP (TE.decodeUtf8 . B64.encode . TE.encodeUtf8)   
-
-instance (UnexpectedDecodeErr f, Applicative f) => DecodeF f (Enc ("enc-B64" ': xs) c T.Text) (Enc xs c T.Text) where
-    decodeF = implDecodeF (asUnexpected prxyB64 . fmap TE.decodeUtf8 . B64.decode . TE.encodeUtf8) 
-
-instance (RecreateErr f, Applicative f) => RecreateF f (Enc xs c T.Text) (Enc ("enc-B64" ': xs) c T.Text) where
-    checkPrevF = implCheckPrevF (asRecreateErr prxyB64 . fmap TE.decodeUtf8 .  B64.decode . TE.encodeUtf8) 
-
-instance Applicative f => EncodeF f (Enc xs c TL.Text) (Enc ("enc-B64" ': xs) c TL.Text) where
-    encodeF = implEncodeP (TEL.decodeUtf8 . BL64.encode . TEL.encodeUtf8)   
-
-instance (UnexpectedDecodeErr f, Applicative f) => DecodeF f (Enc ("enc-B64" ': xs) c TL.Text) (Enc xs c TL.Text) where
-    decodeF = implDecodeF (asUnexpected prxyB64 . fmap TEL.decodeUtf8 . BL64.decode . TEL.encodeUtf8) 
-
-instance (RecreateErr f, Applicative f) => RecreateF f (Enc xs c TL.Text) (Enc ("enc-B64" ': xs) c TL.Text) where
-    checkPrevF = implCheckPrevF (asRecreateErr prxyB64 . fmap TEL.decodeUtf8 .  BL64.decode . TEL.encodeUtf8) 
diff --git a/src/Data/TypedEncoding/Instances/Do/Sample.hs b/src/Data/TypedEncoding/Instances/Do/Sample.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/TypedEncoding/Instances/Do/Sample.hs
@@ -0,0 +1,58 @@
+
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications #-}
+
+-- | This module defines some sample "do-" encodings
+-- currently for example use only.
+module Data.TypedEncoding.Instances.Do.Sample where
+
+import qualified Data.Text as T
+import qualified Data.Text.Lazy as TL
+import qualified Data.ByteString as B
+-- import qualified Data.ByteString.Lazy as BL
+import           Data.Char
+
+import           Data.TypedEncoding.Instances.Support
+
+
+
+instance Applicative f => EncodeF f (Enc xs c T.Text) (Enc ("do-UPPER" ': xs) c T.Text) where
+    encodeF = implEncodeP T.toUpper
+instance (RecreateErr f, Applicative f) => RecreateF f (Enc xs c T.Text) (Enc ("do-UPPER" ': xs) c T.Text) where
+    checkPrevF = implCheckPrevF (asRecreateErr @"do-UPPER" . (\t -> 
+                                 let (g,b) = T.partition isUpper t
+                                 in if T.null b
+                                    then Right t
+                                    else Left $ "Found not upper case chars " ++ T.unpack b)
+                           )
+instance Applicative f => EncodeF f (Enc xs c TL.Text) (Enc ("do-UPPER" ': xs) c TL.Text) where
+    encodeF = implEncodeP TL.toUpper 
+
+instance Applicative f => EncodeF f (Enc xs c T.Text) (Enc ("do-lower" ': xs) c T.Text) where
+    encodeF = implEncodeP T.toLower    
+instance Applicative f => EncodeF f (Enc xs c TL.Text) (Enc ("do-lower" ': xs) c TL.Text) where
+    encodeF = implEncodeP TL.toLower 
+
+instance Applicative f => EncodeF f (Enc xs c T.Text) (Enc ("do-Title" ': xs) c T.Text) where
+    encodeF = implEncodeP T.toTitle   
+instance Applicative f => EncodeF f (Enc xs c TL.Text) (Enc ("do-Title" ': xs) c TL.Text) where
+    encodeF = implEncodeP TL.toTitle   
+
+instance Applicative f => EncodeF f (Enc xs c T.Text) (Enc ("do-reverse" ': xs) c T.Text) where
+    encodeF = implEncodeP T.reverse 
+instance Applicative f => EncodeF f (Enc xs c TL.Text) (Enc ("do-reverse" ': xs) c TL.Text) where
+    encodeF = implEncodeP TL.reverse    
+
+newtype SizeLimit = SizeLimit {unSizeLimit :: Int} deriving (Eq, Show)
+instance (HasA SizeLimit c, Applicative f) => EncodeF f (Enc xs c T.Text) (Enc ("do-size-limit" ': xs) c T.Text) where
+    encodeF =  implEncodeP' (T.take . unSizeLimit . has @ SizeLimit) 
+instance (HasA SizeLimit c, Applicative f) => EncodeF f (Enc xs c B.ByteString) (Enc ("do-size-limit" ': xs) c B.ByteString) where
+    encodeF =  implEncodeP' (B.take . unSizeLimit .  has @ SizeLimit) 
+
diff --git a/src/Data/TypedEncoding/Instances/Enc/Base64.hs b/src/Data/TypedEncoding/Instances/Enc/Base64.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/TypedEncoding/Instances/Enc/Base64.hs
@@ -0,0 +1,150 @@
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE TypeApplications #-}
+
+-- | Defines /Base64/ encoding
+module Data.TypedEncoding.Instances.Enc.Base64 where
+
+import           Data.TypedEncoding
+import           Data.TypedEncoding.Instances.Support
+
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Lazy as BL
+import qualified Data.Text as T
+import qualified Data.Text.Lazy as TL
+import qualified Data.Text.Encoding as TE 
+import qualified Data.Text.Lazy.Encoding as TEL 
+
+import qualified Data.ByteString.Base64 as B64
+import qualified Data.ByteString.Base64.Lazy as BL64
+
+-- import qualified Data.ByteString.Base64.URL as B64URL
+-- import qualified Data.ByteString.Base64.URL.Lazy as BL64URL
+
+-- $setup
+-- >>> :set -XScopedTypeVariables -XKindSignatures -XMultiParamTypeClasses -XDataKinds -XPolyKinds -XPartialTypeSignatures -XFlexibleInstances
+-- >>> import Test.QuickCheck
+-- >>> import Test.QuickCheck.Instances.Text()
+-- >>> import Test.QuickCheck.Instances.ByteString()
+
+-----------------
+-- Conversions --
+-----------------
+
+-- | Type-safer version of Byte-string to text conversion that prevent invalid UTF8 bytestrings
+-- to be conversted to B64 encoded Text.
+byteString2TextS :: Enc ("enc-B64" ': "r-UTF8" ': ys) c B.ByteString -> Enc ("enc-B64" ': ys) c T.Text 
+byteString2TextS = withUnsafeCoerce TE.decodeUtf8
+
+byteString2TextL :: Enc ("enc-B64" ': "r-UTF8" ': ys) c BL.ByteString -> Enc ("enc-B64" ': ys) c TL.Text 
+byteString2TextL = withUnsafeCoerce TEL.decodeUtf8
+
+-- | Converts encoded text to ByteString adding "r-UTF8" annotation.
+-- The question is why "r-UTF8", not for example, "r-UTF16"?
+-- No reason, there maybe a diffrent combinator for that in the future or one that accepts a proxy.
+text2ByteStringS :: Enc ("enc-B64" ': ys) c T.Text -> Enc ("enc-B64" ': "r-UTF8" ': ys) c B.ByteString 
+text2ByteStringS = withUnsafeCoerce TE.encodeUtf8
+
+text2ByteStringL  :: Enc ("enc-B64" ': ys) c TL.Text -> Enc ("enc-B64" ': "r-UTF8" ': ys) c BL.ByteString 
+text2ByteStringL  = withUnsafeCoerce TEL.encodeUtf8
+
+
+-- | B64 encoded bytestring can be converted to Text as "enc-B64-nontext" preventing it from 
+-- being B64-decoded directly to Text
+byteString2TextS' :: Enc ("enc-B64" ': ys) c B.ByteString -> Enc ("enc-B64-nontext" ': ys) c T.Text 
+byteString2TextS' = withUnsafeCoerce TE.decodeUtf8
+
+byteString2TextL' :: Enc ("enc-B64" ': ys) c BL.ByteString -> Enc ("enc-B64-nontext" ': ys) c TL.Text 
+byteString2TextL' = withUnsafeCoerce TEL.decodeUtf8
+
+text2ByteStringS' :: Enc ("enc-B64-nontext" ': ys) c T.Text -> Enc ("enc-B64" ': ys) c B.ByteString 
+text2ByteStringS' = withUnsafeCoerce TE.encodeUtf8
+
+text2ByteStringL'  :: Enc ("enc-B64-nontext" ': ys) c TL.Text -> Enc ("enc-B64" ': ys) c BL.ByteString 
+text2ByteStringL'  = withUnsafeCoerce TEL.encodeUtf8
+
+acceptLenientS :: Enc ("enc-B64-len" ': ys) c B.ByteString -> Enc ("enc-B64" ': ys) c B.ByteString 
+acceptLenientS = withUnsafeCoerce (B64.encode . B64.decodeLenient)
+
+acceptLenientL :: Enc ("enc-B64-len" ': ys) c BL.ByteString -> Enc ("enc-B64" ': ys) c BL.ByteString 
+acceptLenientL = withUnsafeCoerce (BL64.encode . BL64.decodeLenient)
+
+-- | allow to treat B64 encodings as ASCII forgetting about B64 encoding
+-- 
+--
+-- >>> let tstB64 = encodeAll . toEncoding () $ "Hello World" :: Enc '["enc-B64"] () B.ByteString
+-- >>> displ (flattenAs tstB64 :: Enc '["r-ASCII"] () B.ByteString)
+-- "MkEnc '[r-ASCII] () (ByteString SGVsbG8gV29ybGQ=)"
+instance FlattenAs "r-ASCII" "enc-B64-nontext" where
+instance FlattenAs "r-ASCII" "enc-B64" where
+
+
+-----------------
+-- Encodings   --
+-----------------
+
+
+instance Applicative f => EncodeF f (Enc xs c B.ByteString) (Enc ("enc-B64" ': xs) c B.ByteString) where
+    encodeF = implEncodeP B64.encode 
+        
+-- | Effectful instance for corruption detection.
+-- This protocol is used, for example, in emails. 
+-- It is a well known encoding and hackers will have no problem 
+-- making undetectable changes, but error handling at this stage
+-- could verify that email was corrupted.
+instance (UnexpectedDecodeErr f, Applicative f) => DecodeF f (Enc ("enc-B64" ': xs) c B.ByteString) (Enc xs c B.ByteString) where
+    decodeF = implDecodeF (asUnexpected @"enc-B64" . B64.decode) 
+
+instance (RecreateErr f, Applicative f) => RecreateF f (Enc xs c B.ByteString) (Enc ("enc-B64" ': xs) c B.ByteString) where
+    checkPrevF = implCheckPrevF (asRecreateErr @"enc-B64" .  B64.decode) 
+
+instance Applicative f => RecreateF f (Enc xs c B.ByteString) (Enc ("enc-B64-len" ': xs) c B.ByteString) where
+    checkPrevF = implTranP id
+
+instance Applicative f => EncodeF f  (Enc xs c BL.ByteString) (Enc ("enc-B64" ': xs) c BL.ByteString) where
+    encodeF = implEncodeP BL64.encode 
+
+instance (UnexpectedDecodeErr f, Applicative f) => DecodeF f  (Enc ("enc-B64" ': xs) c BL.ByteString) (Enc xs c BL.ByteString) where
+    decodeF = implDecodeF (asUnexpected @"enc-B64"  . BL64.decode)
+
+instance (RecreateErr f, Applicative f) => RecreateF f (Enc xs c BL.ByteString) (Enc ("enc-B64" ': xs) c BL.ByteString) where
+    checkPrevF = implCheckPrevF (asRecreateErr @"enc-B64" .  BL64.decode) 
+
+instance Applicative f => RecreateF f (Enc xs c BL.ByteString) (Enc ("enc-B64-len" ': xs) c BL.ByteString) where
+    checkPrevF = implTranP id
+
+-- B64URL currently not supported
+-- instance Applicative f => EncodeF f (Enc xs c B.ByteString) (Enc ("enc-B64URL" ': xs) c B.ByteString) where
+--     encodeF = implEncodeP B64URL.encode 
+-- instance DecodeF (Either String) (Enc ("enc-B64URL" ': xs) c B.ByteString) (Enc xs c B.ByteString) where
+--     decodeF = implDecodeF B64URL.decode 
+-- instance DecodeF Identity (Enc ("enc-B64URL" ': xs) c B.ByteString) (Enc xs c B.ByteString) where
+--     decodeF = implTranP B64URL.decodeLenient 
+
+-- instance Applicative f => EncodeF f (Enc xs c BL.ByteString) (Enc ("enc-B64URL" ': xs) c BL.ByteString) where
+--     encodeF = implEncodeP BL64URL.encode 
+-- instance DecodeF (Either String) (Enc ("enc-B64URL" ': xs) c BL.ByteString) (Enc xs c BL.ByteString) where
+--     decodeF = implDecodeF BL64URL.decode 
+-- instance DecodeF Identity (Enc ("enc-B64URL" ': xs) c BL.ByteString) (Enc xs c BL.ByteString) where
+--     decodeF = implTranP BL64URL.decodeLenient 
+
+instance Applicative f => EncodeF f (Enc xs c T.Text) (Enc ("enc-B64" ': xs) c T.Text) where
+    encodeF = implEncodeP (TE.decodeUtf8 . B64.encode . TE.encodeUtf8)   
+
+instance (UnexpectedDecodeErr f, Applicative f) => DecodeF f (Enc ("enc-B64" ': xs) c T.Text) (Enc xs c T.Text) where
+    decodeF = implDecodeF (asUnexpected @"enc-B64"  . fmap TE.decodeUtf8 . B64.decode . TE.encodeUtf8) 
+
+instance (RecreateErr f, Applicative f) => RecreateF f (Enc xs c T.Text) (Enc ("enc-B64" ': xs) c T.Text) where
+    checkPrevF = implCheckPrevF (asRecreateErr @"enc-B64" . fmap TE.decodeUtf8 .  B64.decode . TE.encodeUtf8) 
+
+instance Applicative f => EncodeF f (Enc xs c TL.Text) (Enc ("enc-B64" ': xs) c TL.Text) where
+    encodeF = implEncodeP (TEL.decodeUtf8 . BL64.encode . TEL.encodeUtf8)   
+
+instance (UnexpectedDecodeErr f, Applicative f) => DecodeF f (Enc ("enc-B64" ': xs) c TL.Text) (Enc xs c TL.Text) where
+    decodeF = implDecodeF (asUnexpected @"enc-B64"  . fmap TEL.decodeUtf8 . BL64.decode . TEL.encodeUtf8) 
+
+instance (RecreateErr f, Applicative f) => RecreateF f (Enc xs c TL.Text) (Enc ("enc-B64" ': xs) c TL.Text) where
+    checkPrevF = implCheckPrevF (asRecreateErr @"enc-B64" . fmap TEL.decodeUtf8 .  BL64.decode . TEL.encodeUtf8) 
diff --git a/src/Data/TypedEncoding/Instances/Encode/Sample.hs b/src/Data/TypedEncoding/Instances/Encode/Sample.hs
deleted file mode 100644
--- a/src/Data/TypedEncoding/Instances/Encode/Sample.hs
+++ /dev/null
@@ -1,59 +0,0 @@
-
-{-# LANGUAGE DataKinds #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE TypeOperators #-}
-{-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE UndecidableInstances #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-
--- | This module defines some sample "do-" encodings
--- currently for example use only.
-module Data.TypedEncoding.Instances.Encode.Sample where
-
-import qualified Data.Text as T
-import qualified Data.Text.Lazy as TL
-import qualified Data.ByteString as B
--- import qualified Data.ByteString.Lazy as BL
-
-import           Data.TypedEncoding.Instances.Support
-
-import           Data.Proxy
-import           GHC.TypeLits
-import           Data.Char
-
-
-instance Applicative f => EncodeF f (Enc xs c T.Text) (Enc ("do-UPPER" ': xs) c T.Text) where
-    encodeF = implEncodeP T.toUpper
-instance (RecreateErr f, Applicative f) => RecreateF f (Enc xs c T.Text) (Enc ("do-UPPER" ': xs) c T.Text) where
-    checkPrevF = implCheckPrevF (asRecreateErr (Proxy :: Proxy "do-UPPER") . (\t -> 
-                                 let (g,b) = T.partition isUpper t
-                                 in if T.null b
-                                    then Right t
-                                    else Left $ "Found not upper case chars " ++ T.unpack b)
-                           )
-instance Applicative f => EncodeF f (Enc xs c TL.Text) (Enc ("do-UPPER" ': xs) c TL.Text) where
-    encodeF = implEncodeP TL.toUpper 
-
-instance Applicative f => EncodeF f (Enc xs c T.Text) (Enc ("do-lower" ': xs) c T.Text) where
-    encodeF = implEncodeP T.toLower    
-instance Applicative f => EncodeF f (Enc xs c TL.Text) (Enc ("do-lower" ': xs) c TL.Text) where
-    encodeF = implEncodeP TL.toLower 
-
-instance Applicative f => EncodeF f (Enc xs c T.Text) (Enc ("do-Title" ': xs) c T.Text) where
-    encodeF = implEncodeP T.toTitle   
-instance Applicative f => EncodeF f (Enc xs c TL.Text) (Enc ("do-Title" ': xs) c TL.Text) where
-    encodeF = implEncodeP TL.toTitle   
-
-instance Applicative f => EncodeF f (Enc xs c T.Text) (Enc ("do-reverse" ': xs) c T.Text) where
-    encodeF = implEncodeP T.reverse 
-instance Applicative f => EncodeF f (Enc xs c TL.Text) (Enc ("do-reverse" ': xs) c TL.Text) where
-    encodeF = implEncodeP TL.reverse    
-
-newtype SizeLimit = SizeLimit {unSizeLimit :: Int} deriving (Eq, Show)
-instance (HasA c SizeLimit, Applicative f) => EncodeF f (Enc xs c T.Text) (Enc ("do-size-limit" ': xs) c T.Text) where
-    encodeF =  implEncodeP' (T.take . unSizeLimit . has (Proxy :: Proxy SizeLimit)) 
-instance (HasA c SizeLimit, Applicative f) => EncodeF f (Enc xs c B.ByteString) (Enc ("do-size-limit" ': xs) c B.ByteString) where
-    encodeF =  implEncodeP' (B.take . unSizeLimit . has (Proxy :: Proxy SizeLimit)) 
-
diff --git a/src/Data/TypedEncoding/Instances/Restriction/ASCII.hs b/src/Data/TypedEncoding/Instances/Restriction/ASCII.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/TypedEncoding/Instances/Restriction/ASCII.hs
@@ -0,0 +1,119 @@
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE TypeApplications #-}
+
+-- | Strings can move to 'Enc "r-ASCII' only if they contain only ascii characters.
+-- they always decode back
+-- >>> :set -XOverloadedStrings -XMultiParamTypeClasses -XDataKinds
+-- >>> encodeFAll . toEncoding () $ "Hello World" :: Either EncodeEx (Enc '["r-ASCII"] () T.Text)
+-- Right (MkEnc Proxy () "Hello World")
+--
+-- >>> encodeFAll . toEncoding () $ "\194\160" :: Either EncodeEx (Enc '["r-ASCII"] () T.Text)
+-- Left (EncodeEx "r-ASCII" (NonAsciiChar '\194'))
+module Data.TypedEncoding.Instances.Restriction.ASCII where
+
+import           Data.TypedEncoding.Instances.Support
+
+import           Data.Proxy
+
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Lazy as BL
+import qualified Data.Text as T
+import qualified Data.Text.Lazy as TL
+import qualified Data.Text.Encoding as TE 
+import qualified Data.Text.Lazy.Encoding as TEL 
+
+import qualified Data.ByteString.Char8 as B8
+import qualified Data.ByteString.Lazy.Char8 as BL8
+
+import           Data.Char
+import           Data.TypedEncoding.Internal.Util (explainBool)
+import           Data.TypedEncoding.Unsafe (withUnsafe)
+import           Control.Arrow
+
+-- $setup
+-- >>> :set -XDataKinds -XTypeApplications
+
+-----------------
+-- Conversions --
+-----------------
+
+byteString2TextS :: Enc ("r-ASCII" ': ys) c B.ByteString -> Enc ("r-ASCII" ': ys) c T.Text 
+byteString2TextS = withUnsafe (fmap TE.decodeUtf8)
+
+byteString2TextL :: Enc ("r-ASCII" ': ys) c BL.ByteString -> Enc ("r-ASCII" ': ys) c TL.Text 
+byteString2TextL = withUnsafe (fmap TEL.decodeUtf8)
+
+text2ByteStringS :: Enc ("r-ASCII" ': ys) c T.Text -> Enc ("r-ASCII" ': ys) c B.ByteString 
+text2ByteStringS = withUnsafe (fmap TE.encodeUtf8)
+
+text2ByteStringL  :: Enc ("r-ASCII" ': ys) c TL.Text -> Enc ("r-ASCII" ': ys) c BL.ByteString 
+text2ByteStringL  = withUnsafe (fmap TEL.encodeUtf8)
+
+
+-- | allow to treat ASCII encodings as UTF8 forgetting about B64 encoding
+-- 
+-- >>> let Right tstAscii = encodeFAll . toEncoding () $ "Hello World" :: Either EncodeEx (Enc '["r-ASCII"] () T.Text)
+-- >>> displ (inject @ "r-UTF8" tstAscii)
+-- "MkEnc '[r-UTF8] () (Text Hello World)"
+instance Superset "r-UTF8" "r-ASCII" where
+
+-----------------
+-- Encondings  --
+-----------------
+
+newtype NonAsciiChar = NonAsciiChar Char deriving (Eq, Show)
+
+prxyAscii = Proxy :: Proxy "r-ASCII"
+
+instance EncodeF (Either EncodeEx) (Enc xs c Char) (Enc ("r-ASCII" ': xs) c Char) where
+    encodeF = implEncodeF_ prxyAscii (\c -> explainBool NonAsciiChar (c, isAscii c))    
+instance Applicative f => DecodeF f (Enc ("r-ASCII" ': xs) c Char) (Enc xs c Char) where
+    decodeF = implTranP id 
+
+instance EncodeF (Either EncodeEx) (Enc xs c T.Text) (Enc ("r-ASCII" ': xs) c T.Text) where
+    encodeF = implEncodeF_ prxyAscii (encodeImpl T.partition T.head T.null)
+instance (RecreateErr f, Applicative f) => RecreateF f (Enc xs c T.Text) (Enc ("r-ASCII" ': xs) c T.Text) where
+    checkPrevF = implCheckPrevF (asRecreateErr @"r-ASCII" . encodeImpl T.partition T.head T.null)
+instance Applicative f => DecodeF f (Enc ("r-ASCII" ': xs) c T.Text) (Enc xs c T.Text) where
+    decodeF = implTranP id 
+
+instance EncodeF (Either EncodeEx) (Enc xs c TL.Text) (Enc ("r-ASCII" ': xs) c TL.Text) where
+    encodeF = implEncodeF_ prxyAscii (encodeImpl TL.partition TL.head TL.null)
+instance (RecreateErr f, Applicative f) => RecreateF f (Enc xs c TL.Text) (Enc ("r-ASCII" ': xs) c TL.Text) where 
+    checkPrevF = implCheckPrevF (asRecreateErr @"r-ASCII" . encodeImpl TL.partition TL.head TL.null)
+instance Applicative f => DecodeF f (Enc ("r-ASCII" ': xs) c TL.Text) (Enc xs c TL.Text) where
+    decodeF = implTranP id 
+
+instance EncodeF (Either EncodeEx) (Enc xs c B.ByteString) (Enc ("r-ASCII" ': xs) c B.ByteString) where
+    encodeF = implEncodeF_ prxyAscii (encodeImpl (\p -> B8.filter p &&& B8.filter (not . p)) B8.head B8.null)
+instance (RecreateErr f, Applicative f) => RecreateF f (Enc xs c B.ByteString) (Enc ("r-ASCII" ': xs) c B.ByteString) where
+    checkPrevF = implCheckPrevF (asRecreateErr @"r-ASCII" . encodeImpl (\p -> B8.filter p &&& B8.filter (not . p)) B8.head B8.null)
+instance Applicative f => DecodeF f (Enc ("r-ASCII" ': xs) c B.ByteString) (Enc xs c B.ByteString) where
+    decodeF = implTranP id 
+
+instance EncodeF (Either EncodeEx) (Enc xs c BL.ByteString) (Enc ("r-ASCII" ': xs) c BL.ByteString) where
+    encodeF = implEncodeF_ prxyAscii (encodeImpl (\p -> BL8.filter p &&& BL8.filter (not . p)) BL8.head BL8.null)
+instance (RecreateErr f, Applicative f) => RecreateF f (Enc xs c BL.ByteString) (Enc ("r-ASCII" ': xs) c BL.ByteString) where
+    checkPrevF = implCheckPrevF (asRecreateErr @"r-ASCII" . encodeImpl (\p -> BL8.filter p &&& BL8.filter (not . p)) BL8.head BL8.null)
+instance Applicative f => DecodeF f (Enc ("r-ASCII" ': xs) c BL.ByteString) (Enc xs c BL.ByteString) where
+    decodeF = implTranP id 
+
+encodeImpl :: 
+   ((Char -> Bool) -> a -> (a, a))
+   -> (a -> Char)
+   -> (a -> Bool)
+   -> a
+   -> Either NonAsciiChar a
+encodeImpl partitionf headf nullf t = 
+                 let (tascii, nonascii) = partitionf isAscii t 
+                 in if nullf nonascii 
+                    then Right tascii
+                    else Left . NonAsciiChar $ headf nonascii 
+
+-- tst = encodeFAll . toEncoding () $ "Hello World" :: Either EncodeEx (Enc '["r-ASCII"] () T.Text)
+-- tst2 = encodeFAll . toEncoding () $ "\194\160" :: Either EncodeEx (Enc '["r-ASCII"] () T.Text)
+-- tst3 = encodeFAll . toEncoding () $ "\194\160" :: Either EncodeEx (Enc '["r-ASCII"] () B.ByteString)
diff --git a/src/Data/TypedEncoding/Instances/Restriction/Common.hs b/src/Data/TypedEncoding/Instances/Restriction/Common.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/TypedEncoding/Instances/Restriction/Common.hs
@@ -0,0 +1,40 @@
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE TypeApplications #-}
+{-# LANGUAGE AllowAmbiguousTypes #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+-- | Common /restriction/ "r-" instances
+module Data.TypedEncoding.Instances.Restriction.Common where
+
+import           Data.Word
+import           Data.String
+
+-- import qualified Data.ByteString as B
+-- import qualified Data.ByteString.Lazy as BL
+-- import qualified Data.Text as T
+-- import qualified Data.Text.Lazy as TL
+
+import           Data.TypedEncoding.Internal.Class.IsStringR
+import           Data.TypedEncoding.Internal.Instances.Combinators
+import           Data.TypedEncoding.Instances.Support
+
+-- $setup
+-- >>> import qualified Data.Text as T
+
+
+instance (IsStringR str, IsString str) =>  EncodeF (Either EncodeEx) (Enc xs c str) (Enc ("r-Word8-decimal" ': xs) c str) where
+    encodeF = implEncodeF @"r-Word8-decimal" (verifyWithRead @Word8 "Word8-decimal")
+instance (IsStringR str, IsString str, RecreateErr f, Applicative f) => RecreateF f (Enc xs c str) (Enc ("r-Word8-decimal" ': xs) c str) where
+    checkPrevF = implCheckPrevF (asRecreateErr @"r-Word8-decimal" . verifyWithRead @Word8 "Word8-decimal")
+instance (IsStringR str, IsString str, Applicative f) => DecodeF f (Enc ("r-Word8-decimal" ': xs) c str) (Enc xs c str) where
+    decodeF = implTranP id 
+
+
+
+-- tst :: T.Text
+-- tst = fromString $ show $ (fromString $ "123" :: T.Text)
diff --git a/src/Data/TypedEncoding/Instances/Restriction/UTF8.hs b/src/Data/TypedEncoding/Instances/Restriction/UTF8.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/TypedEncoding/Instances/Restriction/UTF8.hs
@@ -0,0 +1,130 @@
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE KindSignatures #-}
+{-# LANGUAGE PolyKinds #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE PartialTypeSignatures #-}
+{-# LANGUAGE TypeApplications #-}
+
+-- | 'UTF-8' encoding
+module Data.TypedEncoding.Instances.Restriction.UTF8 where
+
+import           Data.TypedEncoding.Instances.Support
+
+import           Data.Proxy
+import           GHC.TypeLits
+
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Lazy as BL
+import qualified Data.Text as T
+import qualified Data.Text.Lazy as TL
+import qualified Data.Text.Encoding as TE 
+import qualified Data.Text.Lazy.Encoding as TEL 
+
+-- import qualified Data.ByteString.Char8 as B8
+-- import qualified Data.ByteString.Lazy.Char8 as BL8
+
+import           Data.Either
+
+-- $setup
+-- >>> :set -XScopedTypeVariables -XKindSignatures -XMultiParamTypeClasses -XDataKinds -XPolyKinds -XPartialTypeSignatures -XFlexibleInstances -XTypeApplications
+-- >>> import Test.QuickCheck
+-- >>> import Test.QuickCheck.Instances.Text()
+-- >>> import Test.QuickCheck.Instances.ByteString()
+-- >>> import Data.TypedEncoding.Internal.Util (proxiedId)
+-- >>> let prxyArb = Proxy :: Proxy (Either EncodeEx (Enc '["r-UTF8"] () B.ByteString))
+-- >>> :{
+-- >>> instance Arbitrary (Enc '["r-UTF8"] () B.ByteString) where 
+--      arbitrary =  fmap (fromRight (emptyUTF8B ())) 
+--                   . flip suchThat isRight 
+--                   . fmap (proxiedId prxyArb . encodeFAll . toEncoding ()) $ arbitrary 
+-- :}
+
+-- | empty string is valid utf8
+emptyUTF8B :: c -> Enc '["r-UTF8"] c B.ByteString
+emptyUTF8B c = unsafeSetPayload c ""   
+
+-----------------
+-- Conversions --
+-----------------
+
+-- Right tst = encodeFAll . toEncoding () $ "Hello World" :: Either EncodeEx (Enc '["r-UTF8"] () B.ByteString)
+-- tstTxt = byteString2TextS tst
+
+-- | Type-safer version of @Data.Text.Encoding.encodeUtf8@
+--
+-- >>> displ $ text2ByteStringS $ toEncoding () ("text" :: T.Text)
+-- "MkEnc '[r-UTF8] () (ByteString text)"
+text2ByteStringS :: Enc ys c T.Text -> Enc ("r-UTF8" ': ys) c B.ByteString
+text2ByteStringS = withUnsafeCoerce TE.encodeUtf8
+
+-- | Type-safer version of Data.Text.Encoding.decodeUtf8
+--
+-- >>> let Right tst = encodeFAll . toEncoding () $ "Hello World" :: Either EncodeEx (Enc '["r-UTF8"] () B.ByteString)
+-- >>> displ $ byteString2TextS tst
+-- "MkEnc '[] () (Text Hello World)"
+byteString2TextS :: Enc ("r-UTF8" ': ys) c B.ByteString -> Enc ys c T.Text 
+byteString2TextS = withUnsafeCoerce TE.decodeUtf8
+
+-- | Identity property "byteString2TextS . text2ByteStringS == id"
+-- prop> \t -> t == (fromEncoding . txtBsSIdProp (Proxy :: Proxy '[]) . toEncoding () $ t)
+txtBsSIdProp :: Proxy (ys :: [Symbol]) -> Enc ys c T.Text -> Enc ys c T.Text
+txtBsSIdProp _ = byteString2TextS . text2ByteStringS 
+
+-- | Identity property "text2ByteStringS . byteString2TextS == id".
+--
+-- prop> \(t :: Enc '["r-UTF8"] () B.ByteString) -> t == (bsTxtIdProp (Proxy :: Proxy '[]) $ t)
+bsTxtIdProp :: Proxy (ys :: [Symbol]) -> Enc ("r-UTF8" ': ys) c B.ByteString -> Enc ("r-UTF8" ': ys) c B.ByteString
+bsTxtIdProp _ = text2ByteStringS . byteString2TextS
+
+text2ByteStringL :: Enc ys c TL.Text -> Enc ("r-UTF8" ': ys) c BL.ByteString
+text2ByteStringL = withUnsafeCoerce TEL.encodeUtf8
+
+byteString2TextL :: Enc ("r-UTF8" ': ys) c BL.ByteString -> Enc ys c TL.Text 
+byteString2TextL = withUnsafeCoerce TEL.decodeUtf8
+
+-----------------
+-- Encondings  --
+-----------------
+
+prxyUtf8 = Proxy :: Proxy "r-UTF8"
+
+-- TODO these are quick and dirty
+
+-- | UTF8 encodings are defined for ByteString only as that would not make much sense for Text
+--
+-- >>> encodeFAll . toEncoding () $ "\xc3\xb1" :: Either EncodeEx (Enc '["r-UTF8"] () B.ByteString)
+-- Right (MkEnc Proxy () "\195\177")
+-- >>> encodeFAll . toEncoding () $ "\xc3\x28" :: Either EncodeEx (Enc '["r-UTF8"] () B.ByteString)
+-- Left (EncodeEx "r-UTF8" (Cannot decode byte '\xc3': Data.Text.Internal.Encoding.decodeUtf8: Invalid UTF-8 stream))
+--
+-- Following test uses 'verEncoding' helper that checks that bytes are encoded as Right iff they are valid UTF8 bytes
+--
+-- prop> \(b :: B.ByteString) -> verEncoding b (fmap (fromEncoding . decodeAll . proxiedId (Proxy :: Proxy (Enc '["r-UTF8"] _ _))) . (encodeFAll :: _ -> Either EncodeEx _). toEncoding () $ b)
+
+instance EncodeF (Either EncodeEx) (Enc xs c B.ByteString) (Enc ("r-UTF8" ': xs) c B.ByteString) where
+    encodeF = implEncodeF_ prxyUtf8 (fmap TE.encodeUtf8 . TE.decodeUtf8')
+instance (RecreateErr f, Applicative f) => RecreateF f (Enc xs c B.ByteString) (Enc ("r-UTF8" ': xs) c B.ByteString) where
+    checkPrevF = implCheckPrevF (asRecreateErr @"r-UTF8" . fmap TE.encodeUtf8 . TE.decodeUtf8')
+instance Applicative f => DecodeF f (Enc ("r-UTF8" ': xs) c B.ByteString) (Enc xs c B.ByteString) where
+    decodeF = implTranP id 
+
+instance EncodeF (Either EncodeEx) (Enc xs c BL.ByteString) (Enc ("r-UTF8" ': xs) c BL.ByteString) where
+    encodeF = implEncodeF_ prxyUtf8 (fmap TEL.encodeUtf8 . TEL.decodeUtf8')
+instance (RecreateErr f, Applicative f) => RecreateF f (Enc xs c BL.ByteString) (Enc ("r-UTF8" ': xs) c BL.ByteString) where
+    checkPrevF = implCheckPrevF (asRecreateErr @"r-UTF8" . fmap TEL.encodeUtf8 . TEL.decodeUtf8')
+instance Applicative f => DecodeF f (Enc ("r-UTF8" ': xs) c BL.ByteString) (Enc xs c BL.ByteString) where
+    decodeF = implTranP id 
+
+--- Utilities ---
+
+-- | helper function checks that given ByteString, 
+-- if is encoded as Left is must be not Utf8 decodable
+-- is is encoded as Right is must be Utf8 encodable 
+verEncoding :: B.ByteString -> Either err B.ByteString -> Bool
+verEncoding bs (Left _) = isLeft . TE.decodeUtf8' $ bs
+verEncoding bs (Right _) = isRight . TE.decodeUtf8' $ bs
diff --git a/src/Data/TypedEncoding/Instances/Support.hs b/src/Data/TypedEncoding/Instances/Support.hs
--- a/src/Data/TypedEncoding/Instances/Support.hs
+++ b/src/Data/TypedEncoding/Instances/Support.hs
@@ -1,11 +1,16 @@
 
--- | Exports for encoding instance creation
+-- | Exports for instance creation.
+-- 
+-- Contains typical things needed when implementing
+-- encoding, decoding, recreate, or type to string conversions.
 module Data.TypedEncoding.Instances.Support (
     -- * Types
     module Data.TypedEncoding.Internal.Types
     -- * Classes
     , module Data.TypedEncoding.Internal.Class
+    -- * Combinators
+    , module Data.TypedEncoding.Internal.Instances.Combinators
    ) where
 import           Data.TypedEncoding.Internal.Types
 import           Data.TypedEncoding.Internal.Class 
-
+import           Data.TypedEncoding.Internal.Instances.Combinators 
diff --git a/src/Data/TypedEncoding/Instances/ToEncString/Common.hs b/src/Data/TypedEncoding/Instances/ToEncString/Common.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/TypedEncoding/Instances/ToEncString/Common.hs
@@ -0,0 +1,43 @@
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE PolyKinds #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeApplications #-}
+{-# LANGUAGE AllowAmbiguousTypes #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- | Common 'ToEncString' and 'FromEncString' instances.
+module Data.TypedEncoding.Instances.ToEncString.Common where
+
+
+-- import qualified Data.Text as T
+-- import qualified Data.Text.Lazy as TL
+-- import qualified Data.ByteString as B
+-- -- import qualified Data.ByteString.Lazy as BL
+
+import           Data.TypedEncoding.Instances.Support
+import           Data.TypedEncoding.Internal.Class.IsStringR
+
+import           Data.String
+import           Data.Proxy
+import           Data.Word
+import           Text.Read
+import           Data.Functor.Identity
+
+
+instance IsString str => ToEncString "r-()" str Identity () where
+    toEncStringF _ = Identity $ MkEnc Proxy () (fromString "()")
+
+instance IsString str => ToEncString "r-Int-decimal" str Identity Int where
+    toEncStringF i = Identity $ MkEnc Proxy () (fromString . show $ i)
+
+instance IsString str => ToEncString "r-Word8-decimal" str Identity Word8 where
+    toEncStringF i = Identity $ MkEnc Proxy () (fromString . show $ i)
+
+instance (IsStringR str, UnexpectedDecodeErr f, Applicative f) => FromEncString Word8 f str "r-Word8-decimal" where
+    fromEncStringF  = asUnexpected @ "r-Word8-decimal" . readEither . toString . getPayload
diff --git a/src/Data/TypedEncoding/Instances/UTF8.hs b/src/Data/TypedEncoding/Instances/UTF8.hs
deleted file mode 100644
--- a/src/Data/TypedEncoding/Instances/UTF8.hs
+++ /dev/null
@@ -1,136 +0,0 @@
-{-# LANGUAGE DataKinds #-}
-{-# LANGUAGE KindSignatures #-}
-{-# LANGUAGE PolyKinds #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE TypeOperators #-}
-{-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE PartialTypeSignatures #-}
--- | 
-module Data.TypedEncoding.Instances.UTF8 where
-
-import           Data.TypedEncoding.Instances.Support
--- import           Data.TypedEncoding.Internal.Utils (proxiedId)
-import           Data.TypedEncoding.Unsafe (withUnsafe)
-
-import           Data.Proxy
-import           Data.Functor.Identity
-import           GHC.TypeLits
-
-import qualified Data.ByteString as B
-import qualified Data.ByteString.Lazy as BL
-import qualified Data.Text as T
-import qualified Data.Text.Lazy as TL
-import qualified Data.Text.Encoding as TE 
-import qualified Data.Text.Lazy.Encoding as TEL 
-
-import qualified Data.ByteString.Char8 as B8
-import qualified Data.ByteString.Lazy.Char8 as BL8
-
-import           GHC.TypeLits
-import           Data.Char
-import           Control.Arrow
-import           Data.Text.Encoding.Error (UnicodeException)
-
-import           Data.Either
-
--- $setup
--- >>> :set -XScopedTypeVariables -XKindSignatures -XMultiParamTypeClasses -XDataKinds -XPolyKinds -XPartialTypeSignatures -XFlexibleInstances
--- >>> import Test.QuickCheck
--- >>> import Test.QuickCheck.Instances.Text()
--- >>> import Test.QuickCheck.Instances.ByteString()
--- >>> import Data.TypedEncoding.Internal.Utils (proxiedId)
--- >>> let prxyArb = Proxy :: Proxy (Either EncodeEx (Enc '["r-UTF8"] () B.ByteString))
--- >>> :{
--- >>> instance Arbitrary (Enc '["r-UTF8"] () B.ByteString) where 
---      arbitrary =  fmap (fromRight (emptyUTF8B ())) 
---                   . flip suchThat isRight 
---                   . fmap (proxiedId prxyArb . encodeFAll . toEncoding ()) $ arbitrary 
--- :}
-
--- | empty string is valid utf8
-emptyUTF8B :: c -> Enc '["r-UTF8"] c B.ByteString
-emptyUTF8B c = unsafeSetPayload c ""   
-
------------------
--- Conversions --
------------------
-
--- Right tst = encodeFAll . toEncoding () $ "Hello World" :: Either EncodeEx (Enc '["r-UTF8"] () B.ByteString)
--- tstTxt = byteString2TextS tst
-
--- | Type-safer version of @Data.Text.Encoding.encodeUtf8@
---
--- >>> displ $ text2ByteStringS $ toEncoding () ("text" :: T.Text)
--- "MkEnc '[r-UTF8] () (ByteString text)"
-text2ByteStringS :: Enc ys c T.Text -> Enc ("r-UTF8" ': ys) c B.ByteString
-text2ByteStringS = withUnsafeCoerce TE.encodeUtf8
-
--- | Type-safer version of Data.Text.Encoding.decodeUtf8
---
--- >>> let Right tst = encodeFAll . toEncoding () $ "Hello World" :: Either EncodeEx (Enc '["r-UTF8"] () B.ByteString)
--- >>> displ $ byteString2TextS tst
--- "MkEnc '[] () (Text Hello World)"
-byteString2TextS :: Enc ("r-UTF8" ': ys) c B.ByteString -> Enc ys c T.Text 
-byteString2TextS = withUnsafeCoerce TE.decodeUtf8
-
--- | Identity property "byteString2TextS . text2ByteStringS == id"
--- prop> \t -> t == (fromEncoding . txtBsSIdProp (Proxy :: Proxy '[]) . toEncoding () $ t)
-txtBsSIdProp :: Proxy (ys :: [Symbol]) -> Enc ys c T.Text -> Enc ys c T.Text
-txtBsSIdProp _ = byteString2TextS . text2ByteStringS 
-
--- | Identity property "text2ByteStringS . byteString2TextS == id".
---
--- prop> \(t :: Enc '["r-UTF8"] () B.ByteString) -> t == (bsTxtIdProp (Proxy :: Proxy '[]) $ t)
-bsTxtIdProp :: Proxy (ys :: [Symbol]) -> Enc ("r-UTF8" ': ys) c B.ByteString -> Enc ("r-UTF8" ': ys) c B.ByteString
-bsTxtIdProp _ = text2ByteStringS . byteString2TextS
-
-text2ByteStringL :: Enc ys c TL.Text -> Enc ("r-UTF8" ': ys) c BL.ByteString
-text2ByteStringL = withUnsafeCoerce TEL.encodeUtf8
-
-byteString2TextL :: Enc ("r-UTF8" ': ys) c BL.ByteString -> Enc ys c TL.Text 
-byteString2TextL = withUnsafeCoerce TEL.decodeUtf8
-
------------------
--- Encondings  --
------------------
-
-prxyUtf8 = Proxy :: Proxy "r-UTF8"
-
--- TODO these are quick and dirty
-
--- | UTF8 encodings are defined for ByteString only as that would not make much sense for Text
---
--- >>> encodeFAll . toEncoding () $ "\xc3\xb1" :: Either EncodeEx (Enc '["r-UTF8"] () B.ByteString)
--- Right (MkEnc Proxy () "\195\177")
--- >>> encodeFAll . toEncoding () $ "\xc3\x28" :: Either EncodeEx (Enc '["r-UTF8"] () B.ByteString)
--- Left (EncodeEx "r-UTF8" (Cannot decode byte '\xc3': Data.Text.Internal.Encoding.decodeUtf8: Invalid UTF-8 stream))
---
--- Following test uses 'verEncoding' helper that checks that bytes are encoded as Right iff they are valid UTF8 bytes
---
--- prop> \(b :: B.ByteString) -> verEncoding b (fmap (fromEncoding . decodeAll . proxiedId (Proxy :: Proxy (Enc '["r-UTF8"] _ _))) . (encodeFAll :: _ -> Either EncodeEx _). toEncoding () $ b)
-
-instance EncodeF (Either EncodeEx) (Enc xs c B.ByteString) (Enc ("r-UTF8" ': xs) c B.ByteString) where
-    encodeF = implEncodeF prxyUtf8 (fmap TE.encodeUtf8 . TE.decodeUtf8')
-instance (RecreateErr f, Applicative f) => RecreateF f (Enc xs c B.ByteString) (Enc ("r-UTF8" ': xs) c B.ByteString) where
-    checkPrevF = implCheckPrevF (asRecreateErr prxyUtf8 . fmap TE.encodeUtf8 . TE.decodeUtf8')
-instance Applicative f => DecodeF f (Enc ("r-UTF8" ': xs) c B.ByteString) (Enc xs c B.ByteString) where
-    decodeF = implTranP id 
-
-instance EncodeF (Either EncodeEx) (Enc xs c BL.ByteString) (Enc ("r-UTF8" ': xs) c BL.ByteString) where
-    encodeF = implEncodeF prxyUtf8 (fmap TEL.encodeUtf8 . TEL.decodeUtf8')
-instance (RecreateErr f, Applicative f) => RecreateF f (Enc xs c BL.ByteString) (Enc ("r-UTF8" ': xs) c BL.ByteString) where
-    checkPrevF = implCheckPrevF (asRecreateErr prxyUtf8 . fmap TEL.encodeUtf8 . TEL.decodeUtf8')
-instance Applicative f => DecodeF f (Enc ("r-UTF8" ': xs) c BL.ByteString) (Enc xs c BL.ByteString) where
-    decodeF = implTranP id 
-
---- Utilities ---
-
--- | helper function checks that given ByteString, 
--- if is encoded as Left is must be not Utf8 decodable
--- is is encoded as Right is must be Utf8 encodable 
-verEncoding :: B.ByteString -> Either err B.ByteString -> Bool
-verEncoding bs (Left _) = isLeft . TE.decodeUtf8' $ bs
-verEncoding bs (Right _) = isRight . TE.decodeUtf8' $ bs
diff --git a/src/Data/TypedEncoding/Internal/Class.hs b/src/Data/TypedEncoding/Internal/Class.hs
--- a/src/Data/TypedEncoding/Internal/Class.hs
+++ b/src/Data/TypedEncoding/Internal/Class.hs
@@ -5,218 +5,62 @@
 {-# LANGUAGE TypeOperators #-}
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE UndecidableInstances #-}
+-- {-# LANGUAGE UndecidableInstances #-}
 {-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE TypeFamilies #-}
--- {-# LANGUAGE PartialTypeSignatures #-}
+-- {-# LANGUAGE TypeFamilies #-}
+-- {-# LANGUAGE TypeApplications #-}
+-- {-# LANGUAGE AllowAmbiguousTypes #-}
 
-module Data.TypedEncoding.Internal.Class where
+module Data.TypedEncoding.Internal.Class (
+    module Data.TypedEncoding.Internal.Class
+    , module Data.TypedEncoding.Internal.Class.Util
+    , module Data.TypedEncoding.Internal.Class.Encode
+    , module Data.TypedEncoding.Internal.Class.Decode
+    , module Data.TypedEncoding.Internal.Class.Recreate   
+  ) where
 
+import           Data.TypedEncoding.Internal.Class.Util
+import           Data.TypedEncoding.Internal.Class.Encode
+import           Data.TypedEncoding.Internal.Class.Decode
+import           Data.TypedEncoding.Internal.Class.Recreate
+
 import           Data.TypedEncoding.Internal.Types (Enc(..) 
-                                              , toEncoding
-                                              , getPayload
-                                              , withUnsafeCoerce
-                                              , unsafeChangePayload
-                                              , RecreateEx(..)
-                                              , UnexpectedDecodeEx(..))
-import           Data.Proxy
+                                                   , withUnsafeCoerce)
 import           Data.Functor.Identity
 import           GHC.TypeLits
-import           Data.Semigroup ((<>))
-import qualified Data.ByteString.Char8 as B
-import qualified Data.ByteString.Lazy.Char8 as BL
-import qualified Data.Text as T
-import qualified Data.Text.Lazy as TL
 
-import qualified Data.List as L
 
-
--- $setup
--- >>> :set -XScopedTypeVariables -XKindSignatures -XMultiParamTypeClasses -XDataKinds -XPolyKinds -XFlexibleInstances -XFlexibleContexts
--- >>> import Data.TypedEncoding.Internal.Types (unsafeSetPayload)
-
-class EncodeF f instr outstr where    
-    encodeF :: instr -> f outstr
-
-class EncodeFAll f (xs :: [k]) c str where
-    encodeFAll :: (Enc '[] c str) -> f (Enc xs c str)
-
-instance Applicative f => EncodeFAll f '[] c str where
-    encodeFAll (MkEnc _ c str) = pure $ toEncoding c str 
-
-instance (Monad f, EncodeFAll f xs c str, EncodeF f (Enc xs c str) (Enc (x ': xs) c str)) => EncodeFAll f (x ': xs) c str where
-    encodeFAll str = 
-        let re :: f (Enc xs c str) = encodeFAll str
-        in re >>= encodeF
-
-
-encodeAll :: EncodeFAll Identity (xs :: [k]) c str => 
-              (Enc '[] c str) 
-              -> (Enc xs c str)
-encodeAll = runIdentity . encodeFAll             
-
-
-
-class DecodeF f instr outstr where    
-    decodeF :: instr -> f outstr
-
-class DecodeFAll f (xs :: [k]) c str where
-    decodeFAll :: (Enc xs c str) ->  f (Enc '[] c str)
-
-instance Applicative f => DecodeFAll f '[] c str where
-    decodeFAll (MkEnc _ c str) = pure $ toEncoding c str 
-
-instance (Monad f, DecodeFAll f xs c str, DecodeF f (Enc (x ': xs) c str) (Enc (xs) c str)) => DecodeFAll f (x ': xs) c str where
-    decodeFAll str = 
-        let re :: f (Enc xs c str) = decodeF str
-        in re >>= decodeFAll
-
-decodeAll :: DecodeFAll Identity (xs :: [k]) c str => 
-              (Enc xs c str)
-              -> (Enc '[] c str) 
-decodeAll = runIdentity . decodeFAll 
-
--- | Used to safely recover encoded data validating all encodingss
-class RecreateF f instr outstr where    
-    checkPrevF :: outstr -> f instr
-
-class (Functor f) => RecreateFAll f (xs :: [k]) c str where
-    checkFAll :: (Enc xs c str) -> f (Enc '[] c str)
-    recreateFAll :: (Enc '[] c str) -> f (Enc xs c str)
-    recreateFAll str@(MkEnc _ _ pay) = 
-        let str0 :: Enc xs c str = withUnsafeCoerce id str
-        in fmap (withUnsafeCoerce (const pay)) $ checkFAll str0    
-
-instance Applicative f => RecreateFAll f '[] c str where
-    checkFAll (MkEnc _ c str) = pure $ toEncoding c str 
+-- TODO would be nice to have EncodeFAll1 and DecodeFAll1 that starts
+-- end stops at frist encoding.           
 
+-- | 
+-- Generalized Java @toString@ or a type safe version of Haskell's 'Show'.
+--
+-- Encodes @a@ as @Enc '[xs]@.
+--
+class KnownSymbol x => ToEncString x str f a where
+    toEncStringF :: a -> f (Enc '[x] () str)
 
-instance (Monad f, RecreateFAll f xs c str, RecreateF f (Enc xs c str) (Enc (x ': xs) c str)) => RecreateFAll f (x ': xs) c str where
-    checkFAll str = 
-        let re :: f (Enc xs c str) = checkPrevF str
-        in re >>= checkFAll
+toEncString :: forall x str f a  . (ToEncString x str Identity a) => a -> Enc '[x] () str
+toEncString = runIdentity . toEncStringF
 
 
-recreateAll :: RecreateFAll Identity (xs :: [k]) c str => 
-              (Enc '[] c str) 
-              -> (Enc xs c str)
-recreateAll = runIdentity . recreateFAll             
-
-                    
-
--- | TODO use singletons definition instead?
-type family Append (xs :: [k]) (ys :: [k]) :: [k] where
-    Append '[] xs = xs
-    Append (y ': ys) xs = y ': (Append ys xs)
-
-encodeFPart :: forall f xs xsf c str . (Functor f, EncodeFAll f xs c str) => Proxy xs -> (Enc xsf c str) -> f (Enc (Append xs xsf) c str)
-encodeFPart p (MkEnc _ conf str) = 
-    let re :: f (Enc xs c str) = encodeFAll $ MkEnc Proxy conf str
-    in  (MkEnc Proxy conf . getPayload) <$> re 
-
-encodePart :: EncodeFAll Identity (xs :: [k]) c str => 
-              Proxy xs 
-              -> (Enc xsf c str)
-              -> (Enc (Append xs xsf) c str) 
-encodePart p = runIdentity . encodeFPart p
+-- | 
+-- Reverse of 'ToEncString' decodes encoded string back to @a@
+class (KnownSymbol x) => FromEncString a f str x where
+    fromEncStringF :: Enc '[x] () str -> f a
 
--- | Unsafe implementation guarded by safe type definition
-decodeFPart :: forall f xs xsf c str . (Functor f, DecodeFAll f xs c str) => Proxy xs -> (Enc (Append xs xsf) c str) -> f (Enc xsf c str)
-decodeFPart p (MkEnc _ conf str) = 
-    let re :: f (Enc '[] c str) = decodeFAll $ MkEnc (Proxy :: Proxy xs) conf str
-    in  (MkEnc Proxy conf . getPayload) <$> re 
- 
-decodePart :: DecodeFAll Identity (xs :: [k]) c str => 
-              Proxy xs 
-              -> (Enc (Append xs xsf) c str) 
-              -> (Enc xsf c str) 
-decodePart p = runIdentity . decodeFPart p
+fromEncString :: forall a str x . (FromEncString a Identity str x) => Enc '[x] () str -> a
+fromEncString = runIdentity . fromEncStringF
 
 -- Other classes --
 
--- subsets are useful for restriction encodings
+-- | subsets are useful for restriction encodings
 -- like r-UFT8 but not for other encodings.
-class Subset (x :: k) (y :: k) where
-    inject :: Proxy y -> Enc (x ': xs) c str ->  Enc (y ': xs) c str
-    inject _ = withUnsafeCoerce id
-
-class FlattenAs (x :: k) (y :: k) where
-    flattenAs :: Proxy y -> Enc (x ': xs) c str ->  Enc '[y] c str
-    flattenAs _ = withUnsafeCoerce id
-
--- | Polymorphic data payloads used to encode/decode
-class HasA c a where
-    has :: Proxy a -> c -> a
-
-instance HasA a () where
-    has _ = const ()
-
--- | With type safety in pace decoding errors should be unexpected
--- this class can be used to provide extra info if decoding could fail
-class UnexpectedDecodeErr f where 
-    unexpectedDecodeErr :: UnexpectedDecodeEx -> f a
-
-instance UnexpectedDecodeErr Identity where
-    unexpectedDecodeErr x = fail $ show x
-
-instance UnexpectedDecodeErr (Either UnexpectedDecodeEx) where
-    unexpectedDecodeErr = Left 
-
-asUnexpected :: (UnexpectedDecodeErr f, Applicative f, Show err, KnownSymbol x) => Proxy x -> Either err a -> f a
-asUnexpected p (Left err) = unexpectedDecodeErr $ UnexpectedDecodeEx p err
-asUnexpected _ (Right r) = pure r
-
--- TODO using RecreateErr typeclass is overkill
-
--- | Recovery errors are expected unless Recovery allows Identity instance
-class RecreateErr f where 
-    recoveryErr :: RecreateEx -> f a
-
-instance RecreateErr (Either RecreateEx) where
-    recoveryErr = Left  
-
-asRecreateErr :: (RecreateErr f, Applicative f, Show err, KnownSymbol x) => Proxy x -> Either err a -> f a
-asRecreateErr p (Left err) = recoveryErr $ RecreateEx p err
-asRecreateErr _ (Right r) = pure r
-
-
--- * Display 
-
--- | Human friendly version of Show
-class Displ x where 
-    displ :: x -> String
-
-instance Displ String where
-    displ = id    
-instance Displ T.Text where
-    displ x = "(Text " ++ T.unpack x ++ ")"
-instance Displ TL.Text where
-    displ x = "(TL.Text " ++ TL.unpack x ++ ")"
-instance Displ B.ByteString where
-    displ x = "(ByteString " ++ B.unpack x ++ ")" 
-instance Displ BL.ByteString where
-    displ x = "(ByteString " ++ BL.unpack x ++ ")" 
-
-
-instance Displ (Proxy '[]) where
-    displ _ = ""
-
--- |
--- >>> displ (Proxy :: Proxy ["FIRST", "SECOND"])
--- "FIRST,SECOND"
-instance (pxs ~ Proxy xs, Displ pxs, KnownSymbol x) => Displ (Proxy (x ': xs)) where
-    displ _ =  L.dropWhileEnd (',' ==) $  symbolVal (Proxy :: Proxy x) ++ "," ++ displ (Proxy :: Proxy xs)
-
--- >>> let disptest = unsafeSetPayload () "hello" :: Enc '["TEST"] () T.Text
--- >>> displ disptest
--- "MkEnc '[TEST] () hello"
-instance (Displ (Proxy xs), Show c, Displ str) => Displ ( Enc xs c str) where
-    displ (MkEnc p c s) = 
-        "MkEnc '[" ++ displ p ++ "] " ++ show c ++ " " ++ displ s
-
-
--- Utils --
+class Superset (y :: Symbol) (x :: Symbol) where
+    inject :: Enc (x ': xs) c str ->  Enc (y ': xs) c str
+    inject = withUnsafeCoerce id
 
-errorOnLeft :: Show err => Either err a -> a
-errorOnLeft (Left e) = error $ "You trusted encodings too much " <> show e
-errorOnLeft (Right r) =  r
+class FlattenAs (y :: Symbol) (x :: Symbol) where
+    flattenAs ::  Enc (x ': xs) c str ->  Enc '[y] c str
+    flattenAs = withUnsafeCoerce id
diff --git a/src/Data/TypedEncoding/Internal/Class/Decode.hs b/src/Data/TypedEncoding/Internal/Class/Decode.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/TypedEncoding/Internal/Class/Decode.hs
@@ -0,0 +1,81 @@
+
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE PolyKinds #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE AllowAmbiguousTypes #-}
+
+module Data.TypedEncoding.Internal.Class.Decode where
+
+import           Data.TypedEncoding.Internal.Class.Util
+
+import           Data.TypedEncoding.Internal.Types (Enc(..) 
+                                              , toEncoding
+                                              , getPayload
+                                              , UnexpectedDecodeEx(..))
+import           Data.Proxy
+import           Data.Functor.Identity
+import           GHC.TypeLits
+
+
+class DecodeF f instr outstr where    
+    decodeF :: instr -> f outstr
+
+class DecodeFAll f (xs :: [Symbol]) c str where
+    decodeFAll :: Enc xs c str ->  f (Enc '[] c str)
+
+instance Applicative f => DecodeFAll f '[] c str where
+    decodeFAll (MkEnc _ c str) = pure $ toEncoding c str 
+
+instance (Monad f, DecodeFAll f xs c str, DecodeF f (Enc (x ': xs) c str) (Enc xs c str)) => DecodeFAll f (x ': xs) c str where
+    decodeFAll str = 
+        let re :: f (Enc xs c str) = decodeF str
+        in re >>= decodeFAll
+
+decodeAll :: DecodeFAll Identity (xs :: [Symbol]) c str => 
+              Enc xs c str
+              -> Enc '[] c str
+decodeAll = runIdentity . decodeFAll 
+
+
+decodeFPart_ :: forall f xs xsf c str . (Functor f, DecodeFAll f xs c str) => Proxy xs -> Enc (Append xs xsf) c str -> f (Enc xsf c str)
+decodeFPart_ p (MkEnc _ conf str) = 
+    let re :: f (Enc '[] c str) = decodeFAll $ MkEnc (Proxy :: Proxy xs) conf str
+    in  MkEnc Proxy conf . getPayload <$> re 
+
+decodeFPart :: forall (xs :: [Symbol]) xsf f c str . (Functor f, DecodeFAll f xs c str) =>  Enc (Append xs xsf) c str -> f (Enc xsf c str)
+decodeFPart = decodeFPart_ (Proxy :: Proxy xs) 
+
+decodePart_ :: DecodeFAll Identity (xs :: [Symbol]) c str => 
+              Proxy xs 
+              -> Enc (Append xs xsf) c str 
+              -> Enc xsf c str 
+decodePart_ p = runIdentity . decodeFPart_ p
+
+decodePart :: forall (xs :: [Symbol]) xsf c str .  DecodeFAll Identity xs c str => 
+              Enc (Append xs xsf) c str 
+              -> Enc xsf c str
+decodePart = decodePart_ (Proxy :: Proxy xs)              
+
+-- | With type safety in place decoding errors should be unexpected.
+-- This class can be used to provide extra info if decoding could fail
+class UnexpectedDecodeErr f where 
+    unexpectedDecodeErr :: UnexpectedDecodeEx -> f a
+
+instance UnexpectedDecodeErr Identity where
+    unexpectedDecodeErr x = fail $ show x
+
+instance UnexpectedDecodeErr (Either UnexpectedDecodeEx) where
+    unexpectedDecodeErr = Left 
+
+asUnexpected_ :: (KnownSymbol x, UnexpectedDecodeErr f, Applicative f, Show err) => Proxy x -> Either err a -> f a
+asUnexpected_ p (Left err) = unexpectedDecodeErr $ UnexpectedDecodeEx p err
+asUnexpected_ _ (Right r) = pure r
+
+asUnexpected :: forall x f err a . (KnownSymbol x, UnexpectedDecodeErr f, Applicative f, Show err) => Either err a -> f a
+asUnexpected = asUnexpected_ (Proxy :: Proxy x)
diff --git a/src/Data/TypedEncoding/Internal/Class/Encode.hs b/src/Data/TypedEncoding/Internal/Class/Encode.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/TypedEncoding/Internal/Class/Encode.hs
@@ -0,0 +1,71 @@
+
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE PolyKinds #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeFamilies #-}
+-- {-# LANGUAGE TypeApplications #-}
+{-# LANGUAGE AllowAmbiguousTypes #-}
+
+module Data.TypedEncoding.Internal.Class.Encode where
+
+import           Data.TypedEncoding.Internal.Class.Util
+
+import           Data.TypedEncoding.Internal.Types (Enc(..) 
+                                              , toEncoding
+                                              , getPayload
+                                             )
+import           Data.Proxy
+import           Data.Functor.Identity
+import           GHC.TypeLits
+
+
+class EncodeF f instr outstr where    
+    encodeF :: instr -> f outstr
+
+class EncodeFAll f (xs :: [Symbol]) c str where
+    encodeFAll :: Enc '[] c str -> f (Enc xs c str)
+
+instance Applicative f => EncodeFAll f '[] c str where
+    encodeFAll (MkEnc _ c str) = pure $ toEncoding c str 
+
+instance (Monad f, EncodeFAll f xs c str, EncodeF f (Enc xs c str) (Enc (x ': xs) c str)) => EncodeFAll f (x ': xs) c str where
+    encodeFAll str = 
+        let re :: f (Enc xs c str) = encodeFAll str
+        in re >>= encodeF
+
+
+encodeAll :: EncodeFAll Identity (xs :: [Symbol]) c str => 
+              Enc '[] c str 
+              -> Enc xs c str
+encodeAll = runIdentity . encodeFAll             
+
+
+
+encodeFPart_ :: forall f xs xsf c str . (Functor f, EncodeFAll f xs c str) => Proxy xs -> Enc xsf c str -> f (Enc (Append xs xsf) c str)
+encodeFPart_ p (MkEnc _ conf str) = 
+    let re :: f (Enc xs c str) = encodeFAll $ MkEnc Proxy conf str
+    in  MkEnc Proxy conf . getPayload <$> re 
+
+
+encodeFPart :: forall (xs :: [Symbol]) xsf f c str . (Functor f, EncodeFAll f xs c str) => Enc xsf c str -> f (Enc (Append xs xsf) c str)
+encodeFPart = encodeFPart_ (Proxy :: Proxy xs) 
+
+
+encodePart_ :: EncodeFAll Identity (xs :: [Symbol]) c str => 
+              Proxy xs 
+              -> Enc xsf c str
+              -> Enc (Append xs xsf) c str 
+encodePart_ p = runIdentity . encodeFPart_ p
+
+-- | for some reason ApplyTypes syntax does not want to work if xs is specified with 
+-- polymorphic [Symbol]
+encodePart :: forall (xs :: [Symbol]) xsf c str . EncodeFAll Identity xs c str => 
+               Enc xsf c str
+              -> Enc (Append xs xsf) c str 
+encodePart = encodePart_ (Proxy :: Proxy xs)              
+
diff --git a/src/Data/TypedEncoding/Internal/Class/IsStringR.hs b/src/Data/TypedEncoding/Internal/Class/IsStringR.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/TypedEncoding/Internal/Class/IsStringR.hs
@@ -0,0 +1,64 @@
+
+
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications #-}
+{-# LANGUAGE AllowAmbiguousTypes #-}
+
+module Data.TypedEncoding.Internal.Class.IsStringR where
+
+import           Data.Proxy
+
+import           Data.String
+-- import qualified Data.ByteString.Char8 as B
+import qualified Data.Text as T
+import qualified Data.Text.Lazy as TL
+
+
+
+-- $setup
+-- >>> :set -XScopedTypeVariables -XTypeApplications -XAllowAmbiguousTypes
+-- >>> import Test.QuickCheck
+-- >>> import Test.QuickCheck.Instances.Text()
+-- >>> import Test.QuickCheck.Instances.ByteString()
+
+-- | Reverses 'Data.String.IsString'
+--
+-- laws:
+--
+-- @
+--  toString . fromString == id
+--  fromString . toString == id
+-- @
+--
+-- Note: ByteString is not a valid instance, ByteString "r-ASCII", or "r-UTF8" would
+-- be needed.
+-- @B.unpack $ B.pack "\160688" == "\176"@
+class IsStringR a where
+    toString :: a -> String
+
+prop_fromStringToString :: forall s . (IsString s, IsStringR s, Eq s) => s -> Bool
+prop_fromStringToString x = x == (fromString @s . toString $ x)
+
+prop_toStringFromString :: forall s . (IsString s, IsStringR s) => Proxy s -> String -> Bool
+prop_toStringFromString _ x = x == (toString @s . fromString $ x)
+
+-- This would not work
+-- @B.unpack $ B.pack "\160688" == "\176"@
+--
+-- prop> prop_toStringFromString (Proxy :: Proxy B.ByteString) 
+-- prop> prop_fromStringToString @B.ByteString
+-- instance IsStringR B.ByteString where
+--     toString = B.unpack
+ 
+
+-- |
+-- prop> prop_toStringFromString (Proxy :: Proxy T.Text) 
+-- prop> prop_fromStringToString @T.Text
+instance IsStringR T.Text where
+    toString = T.unpack    
+
+-- |
+-- prop> prop_toStringFromString (Proxy :: Proxy TL.Text) 
+-- prop> prop_fromStringToString @TL.Text
+instance IsStringR TL.Text where
+    toString = TL.unpack  
diff --git a/src/Data/TypedEncoding/Internal/Class/Recreate.hs b/src/Data/TypedEncoding/Internal/Class/Recreate.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/TypedEncoding/Internal/Class/Recreate.hs
@@ -0,0 +1,67 @@
+
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE PolyKinds #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeFamilies #-}
+-- {-# LANGUAGE TypeApplications #-}
+{-# LANGUAGE AllowAmbiguousTypes #-}
+
+module Data.TypedEncoding.Internal.Class.Recreate where
+
+import           Data.TypedEncoding.Internal.Types (Enc(..) 
+                                              , toEncoding
+                                              , withUnsafeCoerce
+                                              , RecreateEx(..)
+                                             )
+import           Data.Proxy
+import           Data.Functor.Identity
+import           GHC.TypeLits
+
+
+-- | Used to safely recover encoded data validating all encodingss
+class RecreateF f instr outstr where    
+    checkPrevF :: outstr -> f instr
+
+class (Functor f) => RecreateFAll f (xs :: [Symbol]) c str where
+    checkFAll :: Enc xs c str -> f (Enc '[] c str)
+    recreateFAll :: Enc '[] c str -> f (Enc xs c str)
+    recreateFAll str@(MkEnc _ _ pay) = 
+        let str0 :: Enc xs c str = withUnsafeCoerce id str
+        in withUnsafeCoerce (const pay) <$> checkFAll str0    
+
+instance Applicative f => RecreateFAll f '[] c str where
+    checkFAll (MkEnc _ c str) = pure $ toEncoding c str 
+
+
+instance (Monad f, RecreateFAll f xs c str, RecreateF f (Enc xs c str) (Enc (x ': xs) c str)) => RecreateFAll f (x ': xs) c str where
+    checkFAll str = 
+        let re :: f (Enc xs c str) = checkPrevF str
+        in re >>= checkFAll
+
+
+recreateAll :: forall xs c str . RecreateFAll Identity xs c str => 
+              Enc '[] c str 
+              -> Enc xs c str
+recreateAll = runIdentity . recreateFAll 
+
+-- TODO using RecreateErr typeclass is overkill
+
+-- | Recovery errors are expected unless Recovery allows Identity instance
+class RecreateErr f where 
+    recoveryErr :: RecreateEx -> f a
+
+instance RecreateErr (Either RecreateEx) where
+    recoveryErr = Left  
+
+asRecreateErr_ :: (RecreateErr f, Applicative f, Show err, KnownSymbol x) => Proxy x -> Either err a -> f a
+asRecreateErr_ p (Left err) = recoveryErr $ RecreateEx p err
+asRecreateErr_ _ (Right r) = pure r
+
+
+asRecreateErr :: forall x f err a . (RecreateErr f, Applicative f, Show err, KnownSymbol x) => Either err a -> f a
+asRecreateErr = asRecreateErr_ (Proxy :: Proxy x)
diff --git a/src/Data/TypedEncoding/Internal/Class/Util.hs b/src/Data/TypedEncoding/Internal/Class/Util.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/TypedEncoding/Internal/Class/Util.hs
@@ -0,0 +1,88 @@
+
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE PolyKinds #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeApplications #-}
+{-# LANGUAGE AllowAmbiguousTypes #-}
+
+module Data.TypedEncoding.Internal.Class.Util where
+
+import           Data.TypedEncoding.Internal.Types.Common
+
+import qualified Data.ByteString.Char8 as B
+import qualified Data.ByteString.Lazy.Char8 as BL
+import qualified Data.Text as T
+import qualified Data.Text.Lazy as TL
+
+import           Data.Proxy
+import qualified Data.List as L
+import           GHC.TypeLits
+
+-- $setup
+-- >>> :set -XScopedTypeVariables -XTypeApplications -XAllowAmbiguousTypes -XDataKinds
+
+-- * Symbol List
+
+class SymbolList (xs::[Symbol]) where 
+    symbolVals :: [String]
+
+instance SymbolList '[] where
+    symbolVals = []
+
+-- |
+-- >>> symbolVals @ '["FIRST", "SECOND"]
+-- ["FIRST","SECOND"]
+instance (SymbolList xs, KnownSymbol x) => SymbolList (x ': xs) where
+    symbolVals =  symbolVal (Proxy :: Proxy x) : symbolVals @xs
+ 
+symbolVals_ :: forall xs . SymbolList xs => Proxy xs -> [String]
+symbolVals_ _ = symbolVals @xs
+
+-- * Display 
+
+-- | Human friendly version of Show
+class Displ x where 
+    displ :: x -> String
+
+instance Displ EncAnn where
+    displ = id 
+instance Displ [EncAnn] where 
+    displ x = "[" ++ L.intercalate "," (map displ x) ++ "]"
+instance Displ T.Text where
+    displ x = "(Text " ++ T.unpack x ++ ")"
+instance Displ TL.Text where
+    displ x = "(TL.Text " ++ TL.unpack x ++ ")"
+instance Displ B.ByteString where
+    displ x = "(ByteString " ++ B.unpack x ++ ")" 
+instance Displ BL.ByteString where
+    displ x = "(ByteString " ++ BL.unpack x ++ ")" 
+
+
+
+-- |
+-- >>> displ (Proxy :: Proxy ["FIRST", "SECOND"])
+-- "[FIRST,SECOND]"
+instance (SymbolList xs) => Displ (Proxy xs) where
+    displ _ = displ $  symbolVals @ xs
+        -- "[" ++ (L.intercalate "," $ map displ $ symbolVals @ xs) ++ "]"
+
+
+-- * Other
+
+-- | TODO should this be imported from somewhere?
+type family Append (xs :: [k]) (ys :: [k]) :: [k] where
+    Append '[] xs = xs
+    Append (y ': ys) xs = y ': Append ys xs
+
+-- | Polymorphic data payloads used to encode/decode
+class HasA a c where
+    has :: c -> a
+
+instance HasA () c where
+    has = const ()
diff --git a/src/Data/TypedEncoding/Internal/Combinators.hs b/src/Data/TypedEncoding/Internal/Combinators.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/TypedEncoding/Internal/Combinators.hs
@@ -0,0 +1,51 @@
+
+{-# LANGUAGE PolyKinds #-}
+{-# LANGUAGE DataKinds #-}
+-- {-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications #-}
+{-# LANGUAGE AllowAmbiguousTypes #-}
+{-# LANGUAGE FlexibleContexts #-}
+
+module Data.TypedEncoding.Internal.Combinators where
+
+import           Data.TypedEncoding.Internal.Types
+import           Data.TypedEncoding.Internal.Class.IsStringR ()
+import           Data.TypedEncoding.Internal.Class.Recreate
+import           Data.TypedEncoding.Internal.Class.Util (SymbolList)
+import           GHC.TypeLits
+
+-- $setup
+-- >>> :set -XTypeApplications
+-- >>> import qualified Data.Text as T
+-- >>> import           Data.Word
+
+-- * Converting 'UncheckedEnc' to 'Enc'
+
+-- | Maybe signals annotation mismatch, effect @f@ is not evaluated unless there is match
+verifyUncheckedEnc :: forall (xs :: [Symbol]) f c str . (
+                     RecreateFAll f xs c str
+                     , RecreateErr f
+                     , Applicative f
+                     , SymbolList xs
+                   ) 
+                   =>
+                   UncheckedEnc c str
+                   ->  Maybe (f (Enc xs c str))
+
+verifyUncheckedEnc x = 
+    -- let perr = Proxy :: Proxy "e-mismatch"
+    --in  
+      case verifyAnn @xs x of
+            Left err -> Nothing -- asRecreateErr_ perr $ Left err
+            Right (MkUncheckedEnc _ c str) -> Just $ recreateFAll . toEncoding c $ str
+
+
+verifyUncheckedEnc' :: forall (xs :: [Symbol]) c str . (
+                     RecreateFAll (Either RecreateEx) xs c str
+                     , SymbolList xs
+                   ) 
+                   =>
+                   UncheckedEnc c str
+                   ->  Maybe (Either RecreateEx (Enc xs c str))
+verifyUncheckedEnc' = verifyUncheckedEnc
diff --git a/src/Data/TypedEncoding/Internal/Instances/Combinators.hs b/src/Data/TypedEncoding/Internal/Instances/Combinators.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/TypedEncoding/Internal/Instances/Combinators.hs
@@ -0,0 +1,89 @@
+
+{-# LANGUAGE PolyKinds #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+-- {-# LANGUAGE AllowAmbiguousTypes #-}
+-- {-# LANGUAGE TypeApplications #-}
+{-# LANGUAGE AllowAmbiguousTypes #-}
+{-# LANGUAGE FlexibleContexts #-}
+
+-- | Combinators that can be helpful in instance creation.
+module Data.TypedEncoding.Internal.Instances.Combinators where
+
+import           Data.String
+import           Data.Proxy
+import           Text.Read
+import           Data.TypedEncoding.Internal.Types
+import           Data.TypedEncoding.Internal.Class.IsStringR 
+import           GHC.TypeLits
+
+-- $setup
+-- >>> :set -XTypeApplications
+-- >>> import qualified Data.Text as T
+-- >>> import           Data.Word
+
+
+-- * Composite encodings from 'Foldable' 'Functor' types
+
+-- | allows to fold payload in Enc to create another Enc, assumes homogeneous input encodings.
+-- This yields not a type safe code, better implementation code should use fixed size
+-- dependently typed @Vect n@ or some @HList@ like foldable.
+foldEnc :: forall (xs2 :: [Symbol]) (xs1 :: [Symbol]) f c s1 s2 
+           . (Foldable f, Functor f) 
+           => c -> (s1 -> s2 -> s2) -> s2 -> f (Enc xs1 c s1) -> Enc xs2 c s2
+foldEnc c f sinit = unsafeSetPayload c . foldr f sinit . fmap getPayload 
+
+-- | Similar to 'foldEnc', assumes that destination payload has @IsString@ instance and uses @""@ as base case. 
+foldEncStr :: forall (xs2 :: [Symbol]) (xs1 :: [Symbol]) f c s1 s2 
+             . (Foldable f, Functor f, IsString s2) 
+             => c -> (s1 -> s2 -> s2) -> f (Enc xs1 c s1) -> Enc xs2 c s2
+foldEncStr c f = foldEnc c f ""
+
+-- | Similar to 'foldEnc', works with untyped 'CheckedEnc'
+foldCheckedEnc :: forall (xs2 :: [Symbol]) f c s1 s2 
+             . (Foldable f, Functor f) 
+             => c -> ([EncAnn] -> s1 -> s2 -> s2) -> s2 -> f (CheckedEnc c s1) -> Enc xs2 c s2
+foldCheckedEnc c f sinit = unsafeSetPayload c . foldr (uncurry f) sinit . fmap getCheckedEncPayload
+
+-- | Similar to 'foldEncStr', works with untyped 'CheckedEnc'
+foldCheckedEncStr :: forall (xs2 :: [Symbol]) f c s1 s2 . (Foldable f, Functor f, IsString s2) => c -> ([EncAnn] -> s1 -> s2 -> s2) -> f (CheckedEnc c s1) -> Enc xs2 c s2
+foldCheckedEncStr c f  = foldCheckedEnc c f ""
+
+
+-- * Composite encoding: Recreate and Encode helpers
+
+-- | Splits composite payload into homogenious chunks
+splitPayload :: forall (xs2 :: [Symbol]) (xs1 :: [Symbol]) c s1 s2 . 
+             (s1 -> [s2]) 
+             -> Enc xs1 c s1 
+             -> [Enc xs2 c s2]
+splitPayload f (MkEnc _ c s1) = map (MkEnc Proxy c) (f s1)
+   
+-- | Untyped version of 'splitPayload'
+splitSomePayload :: forall c s1 s2 . 
+             ([EncAnn] -> s1 -> [([EncAnn], s2)]) 
+             -> CheckedEnc c s1 
+             -> [CheckedEnc c s2]
+splitSomePayload f (MkCheckedEnc ann1 c s1) = map (\(ann2, s2) -> MkCheckedEnc ann2 c s2) (f ann1 s1)
+
+
+-- * Utility combinators 
+
+-- | sometimes show . read is not identity, eg. Word8:
+--
+-- >>> read "256" :: Word8
+-- 0
+--
+-- >>> verifyWithRead @Word8 "Word8-decimal" (T.pack "256")
+-- Left "Payload does not satisfy format Word8-decimal: 256"
+-- >>> verifyWithRead @Word8 "Word8-decimal" (T.pack "123")
+-- Right "123"
+verifyWithRead :: forall a str . (IsStringR str, IsString str, Read a, Show a) => String -> str -> Either String str
+verifyWithRead msg x = 
+    let s = toString x
+        a :: Maybe a = readMaybe s
+        check = (show <$> a) == Just s 
+    in if check
+       then Right x
+       else Left $ "Payload does not satisfy format " ++ msg ++ ": " ++ s    
diff --git a/src/Data/TypedEncoding/Internal/Types.hs b/src/Data/TypedEncoding/Internal/Types.hs
--- a/src/Data/TypedEncoding/Internal/Types.hs
+++ b/src/Data/TypedEncoding/Internal/Types.hs
@@ -1,95 +1,61 @@
 {-# LANGUAGE GADTs #-}
 {-# LANGUAGE PolyKinds #-}
-{-# LANGUAGE DeriveFunctor #-}
 {-# LANGUAGE DataKinds #-}
 {-# LANGUAGE TypeOperators #-}
 {-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE AllowAmbiguousTypes #-}
+-- {-# LANGUAGE RankNTypes #-}
 
 -- |
 -- Internal definition of types
 
-module Data.TypedEncoding.Internal.Types where
-
-import           Data.Proxy
-import           Data.Functor.Identity
-import           GHC.TypeLits
-
--- Not a Functor on purpose
-data Enc enc conf str where
-    -- | constructor is to be treated as Unsafe to Encode and Decode instance implementations
-    -- particular encoding instances may expose smart constructors for limited data types
-    MkEnc :: Proxy enc -> conf -> str -> Enc enc conf str
-    deriving (Show, Eq) 
- 
-toEncoding :: conf -> str -> Enc '[] conf str
-toEncoding conf str = MkEnc Proxy conf str
-
-fromEncoding :: Enc '[] conf str -> str
-fromEncoding = getPayload
-
--- TODO make all implTran functions module-private
--- TODO disambiguate implEncode from implDecode, from implCheckPrevF for type safety
--- especially since these are always used in combo with asRecreateErr or asUnexpected 
-
-implTranF :: Functor f => (str -> f str) -> Enc enc1 conf str -> f (Enc enc2 conf str)
-implTranF f  = implTranF' (\c -> f)
-
--- TODO could this type be more precise?
-implEncodeF :: (Show err, KnownSymbol x) => Proxy x -> (str -> Either err str) ->  Enc enc1 conf str -> Either EncodeEx (Enc enc2 conf str) 
-implEncodeF p f = implTranF (either (Left . EncodeEx p) Right . f) 
-
-implDecodeF :: Functor f => (str -> f str) -> Enc enc1 conf str -> f (Enc enc2 conf str)
-implDecodeF = implTranF
-
-implCheckPrevF :: Functor f => (str -> f str) -> Enc enc1 conf str -> f (Enc enc2 conf str)
-implCheckPrevF = implTranF
-
-
-implTranF' :: Functor f =>  (conf -> str -> f str) -> Enc enc1 conf str -> f (Enc enc2 conf str)
-implTranF' f (MkEnc _ conf str) = (MkEnc Proxy conf) <$> f conf str
-
-implEncodeF' :: (Show err, KnownSymbol x) => Proxy x -> (conf -> str -> Either err str) ->  Enc enc1 conf str -> Either EncodeEx (Enc enc2 conf str) 
-implEncodeF' p f = implTranF' (\c -> either (Left . EncodeEx p) Right . f c) 
-
-implDecodeF' :: Functor f =>  (conf -> str -> f str) -> Enc enc1 conf str -> f (Enc enc2 conf str)
-implDecodeF' = implTranF'
-
-implTranP :: Applicative f => (str -> str) -> Enc enc1 conf str -> f (Enc enc2 conf str)
-implTranP f  = implTranF' (\c -> pure . f)
-
-implEncodeP :: Applicative f => (str -> str) -> Enc enc1 conf str -> f (Enc enc2 conf str)
-implEncodeP = implTranP
-
-implTranP' :: Applicative f => (conf -> str -> str) -> Enc enc1 conf str -> f (Enc enc2 conf str)
-implTranP' f  = implTranF' (\c -> pure . f c)
+module Data.TypedEncoding.Internal.Types (
+        module Data.TypedEncoding.Internal.Types
+        -- * Main encoding type and basic combinators.
+        , module Data.TypedEncoding.Internal.Types.Enc
+        -- * Untyped version and existentially quantified versions of Enc
+        , module Data.TypedEncoding.Internal.Types.CheckedEnc
+        -- * Not verified encoded data
+        , module Data.TypedEncoding.Internal.Types.UncheckedEnc
+        -- * Commmon types
+        , module Data.TypedEncoding.Internal.Types.Common
+    ) where
 
-implEncodeP' :: Applicative f => (conf -> str -> str) -> Enc enc1 conf str -> f (Enc enc2 conf str)
-implEncodeP' = implTranP'
+import           Data.TypedEncoding.Internal.Types.Enc
+import           Data.TypedEncoding.Internal.Types.CheckedEnc
+import           Data.TypedEncoding.Internal.Types.UncheckedEnc
+import           Data.TypedEncoding.Internal.Types.Common
 
 
-getPayload :: Enc enc conf str -> str  
-getPayload (MkEnc _ _ str) = str
-
-unsafeSetPayload :: conf -> str -> Enc enc conf str 
-unsafeSetPayload c str = MkEnc Proxy c str
-
-withUnsafeCoerce ::  (s1 -> s2) -> Enc e1 c s1 -> Enc e2 c s2
-withUnsafeCoerce f (MkEnc _ conf str)  = (MkEnc Proxy conf (f str)) 
-
-unsafeChangePayload ::  (s1 -> s2) -> Enc e c s1 -> Enc e c s2
-unsafeChangePayload f (MkEnc p conf str)  = (MkEnc p conf (f str)) 
+import           Data.Proxy
+-- import           Data.Functor.Identity
+import           GHC.TypeLits
+-- import           Data.TypedEncoding.Internal.Class.Util
 
+-- $setup
+-- >>> :set -XOverloadedStrings -XMultiParamTypeClasses -XDataKinds -XAllowAmbiguousTypes
+-- >>> import qualified Data.Text as T
 
 
 -- | Represents errors in recovery (recreation of encoded types).
 data RecreateEx where
-    RecreateEx:: (Show e, KnownSymbol x) => Proxy x -> e -> RecreateEx 
+    RecreateEx:: (Show e, KnownSymbol x) => Proxy x -> e -> RecreateEx
+    RecreateExUnkStep::   (Show e) => e -> RecreateEx
 
 instance Show RecreateEx where
     show (RecreateEx prxy a) = "(RecreateEx \"" ++ symbolVal prxy ++ "\" (" ++ show a ++ "))"
+    show (RecreateExUnkStep  a) = "(UnknownDecodeStep (" ++ show a ++ "))"
 
 
+recreateErrUnknown :: (Show e) => e -> RecreateEx
+recreateErrUnknown  = RecreateExUnkStep
+
+-- instance Eq RecreateEx where
+--     (RecreateEx prxy1 a1) == RecreateEx prxy2 a2 = (symbolVal prxy1) == (symbolVal prxy2)
+
+
 -- | Represents errors in encoding
 data EncodeEx where
     EncodeEx:: (Show a, KnownSymbol x) => Proxy x -> a -> EncodeEx 
@@ -98,7 +64,6 @@
     show (EncodeEx prxy a) = "(EncodeEx \"" ++ symbolVal prxy ++ "\" (" ++ show a ++ "))"
 
 
-
 -- | Type safety over encodings makes decoding process safe.
 -- However failures are still possible due to bugs or unsafe payload modifications.
 -- UnexpectedDecodeEx represents such errors.
@@ -107,3 +72,18 @@
 
 instance Show UnexpectedDecodeEx where
     show (UnexpectedDecodeEx prxy a) = "(UnexpectedDecodeEx \"" ++ symbolVal prxy ++ "\" (" ++ show a ++ "))"
+
+
+-- * Base combinators that rely on types defined here
+
+-- TODO could this type be more precise?
+implEncodeF_ :: (Show err, KnownSymbol x) => Proxy x -> (str -> Either err str) ->  Enc enc1 conf str -> Either EncodeEx (Enc enc2 conf str) 
+implEncodeF_ p f = implTranF (either (Left . EncodeEx p) Right . f) 
+
+implEncodeF :: forall x enc1 enc2 err conf str . 
+              (Show err, KnownSymbol x) 
+              => (str -> Either err str) ->  Enc enc1 conf str -> Either EncodeEx (Enc enc2 conf str) 
+implEncodeF = implEncodeF_ (Proxy :: Proxy x)
+
+implEncodeF_' :: (Show err, KnownSymbol x) => Proxy x -> (conf -> str -> Either err str) ->  Enc enc1 conf str -> Either EncodeEx (Enc enc2 conf str) 
+implEncodeF_' p f = implTranF' (\c -> either (Left . EncodeEx p) Right . f c) 
diff --git a/src/Data/TypedEncoding/Internal/Types/CheckedEnc.hs b/src/Data/TypedEncoding/Internal/Types/CheckedEnc.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/TypedEncoding/Internal/Types/CheckedEnc.hs
@@ -0,0 +1,85 @@
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+-- {-# LANGUAGE PolyKinds #-}
+-- {-# LANGUAGE DataKinds #-}
+-- {-# LANGUAGE TypeOperators #-}
+-- {-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE StandaloneDeriving #-}
+{-# LANGUAGE TypeApplications #-}
+{-# LANGUAGE AllowAmbiguousTypes #-}
+{-# LANGUAGE RankNTypes #-}
+
+-- |
+-- Module defines 'CheckedEnc' - untyped ADT version of 'Enc' 
+
+module Data.TypedEncoding.Internal.Types.CheckedEnc where
+
+import           Data.TypedEncoding.Internal.Types.Enc
+import           Data.TypedEncoding.Internal.Types.Common
+import           Data.TypedEncoding.Internal.Class.Util
+import           Data.Proxy
+
+-- $setup
+-- >>> :set -XOverloadedStrings -XMultiParamTypeClasses -XDataKinds -XAllowAmbiguousTypes
+-- >>> import qualified Data.Text as T
+
+
+-- * Untyped Enc
+
+-- constructor is to be treated as Unsafe to Encode and Decode instance implementations
+-- particular encoding instances may expose smart constructors for limited data types
+
+-- | Represents some validated encoded string. 
+--
+-- @CheckedEnc@ is untyped version of 'Data.TypedEncoding.Internal.Types.Enc.Enc'. 
+-- @CheckedEnc@ contains verified encoded data, encoding is visible
+-- at the value level only.
+data CheckedEnc conf str = MkCheckedEnc [EncAnn] conf str
+     deriving (Show, Eq) 
+
+unsafeCheckedEnc:: [EncAnn] -> c -> s -> CheckedEnc c s
+unsafeCheckedEnc = MkCheckedEnc
+
+getCheckedPayload :: CheckedEnc conf str -> str
+getCheckedPayload = snd . getCheckedEncPayload
+
+getCheckedEncPayload :: CheckedEnc conf str -> ([EncAnn], str) 
+getCheckedEncPayload (MkCheckedEnc t _ s) = (t,s)
+
+toCheckedEnc :: forall xs c str . (SymbolList xs) => Enc xs c str -> CheckedEnc c str 
+toCheckedEnc (MkEnc p c s) = 
+        MkCheckedEnc (symbolVals @ xs) c s   
+
+
+fromCheckedEnc :: forall xs c str . SymbolList xs => CheckedEnc c str -> Maybe (Enc xs c str)
+fromCheckedEnc (MkCheckedEnc xs c s) = 
+    let p = Proxy :: Proxy xs
+    in if symbolVals @ xs == xs
+       then Just $ MkEnc p c s
+       else Nothing
+
+------------------------
+
+-- |
+-- >>> let encsometest = MkCheckedEnc ["TEST"] () $ T.pack "hello"
+-- >>> proc_toCheckedEncFromCheckedEnc @'["TEST"] encsometest
+-- True
+-- >>> proc_toCheckedEncFromCheckedEnc @'["TEST1"] encsometest
+-- False
+proc_toCheckedEncFromCheckedEnc :: forall xs c str . (SymbolList xs, Eq c, Eq str) => CheckedEnc c str -> Bool
+proc_toCheckedEncFromCheckedEnc x = (== Just x) . fmap (toCheckedEnc @ xs) . fromCheckedEnc $ x
+
+-- |
+-- >>> let enctest = unsafeSetPayload () "hello" :: Enc '["TEST"] () T.Text
+-- >>> proc_fromCheckedEncToCheckedEnc enctest
+-- True
+proc_fromCheckedEncToCheckedEnc :: forall xs c str . (SymbolList xs, Eq c, Eq str) => Enc xs c str -> Bool
+proc_fromCheckedEncToCheckedEnc x = (== Just x) . fromCheckedEnc . toCheckedEnc $ x
+
+-- |
+-- >>> displ $ unsafeCheckedEnc ["TEST"] () ("hello" :: T.Text)
+-- "MkCheckedEnc [TEST] () (Text hello)"
+instance (Show c, Displ str) => Displ (CheckedEnc c str) where
+    displ (MkCheckedEnc xs c s) = 
+        "MkCheckedEnc " ++ displ xs  ++ " " ++ show c ++ " " ++ displ s
+
diff --git a/src/Data/TypedEncoding/Internal/Types/Common.hs b/src/Data/TypedEncoding/Internal/Types/Common.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/TypedEncoding/Internal/Types/Common.hs
@@ -0,0 +1,4 @@
+module Data.TypedEncoding.Internal.Types.Common where
+
+-- | Represents value level (single) annotation.
+type EncAnn = String    
diff --git a/src/Data/TypedEncoding/Internal/Types/Enc.hs b/src/Data/TypedEncoding/Internal/Types/Enc.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/TypedEncoding/Internal/Types/Enc.hs
@@ -0,0 +1,93 @@
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE PolyKinds #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+-- {-# LANGUAGE TypeApplications #-}
+{-# LANGUAGE AllowAmbiguousTypes #-}
+-- {-# LANGUAGE RankNTypes #-}
+
+-- |
+-- Internal definition of types
+
+module Data.TypedEncoding.Internal.Types.Enc where
+
+import           Data.Proxy
+
+import           Data.TypedEncoding.Internal.Class.Util
+
+-- $setup
+-- >>> :set -XOverloadedStrings -XMultiParamTypeClasses -XDataKinds -XAllowAmbiguousTypes
+-- >>> import qualified Data.Text as T
+
+-- This type contains type level encoding information as well as
+-- configuration and payload.
+data Enc enc conf str where
+    -- | constructor is to be treated as Unsafe to Encode and Decode instance implementations
+    -- particular encoding instances may expose smart constructors for limited data types
+    MkEnc :: Proxy enc -> conf -> str -> Enc enc conf str
+    deriving (Show, Eq) 
+
+-- |
+-- >>> let disptest = unsafeSetPayload () "hello" :: Enc '["TEST"] () T.Text
+-- >>> displ disptest
+-- "MkEnc '[TEST] () (Text hello)"
+instance (SymbolList xs, Show c, Displ str) => Displ ( Enc xs c str) where
+    displ (MkEnc p c s) = 
+        "MkEnc '" ++ displ (Proxy :: Proxy xs) ++ " " ++ show c ++ " " ++ displ s
+
+
+toEncoding :: conf -> str -> Enc '[] conf str
+toEncoding = MkEnc Proxy 
+
+fromEncoding :: Enc '[] conf str -> str
+fromEncoding = getPayload
+
+-- TODO make all implTran functions module-private
+-- TODO disambiguate implEncode from implDecode, from implCheckPrevF for type safety
+-- especially since these are always used in combo with asRecreateErr_ or asUnexpected 
+
+implTranF :: Functor f => (str -> f str) -> Enc enc1 conf str -> f (Enc enc2 conf str)
+implTranF f  = implTranF' (const f)
+
+
+implDecodeF :: Functor f => (str -> f str) -> Enc enc1 conf str -> f (Enc enc2 conf str)
+implDecodeF = implTranF
+
+implCheckPrevF :: Functor f => (str -> f str) -> Enc enc1 conf str -> f (Enc enc2 conf str)
+implCheckPrevF = implTranF
+
+
+implTranF' :: Functor f =>  (conf -> str -> f str) -> Enc enc1 conf str -> f (Enc enc2 conf str)
+implTranF' f (MkEnc _ conf str) = MkEnc Proxy conf <$> f conf str
+
+
+implDecodeF' :: Functor f =>  (conf -> str -> f str) -> Enc enc1 conf str -> f (Enc enc2 conf str)
+implDecodeF' = implTranF'
+
+implTranP :: Applicative f => (str -> str) -> Enc enc1 conf str -> f (Enc enc2 conf str)
+implTranP f  = implTranF' (\c -> pure . f)
+
+implEncodeP :: Applicative f => (str -> str) -> Enc enc1 conf str -> f (Enc enc2 conf str)
+implEncodeP = implTranP
+
+implTranP' :: Applicative f => (conf -> str -> str) -> Enc enc1 conf str -> f (Enc enc2 conf str)
+implTranP' f  = implTranF' (\c -> pure . f c)
+
+implEncodeP' :: Applicative f => (conf -> str -> str) -> Enc enc1 conf str -> f (Enc enc2 conf str)
+implEncodeP' = implTranP'
+
+
+getPayload :: Enc enc conf str -> str  
+getPayload (MkEnc _ _ str) = str
+
+unsafeSetPayload :: conf -> str -> Enc enc conf str 
+unsafeSetPayload  = MkEnc Proxy 
+
+withUnsafeCoerce ::  (s1 -> s2) -> Enc e1 c s1 -> Enc e2 c s2
+withUnsafeCoerce f (MkEnc _ conf str)  = MkEnc Proxy conf (f str)
+
+unsafeChangePayload ::  (s1 -> s2) -> Enc e c s1 -> Enc e c s2
+unsafeChangePayload f (MkEnc p conf str)  = MkEnc p conf (f str) 
diff --git a/src/Data/TypedEncoding/Internal/Types/SomeAnnotation.hs b/src/Data/TypedEncoding/Internal/Types/SomeAnnotation.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/TypedEncoding/Internal/Types/SomeAnnotation.hs
@@ -0,0 +1,34 @@
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE PolyKinds #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE AllowAmbiguousTypes #-}
+{-# LANGUAGE RankNTypes #-}
+
+-- | internally used existential type for taking track of annotations
+module Data.TypedEncoding.Internal.Types.SomeAnnotation where
+
+import           Data.TypedEncoding.Internal.Types.Common
+import           Data.TypedEncoding.Internal.Class.Util
+import           Data.TypedEncoding.Internal.Util
+import           Data.Proxy
+import           GHC.TypeLits
+
+
+data SomeAnnotation where
+    MkSomeAnnotation :: SymbolList xs => Proxy xs -> SomeAnnotation
+
+withSomeAnnotation :: SomeAnnotation -> (forall xs . SymbolList xs => Proxy xs -> r) -> r
+withSomeAnnotation (MkSomeAnnotation p) fn = fn p
+
+-- folds over SomeSymbol list using withSomeSymbol and proxyCons
+someAnnValue :: [EncAnn] -> SomeAnnotation
+someAnnValue xs = 
+     foldr (fn . someSymbolVal) (MkSomeAnnotation (Proxy :: Proxy '[])) xs
+     where 
+         somesymbs = map someSymbolVal xs
+         fn ss (MkSomeAnnotation pxs) = withSomeSymbol ss (\px -> MkSomeAnnotation  (px `proxyCons` pxs)) 
+
+proxyCons :: forall (x :: Symbol) (xs :: [Symbol]) . Proxy x -> Proxy xs -> Proxy (x ': xs)
+proxyCons _ _ = Proxy
diff --git a/src/Data/TypedEncoding/Internal/Types/SomeEnc.hs b/src/Data/TypedEncoding/Internal/Types/SomeEnc.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/TypedEncoding/Internal/Types/SomeEnc.hs
@@ -0,0 +1,61 @@
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+-- {-# LANGUAGE PolyKinds #-}
+-- {-# LANGUAGE DataKinds #-}
+-- {-# LANGUAGE TypeOperators #-}
+-- {-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE StandaloneDeriving #-}
+{-# LANGUAGE TypeApplications #-}
+{-# LANGUAGE AllowAmbiguousTypes #-}
+{-# LANGUAGE RankNTypes #-}
+
+-- |
+-- Module defines 'SomeEnc' - existentially quantified version of @Enc@
+-- and basic combinators
+
+module Data.TypedEncoding.Internal.Types.SomeEnc where
+
+import           Data.TypedEncoding.Internal.Types.Enc
+import           Data.TypedEncoding.Internal.Class.Util
+import           Data.TypedEncoding.Internal.Types.SomeAnnotation
+import           Data.TypedEncoding.Internal.Types.CheckedEnc
+
+-- $setup
+-- >>> :set -XOverloadedStrings -XMultiParamTypeClasses -XDataKinds -XAllowAmbiguousTypes
+-- >>> import qualified Data.Text as T
+
+
+
+-- | Existentially quantified quanitified @Enc@
+-- effectively isomorphic to 'CheckedEnc'
+data SomeEnc conf str where
+    MkSomeEnc :: SymbolList xs => Enc xs conf str -> SomeEnc conf str
+    
+withSomeEnc :: SomeEnc conf str -> (forall xs . SymbolList xs => Enc xs conf str -> r) -> r
+withSomeEnc (MkSomeEnc enc) f = f enc
+
+toSome :: SymbolList xs => Enc xs conf str -> SomeEnc conf str
+toSome = MkSomeEnc
+
+-- | 
+-- >>> let enctest = unsafeSetPayload () "hello" :: Enc '["TEST"] () T.Text
+-- >>> someToChecked . MkSomeEnc $ enctest
+-- MkCheckedEnc ["TEST"] () "hello"
+someToChecked :: SomeEnc conf str -> CheckedEnc conf str
+someToChecked se = withSomeEnc se toCheckedEnc
+
+-- | 
+-- >>> let tst = unsafeCheckedEnc ["TEST"] () "test"
+-- >>> displ $ checkedToSome tst
+-- "Some (MkEnc '[TEST] () test)"
+checkedToSome :: CheckedEnc conf str -> SomeEnc conf str
+checkedToSome (MkCheckedEnc xs c s) = withSomeAnnotation (someAnnValue xs) (\p -> MkSomeEnc (MkEnc p c s))
+
+
+-- |
+-- >>> let enctest = unsafeSetPayload () "hello" :: Enc '["TEST"] () T.Text
+-- >>> displ $ MkSomeEnc enctest
+-- "Some (MkEnc '[TEST] () (Text hello))"
+instance (Show c, Displ str) => Displ (SomeEnc c str) where
+    displ (MkSomeEnc en) = 
+       "Some (" ++ displ en ++ ")"
diff --git a/src/Data/TypedEncoding/Internal/Types/UncheckedEnc.hs b/src/Data/TypedEncoding/Internal/Types/UncheckedEnc.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/TypedEncoding/Internal/Types/UncheckedEnc.hs
@@ -0,0 +1,52 @@
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE PolyKinds #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications #-}
+{-# LANGUAGE AllowAmbiguousTypes #-}
+
+-- |
+-- Internal definition of types
+
+module Data.TypedEncoding.Internal.Types.UncheckedEnc where
+
+import           Data.Proxy
+import           Data.TypedEncoding.Internal.Class.Util
+import           Data.TypedEncoding.Internal.Types.Common
+
+-- $setup
+-- >>> :set -XOverloadedStrings -XMultiParamTypeClasses -XDataKinds -XAllowAmbiguousTypes
+-- >>> import qualified Data.Text as T
+
+
+-- * UncheckedEnc for recreate, similar to CheckedEnc only not verified
+
+-- | Represents some encoded string where encoding was not validated.
+--
+-- Similar to 'Data.TypedEncoding.Internal.Types.CheckedEnc' but unlike
+-- @CheckedEnc@ it can contain payloads that have invalid encoding.
+-- 
+data UncheckedEnc c str = MkUncheckedEnc [EncAnn] c str deriving (Show, Eq)
+
+toUncheckedEnc :: [EncAnn] -> c -> str -> UncheckedEnc c str
+toUncheckedEnc = MkUncheckedEnc
+
+getUncheckedEncAnn :: UncheckedEnc c str -> [EncAnn]
+getUncheckedEncAnn (MkUncheckedEnc ann _ _) = ann
+
+verifyAnn :: forall xs c str . SymbolList xs => UncheckedEnc c str -> Either String (UncheckedEnc c str)
+verifyAnn x@(MkUncheckedEnc xs _ _) = 
+    let p = Proxy :: Proxy xs
+    in if symbolVals @ xs == xs
+       then Right x
+       else Left $ "UncheckedEnc has not matching annotation " ++ displ xs
+
+-- |
+-- >>> displ $ MkUncheckedEnc ["TEST"] () ("hello" :: T.Text)
+-- "MkUncheckedEnc [TEST] () (Text hello)"
+instance (Show c, Displ str) => Displ (UncheckedEnc c str) where
+    displ (MkUncheckedEnc xs c s) = 
+        "MkUncheckedEnc " ++ displ xs ++ " " ++ show c ++ " " ++ displ s
diff --git a/src/Data/TypedEncoding/Internal/Types/Unsafe.hs b/src/Data/TypedEncoding/Internal/Types/Unsafe.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/TypedEncoding/Internal/Types/Unsafe.hs
@@ -0,0 +1,29 @@
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE PolyKinds #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE FlexibleInstances #-}
+
+module Data.TypedEncoding.Internal.Types.Unsafe where
+
+import           Data.Proxy
+import           Data.TypedEncoding.Internal.Types
+
+ 
+-- | Allows to operate within Enc. These are considered unsafe.
+-- keeping the same list of encodings 
+newtype Unsafe enc conf str = Unsafe {runUnsafe :: Enc enc conf str} deriving (Show)
+
+withUnsafe :: (Unsafe e c s1 -> Unsafe e c s2) -> Enc e c s1 -> Enc e c s2
+withUnsafe f enc = runUnsafe . f $ Unsafe enc
+
+instance Functor (Unsafe enc conf) where
+    fmap f (Unsafe (MkEnc p c x)) = Unsafe (MkEnc p c (f x))
+  
+instance Applicative (Unsafe enc ()) where
+    pure = Unsafe . MkEnc Proxy ()  
+    Unsafe (MkEnc p c1 f) <*> Unsafe (MkEnc _ c2 x) = Unsafe (MkEnc p () (f x))  
+
+instance Monad (Unsafe enc ()) where 
+    Unsafe (MkEnc _ _ x) >>= f = f x     
+
diff --git a/src/Data/TypedEncoding/Internal/Util.hs b/src/Data/TypedEncoding/Internal/Util.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/TypedEncoding/Internal/Util.hs
@@ -0,0 +1,26 @@
+
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE RankNTypes #-}
+
+module Data.TypedEncoding.Internal.Util where
+
+import           Data.Proxy
+import           GHC.TypeLits
+
+explainBool :: (a -> err) -> (a, Bool) -> Either err a
+explainBool _ (a, True) = Right a
+explainBool f (a, False) = Left $ f a 
+
+
+-- | Sometimes is easier to pass around a proxy than do TypeApplications
+proxiedId :: Proxy a -> a -> a
+proxiedId _ = id
+
+-- | explicit mapM
+extractEither :: Traversable t => t (Either err a) -> Either err (t a)
+extractEither = sequence -- mapM id
+
+withSomeSymbol :: SomeSymbol -> (forall x. KnownSymbol x => Proxy x -> r) -> r
+withSomeSymbol s fn = case s of 
+    SomeSymbol p -> fn p
diff --git a/src/Data/TypedEncoding/Internal/Utils.hs b/src/Data/TypedEncoding/Internal/Utils.hs
deleted file mode 100644
--- a/src/Data/TypedEncoding/Internal/Utils.hs
+++ /dev/null
@@ -1,13 +0,0 @@
-module Data.TypedEncoding.Internal.Utils where
-
-import           Data.Proxy
-
-explainBool :: (a -> err) -> (a, Bool) -> Either err a
-explainBool _ (a, True) = Right a
-explainBool f (a, False) = Left $ f a 
-
-
-proxiedId :: Proxy a -> a -> a
-proxiedId _ = id
-
-
diff --git a/src/Data/TypedEncoding/Unsafe.hs b/src/Data/TypedEncoding/Unsafe.hs
--- a/src/Data/TypedEncoding/Unsafe.hs
+++ b/src/Data/TypedEncoding/Unsafe.hs
@@ -1,34 +1,12 @@
 {-# LANGUAGE GADTs #-}
 {-# LANGUAGE PolyKinds #-}
-{-# LANGUAGE DeriveFunctor #-}
 {-# LANGUAGE DataKinds #-}
 {-# LANGUAGE TypeOperators #-}
 {-# LANGUAGE FlexibleInstances #-}
 
-module Data.TypedEncoding.Unsafe where
-
-import           Data.Proxy
-import           Data.Functor.Identity
-import           Data.TypedEncoding.Internal.Types
-
- 
--- | Allows to operate within Enc. These are considered unsafe.
--- keeping the same list of encodings 
-newtype Unsafe enc conf str = Unsafe {runUnsafe :: Enc enc conf str} deriving (Show)
-
-withUnsafe :: (Unsafe e c s1 -> Unsafe e c s2) -> Enc e c s1 -> Enc e c s2
-withUnsafe f enc = runUnsafe . f $ Unsafe enc
-
-instance Functor (Unsafe enc conf) where
-    fmap f (Unsafe (MkEnc p c x)) = Unsafe (MkEnc p c (f x))
-  
-instance Applicative (Unsafe enc ()) where
-    pure = Unsafe . MkEnc Proxy ()  
-    Unsafe (MkEnc p c1 f) <*> Unsafe (MkEnc _ c2 x) = Unsafe (MkEnc p () (f x))  
-
-instance Monad (Unsafe enc ()) where 
-    Unsafe (MkEnc _ _ x) >>= f = f x     
-
---TODO JSON instances    
+module Data.TypedEncoding.Unsafe (
+     module Data.TypedEncoding.Internal.Types.Unsafe
+  ) where
 
+import           Data.TypedEncoding.Internal.Types.Unsafe
 
diff --git a/src/Examples/TypedEncoding.hs b/src/Examples/TypedEncoding.hs
--- a/src/Examples/TypedEncoding.hs
+++ b/src/Examples/TypedEncoding.hs
@@ -5,6 +5,8 @@
    , module Examples.TypedEncoding.Conversions
    -- * Adding new encodings, error handling      
    , module Examples.TypedEncoding.DiySignEncoding
+   -- * Converting other types to and from encoded strings 
+   , module Examples.TypedEncoding.ToEncString
    -- * Modifying encoded payload    
    , module Examples.TypedEncoding.Unsafe 
   ) where
@@ -13,3 +15,4 @@
 import           Examples.TypedEncoding.Conversions     
 import           Examples.TypedEncoding.DiySignEncoding  
 import           Examples.TypedEncoding.Unsafe  
+import           Examples.TypedEncoding.ToEncString  
diff --git a/src/Examples/TypedEncoding/Conversions.hs b/src/Examples/TypedEncoding/Conversions.hs
--- a/src/Examples/TypedEncoding/Conversions.hs
+++ b/src/Examples/TypedEncoding/Conversions.hs
@@ -4,6 +4,7 @@
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE TypeApplications #-}
 
 -- | Examples or moving between type annotated encodings
 --
@@ -15,17 +16,17 @@
 module Examples.TypedEncoding.Conversions where
 
 import           Data.TypedEncoding
-import qualified Data.TypedEncoding.Instances.Base64 as EnB64
-import qualified Data.TypedEncoding.Instances.ASCII as EnASCII
-import qualified Data.TypedEncoding.Instances.UTF8  as EnUTF8
-
-import           Data.Proxy
+import qualified Data.TypedEncoding.Instances.Enc.Base64 as EnB64
+import qualified Data.TypedEncoding.Instances.Restriction.ASCII as EnASCII
+-- import qualified Data.TypedEncoding.Instances.Restriction.UTF8  as EnUTF8
 
 import qualified Data.Text as T
 import qualified Data.ByteString as B
 
 -- $setup
--- >>> :set -XOverloadedStrings -XMultiParamTypeClasses -XDataKinds
+-- >>> :set -XOverloadedStrings -XMultiParamTypeClasses -XDataKinds -XTypeApplications
+-- >>> import           Data.TypedEncoding.Instances.Restriction.UTF8 ()
+-- >>> import           Data.Proxy
 --
 -- This module contains some ghci friendly values to play with.
 --
@@ -57,8 +58,9 @@
 
 -- * Subsets
 
+
 helloUtf8B :: Enc '["r-UTF8"] () B.ByteString
-helloUtf8B = inject Proxy helloAsciiB
+helloUtf8B = inject helloAsciiB
 -- ^ To get UTF8 annotation, instead of doing this: 
 --
 -- >>> encodeFAll . toEncoding () $ "HeLlo world" :: Either EncodeEx (Enc '["r-UTF8"] () B.ByteString)
@@ -66,11 +68,11 @@
 -- 
 -- We should be able to convert the ASCII version.
 --
--- This is done using 'Subset' typeclass.
+-- This is done using 'Superset' typeclass.
 --
 -- @inject@ method accepts proxy to specify superset to use.
 --
--- >>> displ $ inject (Proxy :: Proxy "r-UTF8") helloAsciiB
+-- >>> displ $ inject @ "r-UTF8" helloAsciiB
 -- "MkEnc '[r-UTF8] () (ByteString HeLlo world)"
 
 
@@ -78,10 +80,10 @@
 -- * More complex rules
 
 helloUtf8B64B :: Enc '["enc-B64", "r-UTF8"] () B.ByteString
-helloUtf8B64B = encodePart (Proxy :: Proxy '["enc-B64"]) helloUtf8B 
+helloUtf8B64B = encodePart @'["enc-B64"] helloUtf8B 
 -- ^ We put Base64 on the UFT8 ByteString
 --
--- >>> displ $ encodePart (Proxy :: Proxy '["enc-B64"]) helloUtf8B
+-- >>> displ $ encodePart_ (Proxy :: Proxy '["enc-B64"]) helloUtf8B
 -- "MkEnc '[enc-B64,r-UTF8] () (ByteString SGVMbG8gd29ybGQ=)"
 
 helloUtf8B64T :: Enc '["enc-B64"] () T.Text
@@ -152,11 +154,11 @@
 -- * Flattening
 
 b64IsAscii :: Enc '["r-ASCII"] () B.ByteString
-b64IsAscii = flattenAs Proxy helloUtf8B64B
+b64IsAscii = flattenAs helloUtf8B64B
 -- ^ Base 64 encodes binary data as ASCII text. 
 -- thus, we should be able to treat "enc-B64" as "r-ASCII" losing some information.
 -- this is done using 'FlattenAs' type class
 --
--- >>> :t flattenAs (Proxy :: Proxy "r-ASCII") helloUtf8B64B
--- flattenAs (Proxy :: Proxy "r-ASCII") helloUtf8B64B
+-- >>> :t flattenAs @ "r-ASCII" helloUtf8B64B
+-- flattenAs @ "r-ASCII" helloUtf8B64B
 -- ... :: Enc '["r-ASCII"] () B.ByteString
diff --git a/src/Examples/TypedEncoding/DiySignEncoding.hs b/src/Examples/TypedEncoding/DiySignEncoding.hs
--- a/src/Examples/TypedEncoding/DiySignEncoding.hs
+++ b/src/Examples/TypedEncoding/DiySignEncoding.hs
@@ -5,6 +5,8 @@
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications #-}
+
 -- {-# LANGUAGE PartialTypeSignatures #-}
 
 -- | Simple DIY encoding example that "signs" Text with its length.
@@ -27,14 +29,9 @@
 import           Data.TypedEncoding
 import qualified Data.TypedEncoding.Instances.Support as EnT
 
-import           Data.Proxy
-import           Data.Functor.Identity
-import           GHC.TypeLits
-
 import qualified Data.Text as T
 import           Data.Char
 import           Data.Semigroup ((<>))
-import           Control.Arrow
 import           Text.Read (readMaybe)
 
 -- $setup
@@ -104,7 +101,6 @@
 -- >>> recreateFAll . toEncoding () $ payload :: Either RecreateEx (Enc '["my-sign"] () T.Text)
 -- Right (MkEnc Proxy () "11:Hello World")
 
-prxyMySign = Proxy :: Proxy "my-sign"
 
 -- | Because encoding function is pure we can create instance of EncodeF 
 -- that is polymorphic in effect @f@. This is done using 'EnT.implTranP' combinator.
@@ -117,9 +113,9 @@
 -- 'UnexpectedDecodeErr' has Identity instance allowing for decoding that assumes errors are not possible.
 -- For debugging purposes or when unsafe changes to "my-sign" @Error UnexpectedDecodeEx@ instance can be used.
 instance (UnexpectedDecodeErr f, Applicative f) => DecodeF f (Enc ("my-sign" ': xs) c T.Text) (Enc xs c T.Text) where
-    decodeF = EnT.implDecodeF (asUnexpected prxyMySign . decodeSign) 
+    decodeF = EnT.implDecodeF (asUnexpected @"my-sign" . decodeSign) 
 
 -- | Recreation allows effectful @f@ to check for tampering with data.
 -- Implementation simply uses 'EnT.implCheckPrevF' combinator on the recovery function.
 instance (RecreateErr f, Applicative f) => RecreateF f (Enc xs c T.Text) (Enc ("my-sign" ': xs) c T.Text) where   
-    checkPrevF = EnT.implCheckPrevF (asRecreateErr prxyMySign . decodeSign) 
+    checkPrevF = EnT.implCheckPrevF (asRecreateErr @"my-sign" . decodeSign) 
diff --git a/src/Examples/TypedEncoding/Overview.hs b/src/Examples/TypedEncoding/Overview.hs
--- a/src/Examples/TypedEncoding/Overview.hs
+++ b/src/Examples/TypedEncoding/Overview.hs
@@ -1,6 +1,7 @@
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE DataKinds #-}
+{-# LANGUAGE TypeApplications #-}
 
 -- | type-encoding overview examples. 
 --
@@ -10,28 +11,24 @@
 --
 -- This module uses encoding instances found in 
 --
--- * "Data.TypedEncoding.Instances.Base64"
--- * "Data.TypedEncoding.Instances.ASCII"
--- * "Data.TypedEncoding.Instances.Encode.Sample"
+-- * "Data.TypedEncoding.Instances.Enc.Base64"
+-- * "Data.TypedEncoding.Instances.Restriction.ASCII"
+-- * "Data.TypedEncoding.Instances.Do.Sample"
 --
 
 module Examples.TypedEncoding.Overview where
 
 import           Data.TypedEncoding
-import           Data.TypedEncoding.Instances.Base64
-import           Data.TypedEncoding.Instances.ASCII
-import           Data.TypedEncoding.Instances.Encode.Sample
+import           Data.TypedEncoding.Instances.Enc.Base64 ()
+import           Data.TypedEncoding.Instances.Restriction.ASCII ()
+import           Data.TypedEncoding.Instances.Do.Sample
  
-import           GHC.TypeLits
 import qualified Data.ByteString as B
-import qualified Data.ByteString.Lazy as BL
 import qualified Data.Text as T
-import           Data.Proxy
-import           Data.Functor.Identity
 
 
 -- $setup
--- >>> :set -XOverloadedStrings -XMultiParamTypeClasses -XDataKinds
+-- >>> :set -XOverloadedStrings -XMultiParamTypeClasses -XDataKinds -XTypeApplications
 --
 -- This module contains some ghci friendly values to play with.
 --
@@ -68,6 +65,19 @@
 --
 -- >>> recreateFAll . toEncoding () $ "SGVsbG8gV29ybGQ" :: Either RecreateEx (Enc '["enc-B64"] () B.ByteString)
 -- Left (RecreateEx "enc-B64" ("invalid padding"))
+--
+-- The above example start by placing payload in zero-encoded @Enc '[] ()@ type and then apply 'recreateFAll'
+-- this is a good way to recreate encoded type if encoding is known. 
+--
+-- If is it not, 'UncheckedEnc' type can be used. 
+--
+-- (See 'Examples.TypedEncoding.ToEncString' for better example).
+-- 
+-- This module is concerned only with the first approach. 
+--
+-- >>> let unchecked = toUncheckedEnc ["enc-B64"] () ("SGVsbG8gV29ybGQ=" :: T.Text)
+-- >>> verifyUncheckedEnc' @'["enc-B64"] unchecked
+-- Just (Right (MkEnc Proxy () "SGVsbG8gV29ybGQ="))
 helloB64Recovered :: Either RecreateEx (Enc '["enc-B64"] () B.ByteString)
 helloB64Recovered = recreateFAll . toEncoding () $ "SGVsbG8gV29ybGQ="
 
@@ -84,13 +94,13 @@
 
 -- | Double Base64 encoded "Hello World" with one layer of encoding removed
 --
--- >>> decodePart (Proxy :: Proxy '["enc-B64"]) $ helloB64B64 :: Enc '["enc-B64"] () B.ByteString
+-- >>> decodePart @'["enc-B64"] $ helloB64B64 :: Enc '["enc-B64"] () B.ByteString
 -- MkEnc Proxy () "SGVsbG8gV29ybGQ="
 --
 -- >>> helloB64B64PartDecode == helloB64
 -- True
 helloB64B64PartDecode :: Enc '["enc-B64"] () B.ByteString
-helloB64B64PartDecode = decodePart (Proxy :: Proxy '["enc-B64"]) $ helloB64B64
+helloB64B64PartDecode = decodePart @'["enc-B64"] helloB64B64
 
 -- | 'helloB64B64' all the way to 'B.ByteString'
 --
@@ -101,14 +111,14 @@
 -- 
 -- We can also decode all the parts: 
 --
--- >>> fromEncoding . decodePart (Proxy :: Proxy '["enc-B64","enc-B64"]) $ helloB64B64
+-- >>> fromEncoding . decodePart @'["enc-B64","enc-B64"] $ helloB64B64
 -- "Hello World"
 helloB64B64Decoded :: B.ByteString
 helloB64B64Decoded = fromEncoding . decodeAll $ helloB64B64
 
 -- | what happens when we try to recover encoded once text to @Enc '["enc-B64", "enc-B64"]@. 
 --
--- Again, notice the same expression is used as in previous recovery.
+-- Again, notice the same expression is used as in previous recovery. 
 --
 -- >>> recreateFAll . toEncoding () $ "SGVsbG8gV29ybGQ=" :: Either RecreateEx (Enc '["enc-B64", "enc-B64"] () B.ByteString)
 -- Left (RecreateEx "enc-B64" ("invalid padding"))
@@ -120,7 +130,7 @@
 -- * "do-" Encodings
 
 -- |
--- "do-UPPER" (from 'Data.TypedEncoding.Instances.Encode.Sample' module) encoding applied to "Hello World"
+-- "do-UPPER" (from 'Data.TypedEncoding.Instances.Do.Sample' module) encoding applied to "Hello World"
 --
 -- Notice a namespace thing going on, "enc-" is encoding, "do-" is some transformation. 
 -- These are typically not reversible, some could be recoverable.
@@ -144,13 +154,13 @@
 -- * Configuration
 
 -- | Example configuration
-data Config = Config {
+newtype Config = Config {
     sizeLimit :: SizeLimit
   } deriving (Show)
 exampleConf = Config (SizeLimit 8) 
 
-instance HasA Config SizeLimit where
-   has _ = sizeLimit  
+instance HasA SizeLimit Config where
+   has = sizeLimit  
 
 -- | `helloTitle' is needed in following examples
 --
@@ -171,10 +181,10 @@
 --
 -- Instead, encode previously defined 'helloTitle' by reversing it and adding size limit
 --
--- >>> encodePart (Proxy :: Proxy '["do-size-limit", "do-reverse"]) helloTitle :: Enc '["do-size-limit", "do-reverse", "do-Title"] Config T.Text
+-- >>> encodePart @'["do-size-limit", "do-reverse"] helloTitle :: Enc '["do-size-limit", "do-reverse", "do-Title"] Config T.Text
 -- MkEnc Proxy (Config {sizeLimit = SizeLimit {unSizeLimit = 8}}) "dlroW ol"
 helloRevLimit :: Enc '["do-size-limit", "do-reverse", "do-Title"] Config T.Text
-helloRevLimit = encodePart (Proxy :: Proxy '["do-size-limit", "do-reverse"]) helloTitle
+helloRevLimit = encodePart @'["do-size-limit", "do-reverse"] helloTitle
 
 -- >>> encodeAll . toEncoding exampleConf $ "HeLlo world" :: Enc '["enc-B64", "do-size-limit"] Config B.ByteString
 -- MkEnc Proxy (Config {sizeLimit = SizeLimit {unSizeLimit = 8}}) "SGVMbG8gd28="
@@ -183,10 +193,10 @@
 
 -- | ... and we unwrap the B64 part only
 -- 
--- >>> decodePart (Proxy :: Proxy '["enc-B64"]) $ helloLimitB64
+-- >>> decodePart @'["enc-B64"] $ helloLimitB64
 -- MkEnc Proxy (Config {sizeLimit = SizeLimit {unSizeLimit = 8}}) "HeLlo wo"
 helloRevLimitParDec :: Enc '["do-size-limit"] Config B.ByteString
-helloRevLimitParDec =  decodePart (Proxy :: Proxy '["enc-B64"]) $ helloLimitB64
+helloRevLimitParDec =  decodePart @'["enc-B64"] helloLimitB64
 
 
 
@@ -217,7 +227,7 @@
 helloAsciiB64 = encodeFAll . toEncoding () $ "Hello World"
 
 -- |
--- >>> decodePart (Proxy :: Proxy '["enc-B64"]) <$> helloAsciiB64
+-- >>> decodePart @'["enc-B64"] <$> helloAsciiB64
 -- Right (MkEnc Proxy () "Hello World")
 helloAsciiB64PartDec :: Either EncodeEx (Enc '["r-ASCII"] () B.ByteString)
-helloAsciiB64PartDec = decodePart (Proxy :: Proxy '["enc-B64"]) <$> helloAsciiB64 
+helloAsciiB64PartDec = decodePart @'["enc-B64"] <$> helloAsciiB64 
diff --git a/src/Examples/TypedEncoding/ToEncString.hs b/src/Examples/TypedEncoding/ToEncString.hs
new file mode 100644
--- /dev/null
+++ b/src/Examples/TypedEncoding/ToEncString.hs
@@ -0,0 +1,315 @@
+{-# LANGUAGE MultiParamTypeClasses #-}
+-- {-# LANGUAGE PolyKinds #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE DeriveFunctor #-}
+{-# LANGUAGE DeriveFoldable #-}
+{-# LANGUAGE DeriveTraversable #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE TypeApplications #-}
+{-# LANGUAGE AllowAmbiguousTypes #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE PartialTypeSignatures #-}
+
+{-# OPTIONS_GHC -Wno-partial-type-signatures #-}
+
+-- |
+-- This module shows use of 'ToEncString' and 'FromEncString'
+-- and demonstrates /composite/ encoding.
+--
+-- @Show@ and @Read@ classes use a very permissive String type. This often results in 
+-- read errors. type-encoding approach provides type safety over decoding process.
+--
+-- This module includes a simplified email example. This is a non-homogenious case, 
+-- email parts do not have the same encoding. 
+--
+-- Examples here could be made more type safe with use of dependently typed
+-- concepts like @Vect@, @HList@ or variant equivalents of these types.
+--
+-- Current version of typed-encoding does not have dependencies on such types. 
+--
+-- These examples use 'CheckedEnc' when untyped version of 'Enc' is needed.
+-- Alternatively, an existentially quantified 'SomeEnc' type could have been used.
+-- Both are isomorphic.  
+module Examples.TypedEncoding.ToEncString where
+
+import           Data.TypedEncoding
+import qualified Data.TypedEncoding.Instances.Support as EnT
+import           Data.TypedEncoding.Instances.Restriction.Common ()
+import           Data.TypedEncoding.Instances.ToEncString.Common ()
+import           Data.TypedEncoding.Instances.Enc.Base64 ()
+import           Data.TypedEncoding.Instances.Restriction.ASCII ()
+import           Data.TypedEncoding.Instances.Restriction.UTF8 ()
+
+import           Data.Word
+import           Data.Functor.Identity
+import qualified Data.Text as T
+import qualified Data.ByteString as B
+import           Control.Applicative -- ((<|>))
+import           Data.Maybe
+import           Data.Semigroup ((<>))
+
+
+
+-- $setup
+-- >>> :set -XMultiParamTypeClasses -XDataKinds -XPolyKinds -XFlexibleInstances -XTypeApplications -XOverloadedStrings
+-- >>> import qualified Data.List as L
+
+
+-- * IpV4 example
+
+type IpV4 = IpV4F Word8
+
+-- | 
+-- In this example all data fields have the same type. 
+-- This simplifies encoding work as all fields will be encoded the same way.
+-- We use IP address since all fields are single byte size.
+data IpV4F a = IpV4F {
+     oct1 :: a
+     , oct2 :: a
+     , oct3 :: a
+     , oct4 :: a
+   } deriving (Show, Functor, Foldable)
+
+tstIp :: IpV4
+tstIp = IpV4F 128 1 1 10
+
+
+
+-- |
+-- In this example @toEncString@ converts 'IpV4' to @Enc '["r-IPv4"] Text@.
+--  
+-- This is done with help of existing @"r-Word8-decimal"@ annotation defined
+-- in "Data.TypedEncoding.Instances.Restriction.Common"
+--
+-- >>> toEncString @"r-IPv4" @T.Text tstIp
+-- MkEnc Proxy () "128.1.1.10"
+--
+-- Implementation is a classic map reduce where reduce is done with help of
+-- 'EnT.foldEncStr'
+--
+-- >>> let fn a b = if b == "" then a else a <> "." <> b
+-- >>> let reduce = EnT.foldEncStr @'["r-IPv4"] @'["r-Word8-decimal"] () fn
+-- >>>  displ . reduce . fmap toEncString $ tstIp
+-- "MkEnc '[r-IPv4] () 128.1.1.10" 
+--
+-- Note lack of type safety here, the same code would work just fine if we added
+-- 5th field to 'IpV4F' constructor.  
+--
+-- Using something like a dependently typed
+--
+-- @
+-- Vect 4 (Enc '["r-Word8-decimal"] () T.Text)
+-- @ 
+-- 
+-- would have improved this situation.
+-- @HList@ could be used for record types with heterogeneous fields.
+--
+-- Currently, 'type-encoding' library does not have these types in scope.  
+instance ToEncString "r-IPv4" T.Text Identity IpV4 where
+    toEncStringF = Identity . reduce . map
+      where map :: IpV4F Word8 -> IpV4F (Enc '["r-Word8-decimal"] () T.Text) 
+            map = fmap toEncString
+
+            reduce :: IpV4F (Enc '["r-Word8-decimal"] () T.Text) -> Enc '["r-IPv4"] () T.Text 
+            reduce = EnT.foldEncStr () (\a b-> if b == "" then a else a <> "." <> b) 
+
+-- |
+--
+-- >>> let enc = toEncString @"r-IPv4" @T.Text tstIp
+-- >>> fromEncString @IpV4 enc
+-- IpV4F {oct1 = 128, oct2 = 1, oct3 = 1, oct4 = 10}
+--
+-- To get 'IpV4' out of the string we need to reverse previous @reduce@.
+-- This is currently done using helper 'EnT.splitPayload' combinator. 
+--
+-- >>> EnT.splitPayload @ '["r-Word8-decimal"] (T.splitOn $ T.pack ".") $ enc 
+-- [MkEnc Proxy () "128",MkEnc Proxy () "1",MkEnc Proxy () "1",MkEnc Proxy () "10"]
+-- 
+-- The conversion of a list to IpV4F needs handle errors but these errors 
+-- are considered unexpected.
+--
+-- Note, again, the error condition exposed by this implementation could have been avoided
+-- if 'EnT.splitPayload' returned fixed size @Vect 4@.
+instance (UnexpectedDecodeErr f, Applicative f) => FromEncString IpV4 f T.Text "r-IPv4" where   
+    fromEncStringF = fmap map . unreduce
+      where unreduce :: Enc '["r-IPv4"] () T.Text -> f (IpV4F (Enc '["r-Word8-decimal"] () T.Text))
+            unreduce = asUnexpected @"r-IPv4" . recover . EnT.splitPayload @ '["r-Word8-decimal"] (T.splitOn ".")
+            
+            map :: IpV4F (Enc '["r-Word8-decimal"] () T.Text) -> IpV4F Word8 
+            map = fmap fromEncString
+
+            recover ::  Show a => [a] -> Either String (IpV4F a)
+            recover [o1,o2,o3,o4] = pure $ IpV4F o1 o2 o3 o4
+            recover x = Left $ "Invalid Content" ++ show x
+
+
+
+
+-- * Simplified email example
+
+
+-- | Simplified Part header  
+type PartHeader = [String]
+
+-- | Simplified Email header  
+type EmailHeader = String
+
+-- | This section shows a type safe processing of emails.
+--
+-- 'SimplifiedEmailF' is an over-simplified email type, it has parts that can be either 
+-- 
+-- * binary and have to be Base 64 encoded or 
+-- * are text that have either UTF8 or ASCII character set 
+--
+-- The text parts can be optionally can be Base 64 encoded but do not have to be.
+--
+-- For simplicity, the layout of simplified headers is assumed the same as encoding annotations in this library.
+data SimplifiedEmailF a = SimplifiedEmailF {
+          emailHeader :: EmailHeader
+          , parts :: [a]
+      } deriving (Show, Eq, Functor, Foldable, Traversable)
+
+type SimplifiedEmail = SimplifiedEmailF (PartHeader, B.ByteString)
+
+type SimplifiedEmailEncB = SimplifiedEmailF (CheckedEnc () B.ByteString)
+
+-- TODO
+-- type SimplifiedEmailEncT = SimplifiedEmailF (CheckedEnc () T.Text)
+
+-- | @tstEmail@ contains some simple data to play with
+tstEmail :: SimplifiedEmail
+tstEmail = SimplifiedEmailF {
+      emailHeader = "Some Header"
+      , parts = [
+        (["enc-B64","image"], "U29tZSBBU0NJSSBUZXh0") 
+        , (["enc-B64","r-ASCII"], "U29tZSBBU0NJSSBUZXh0")
+        , (["enc-B64","r-UTF8"], "U29tZSBVVEY4IFRleHQ=") 
+        , (["r-ASCII"], "Some ASCII plain text") 
+         ]
+  }
+
+-- | 
+-- This example encodes fields in 'SimplifiedEmailF' into an untyped version of @Enc@ which 
+-- stores verified encoded data and encoding information is stored at the value level: 
+-- @CheckedEnc () B.ByteString@.
+-- 
+-- Part of email are first converted to 'UncheckedEnc' (that stores encoding information at the value level as well).
+-- 'UncheckedEnc'  that can easily represent parts of the email
+--
+-- >>> let part = parts tstEmail L.!! 2
+-- >>> part
+-- (["enc-B64","r-UTF8"],"U29tZSBVVEY4IFRleHQ=")
+-- >>> let unchecked = toUncheckedEnc (fst part) () (snd part)
+-- >>> unchecked 
+-- MkUncheckedEnc ["enc-B64","r-UTF8"] () "U29tZSBVVEY4IFRleHQ="
+--
+-- We can play 'Alternative' ('<|>') game (we acually use @Maybe@) with final option being a 'RecreateEx' error:
+--
+-- >>> verifyUncheckedEnc' @'["enc-B64","r-ASCII"] $ unchecked
+-- Nothing
+-- >>> verifyUncheckedEnc' @'["enc-B64","r-UTF8"] $ unchecked
+-- Just (Right (MkEnc Proxy () "U29tZSBVVEY4IFRleHQ="))
+--
+-- Since the data is heterogeneous (each piece has a different encoding annotation), we need wrap the result in another plain ADT: 'CheckedEnc'.
+-- 
+-- 'CheckedEnc' is similar to 'UncheckedEnc' with the difference that the only (safe) way to get values of this type is
+-- from properly encoded 'Enc' values. 
+--
+-- Using 'unsafeCheckedEnc' would break type safety here. 
+-- 
+-- It is important to handle all cases during encoding so decoding errors become impossible.
+--
+-- Again, use of dependently typed variant types that could enumerate all possible encodings
+-- would made this code nicer.
+recreateEncoding :: SimplifiedEmail -> Either RecreateEx SimplifiedEmailEncB
+recreateEncoding = mapM encodefn
+  where 
+        -- | simplified parse header assumes email has the same layout as encodings
+        -- image is ingored, since [enc-B64] annotation on ByteString permits base 64
+        -- encoded bytes
+        parseHeader :: PartHeader -> [EncAnn]
+        parseHeader ["enc-B64","image"] = ["enc-B64"] 
+        parseHeader x = x
+
+        encodefn :: (PartHeader, B.ByteString) -> Either RecreateEx (CheckedEnc () B.ByteString)
+        encodefn (parth, body) = 
+          runAlternatives' (fromMaybe def) [try1, try2, try3, try4, try5] body
+          where
+              unchecked = toUncheckedEnc (parseHeader parth) () 
+              try1 = fmap (fmap toCheckedEnc) . verifyUncheckedEnc' @'["enc-B64","r-UTF8"] . unchecked
+              try2 = fmap (fmap toCheckedEnc) . verifyUncheckedEnc' @'["enc-B64","r-ASCII"] . unchecked
+              try3 = fmap (fmap toCheckedEnc) . verifyUncheckedEnc' @'["r-ASCII"] . unchecked
+              try4 = fmap (fmap toCheckedEnc) . verifyUncheckedEnc' @'["r-UTF8"] . unchecked
+              try5 = fmap (fmap toCheckedEnc) . verifyUncheckedEnc' @'["enc-B64"] . unchecked
+              def =  Left $ recreateErrUnknown ("Invalid Header " ++ show parth) 
+
+
+-- | 
+-- Example decodes parts of email that are base 64 encoded text and nothing else.
+--
+-- This provides a type safety assurance that we do not decode certain parts of email
+-- (like trying to decode base 64 on a plain text part).
+--
+-- >>> decodeB64ForTextOnly <$> recreateEncoding tstEmail
+-- Right (SimplifiedEmailF {emailHeader = "Some Header", parts = [MkCheckedEnc ["enc-B64"] () "U29tZSBBU0NJSSBUZXh0",MkCheckedEnc ["r-ASCII"] () "Some ASCII Text",MkCheckedEnc ["r-UTF8"] () "Some UTF8 Text",MkCheckedEnc ["r-ASCII"] () "Some ASCII plain text"]})
+--
+-- Combinator @fromCheckedEnc \@'["enc-B64", "r-UTF8"]@ acts as a selector and picks only the
+-- @["enc-B64", "r-UTF8"]@ values from our 'Traversable' type. 
+--
+-- We play the ('<|>') game on all the selectors we want picking and decoding right pieces only.
+--
+-- Imagine this is one of the pieces:
+--
+-- >>> let piece = unsafeCheckedEnc ["enc-B64","r-ASCII"] () ("U29tZSBBU0NJSSBUZXh0" :: B.ByteString)
+-- >>> displ piece
+-- "MkCheckedEnc [enc-B64,r-ASCII] () (ByteString U29tZSBBU0NJSSBUZXh0)"
+--
+-- This code will not pick it up:
+--
+-- >>> fromCheckedEnc @ '["enc-B64", "r-UTF8"] $ piece
+-- Nothing
+--
+-- But this one will:
+--
+-- >>> fromCheckedEnc @ '["enc-B64", "r-ASCII"]  $ piece
+-- Just (MkEnc Proxy () "U29tZSBBU0NJSSBUZXh0")
+--
+-- so we can apply the decoding on the selected piece 
+--
+-- >>> fmap (toCheckedEnc . decodePart @'["enc-B64"]) . fromCheckedEnc @ '["enc-B64", "r-ASCII"] $ piece
+-- Just (MkCheckedEnc ["r-ASCII"] () "Some ASCII Text")
+
+decodeB64ForTextOnly :: SimplifiedEmailEncB -> SimplifiedEmailEncB
+decodeB64ForTextOnly = fmap (runAlternatives fromMaybe [tryUtf8, tryAscii]) 
+  where
+    tryUtf8, tryAscii :: CheckedEnc c B.ByteString -> Maybe (CheckedEnc c B.ByteString)
+    tryUtf8 = fmap (toCheckedEnc . decodeToUtf8) . fromCheckedEnc @ '["enc-B64", "r-UTF8"] 
+    tryAscii = fmap (toCheckedEnc . decodeToAscii) . fromCheckedEnc @ '["enc-B64", "r-ASCII"] 
+ 
+    decodeToUtf8 :: Enc '["enc-B64", "r-UTF8"] c B.ByteString -> _
+    decodeToUtf8 = decodePart @'["enc-B64"]
+
+    decodeToAscii :: Enc '["enc-B64", "r-ASCII"] c B.ByteString -> _
+    decodeToAscii = decodePart @'["enc-B64"]
+
+
+-- * Helpers
+
+-- | Provides easy to read encoding information
+instance Displ a => Displ (IpV4F a) where
+    displ = show . fmap displ
+
+-- | Provides easy to read encoding information
+instance Displ a => Displ (SimplifiedEmailF a) where
+    displ = show . fmap displ    
+
+runAlternatives' :: Alternative f => (f b -> b) -> [a -> f b] -> a -> b
+runAlternatives' defF fns = defF . alternatives fns
+
+runAlternatives :: Alternative f => (a -> f b -> b) -> [a -> f b] -> a -> b
+runAlternatives defF fns a = defF a . alternatives fns $ a
+
+alternatives :: Alternative f => [a -> f b] -> a -> f b
+alternatives fns a = foldr ((<|>) . ($ a)) empty fns
diff --git a/src/Examples/TypedEncoding/Unsafe.hs b/src/Examples/TypedEncoding/Unsafe.hs
--- a/src/Examples/TypedEncoding/Unsafe.hs
+++ b/src/Examples/TypedEncoding/Unsafe.hs
@@ -14,18 +14,13 @@
 
 module Examples.TypedEncoding.Unsafe where
 
-
-import           Data.Proxy
-
 import qualified Data.Text as T
-
-import           Data.Char
+import           Data.Semigroup ((<>))
 
 import           Data.TypedEncoding
-import qualified Data.TypedEncoding.Instances.ASCII as EnASCII
 import qualified Data.TypedEncoding.Unsafe as Unsafe
+import qualified Data.TypedEncoding.Instances.Restriction.ASCII()
 
-import           Data.Semigroup ((<>))
 
 -- $setup
 -- >>> :set -XOverloadedStrings -XMultiParamTypeClasses -XDataKinds
@@ -48,6 +43,8 @@
 -- >>> recreateFAll . toEncoding () $ newPayload :: Either RecreateEx (Enc '["r-ASCII"] () T.Text)
 -- Right (MkEnc Proxy () "HELLO some extra stuff")
 --
+-- Alternatively, 'UncheckedEnc' type can be used in recreation, see 'Examples.TypedEncoding.Overview'
+-- 
 modifiedAsciiT :: Either RecreateEx (Enc '["r-ASCII"] () T.Text)
 modifiedAsciiT =  recreateFAll . toEncoding () . ( <> " some extra stuff") . getPayload $ exAsciiT
   
@@ -70,7 +67,7 @@
 -- but @Enc '["r-ASCII"] () T.Text@ does not expose it
 -- We use Functor instance of Unsafe wrapper type to accomplish this
 toLowerAscii :: Either EncodeEx (Enc '["r-ASCII"] () T.Text)
-toLowerAscii = exAsciiTE >>= pure . Unsafe.withUnsafe (fmap T.toLower)
+toLowerAscii = Unsafe.withUnsafe (fmap T.toLower) <$> exAsciiTE
 
 -- | 
 -- Similar example uses applicative instance of 'Unsafe.Unsafe'
diff --git a/test/Spec.hs b/test/Spec.hs
--- a/test/Spec.hs
+++ b/test/Spec.hs
@@ -1,3 +1,3 @@
 -- {-# OPTIONS_GHC -F -pgmF doctest-discover #-}
 main :: IO ()
-main = putStrLn "Test suite not yet implemented"
+main = putStrLn "Only doctest suite is implemented, no other tests"
diff --git a/typed-encoding.cabal b/typed-encoding.cabal
--- a/typed-encoding.cabal
+++ b/typed-encoding.cabal
@@ -4,10 +4,10 @@
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: e2dc0ab6f8312959f012e795327b2395efd87de964449886a61a2cc19f64accd
+-- hash: 1589fa6653cfa6d1278a74078d61a95a0fe2caa0df5157deafd3f3dc4644385d
 
 name:           typed-encoding
-version:        0.1.0.0
+version:        0.2.0.0
 synopsis:       Type safe string transformations
 description:    See README.md in the project github repository.
 category:       Data, Text
@@ -30,24 +30,42 @@
 library
   exposed-modules:
       Data.TypedEncoding
-      Data.TypedEncoding.Instances.ASCII
-      Data.TypedEncoding.Instances.Base64
-      Data.TypedEncoding.Instances.Encode.Sample
+      Data.TypedEncoding.Instances.Do.Sample
+      Data.TypedEncoding.Instances.Enc.Base64
+      Data.TypedEncoding.Instances.Restriction.ASCII
+      Data.TypedEncoding.Instances.Restriction.Common
+      Data.TypedEncoding.Instances.Restriction.UTF8
       Data.TypedEncoding.Instances.Support
-      Data.TypedEncoding.Instances.UTF8
+      Data.TypedEncoding.Instances.ToEncString.Common
       Data.TypedEncoding.Internal.Class
+      Data.TypedEncoding.Internal.Class.Decode
+      Data.TypedEncoding.Internal.Class.Encode
+      Data.TypedEncoding.Internal.Class.IsStringR
+      Data.TypedEncoding.Internal.Class.Recreate
+      Data.TypedEncoding.Internal.Class.Util
+      Data.TypedEncoding.Internal.Combinators
+      Data.TypedEncoding.Internal.Instances.Combinators
       Data.TypedEncoding.Internal.Types
-      Data.TypedEncoding.Internal.Utils
+      Data.TypedEncoding.Internal.Types.CheckedEnc
+      Data.TypedEncoding.Internal.Types.Common
+      Data.TypedEncoding.Internal.Types.Enc
+      Data.TypedEncoding.Internal.Types.SomeAnnotation
+      Data.TypedEncoding.Internal.Types.SomeEnc
+      Data.TypedEncoding.Internal.Types.UncheckedEnc
+      Data.TypedEncoding.Internal.Types.Unsafe
+      Data.TypedEncoding.Internal.Util
       Data.TypedEncoding.Unsafe
       Examples.TypedEncoding
       Examples.TypedEncoding.Conversions
       Examples.TypedEncoding.DiySignEncoding
       Examples.TypedEncoding.Overview
+      Examples.TypedEncoding.ToEncString
       Examples.TypedEncoding.Unsafe
   other-modules:
       Paths_typed_encoding
   hs-source-dirs:
       src
+  ghc-options: -fwarn-unused-imports -fwarn-incomplete-patterns -fprint-explicit-kinds
   build-depends:
       base >=4.7 && <5
     , base64-bytestring >=1.0 && <1.1
