diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# Morpheus GraphQL [![Hackage](https://img.shields.io/hackage/v/morpheus-graphql.svg)](https://hackage.haskell.org/package/morpheus-graphql) [![Build Status](https://api.travis-ci.com/morpheusgraphql/morpheus-graphql.svg?branch=master)](https://travis-ci.com/morpheusgraphql/morpheus-graphql)
+# Morpheus GraphQL [![Hackage](https://img.shields.io/hackage/v/morpheus-graphql.svg)](https://hackage.haskell.org/package/morpheus-graphql) [![CircleCI](https://circleci.com/gh/morpheusgraphql/morpheus-graphql.svg?style=svg)](https://circleci.com/gh/morpheusgraphql/morpheus-graphql)
 
 Build GraphQL APIs with your favourite functional language!
 
@@ -14,7 +14,7 @@
 
 To get started with Morpheus, you first need to add it to your project's dependencies, as follows (assuming you're using hpack):
 
-package.yml
+_package.yml_
 
 ```yaml
 dependencies:
@@ -23,53 +23,77 @@
 
 Additionally, you should tell stack which version to pick:
 
-stack.yml
+_stack.yml_
 
 ```yaml
-resolver: lts-12.0 # or greater
+resolver: lts-13.24
+
 extra-deps:
   - megaparsec-7.0.5
   - aeson-1.4.4.0
   - time-compat-1.9.2.2
-  - morpheus-graphql-0.2.2
 ```
 
 As Morpheus is quite new, make sure stack can find morpheus-graphql by running `stack update`
 
 ### Building your first GrqphQL API
 
-### with GraphQL syntax and Haskell QuasiQuotes
+### with GraphQL syntax
 
+_schema.gql_
+
+```gql
+type Query {
+  deity(name: String!): Deity!
+}
+
+type Deity {
+  name: String!
+  power: String
+}
+```
+
+_API.hs_
+
 ```haskell
+{-# LANGUAGE DeriveGeneric         #-}
+{-# LANGUAGE FlexibleContexts      #-}
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE NamedFieldPuns        #-}
+{-# LANGUAGE OverloadedStrings     #-}
+{-# LANGUAGE ScopedTypeVariables   #-}
+{-# LANGUAGE TemplateHaskell       #-}
+{-# LANGUAGE TypeFamilies          #-}
 
-[gqlDocument|
-  type Query {
-    deity (uid: Text!): Deity!
-  }
+module API (api) where
 
-  type Deity {
-    name  : Text!
-    power : Text
-  }
-|]
+import qualified Data.ByteString.Lazy.Char8 as B
 
-rootResolver :: GQLRootResolver IO () () Query () ()
+import           Data.Morpheus              (interpreter)
+import           Data.Morpheus.Document     (importGQLDocumentWithNamespace)
+import           Data.Morpheus.Types        (GQLRootResolver (..), IORes)
+import           Data.Text                  (Text)
+
+importGQLDocumentWithNamespace "schema.gql"
+
+rootResolver :: GQLRootResolver IO () () (Query IORes) () ()
 rootResolver =
-  GQLRootResolver {queryResolver = return Query {deity}, mutationResolver = pure (), subscriptionResolver = pure ()}
+  GQLRootResolver
+    {queryResolver = return Query {queryDeity}, mutationResolver = pure (), subscriptionResolver = pure ()}
   where
-    deity DeityArgs {uid} = pure Deity {name, power}
+    queryDeity QueryDeityArgs {queryDeityArgsName} = pure Deity {deityName, deityPower}
       where
-        name _ = pure "Morpheus"
-        power _ = pure (Just "Shapeshifting")
+        deityName _ = pure "Morpheus"
+        deityPower _ = pure (Just "Shapeshifting")
 
-gqlApi :: ByteString -> IO ByteString
-gqlApi = interpreter rootResolver
+api :: ByteString -> IO ByteString
+api = interpreter rootResolver
 ```
 
 Template Haskell Generates types: `Query` , `Deity`, `DeityArgs`, that can be used by `rootResolver`
 
-generated types are not compatible with `Mutation`, `Subscription`,
-they can be used only in `Query`, but this issue will be fixed in next release
+`importGQLDocumentWithNamespace` will generate Types with namespaced fields. if you don't need napespacing use `importGQLDocument`
 
 ### with Native Haskell Types
 
@@ -79,7 +103,7 @@
 ```haskell
 data Query = Query
   { deity :: DeityArgs -> IORes Deity
-  } deriving (Generic)
+  } deriving (Generic, GQLType)
 
 data Deity = Deity
   { fullName :: Text         -- Non-Nullable Field
@@ -260,7 +284,7 @@
 ```haskell
 newtype Mutation = Mutation
   { createDeity :: Form -> IOMutRes Deity
-  } deriving (Generic)
+  } deriving (Generic, GQLType)
 
 createDeityMutation :: Form -> IOMutRes Deity
 createDeityMutation = ...
@@ -298,15 +322,15 @@
 
 newtype Query = Query
   { deity :: () -> IORes Deity
-  } deriving (Generic)
+  } deriving (Generic, GQLType)
 
 newtype Mutation = Mutation
   { createDeity :: () -> IOMutRes Channel Content Deity
-  } deriving (Generic)
+  } deriving (Generic, GQLType)
 
 newtype Subscription = Subscription
   { newDeity :: () -> IOSubRes Channel Content Deity
-  } deriving (Generic)
+  } deriving (Generic, GQLType)
 
 rootResolver :: GQLRootResolver IO Channel Content Query Mutation Subscription
 rootResolver =
@@ -318,11 +342,11 @@
   where
     fetchDeity = resolver $ dbDeity "" Nothing
     createDeity _args = toMutResolver [Event {channels = [ChannelA], content = ContentA 1}] fetchDeity
-    newDeity _args = Event {channels = [ChannelA], content}
+    newDeity _args = SubResolver {subChannels = [ChannelA], subResolver}
       where
-        content (Event [ChannelA] (ContentA _value)) = resolver $ dbDeity "" Nothing -- resolve New State
-        content (Event [ChannelA] (ContentB value))  = resolver $ dbDeity value Nothing -- resolve New State
-        content _                                    = fetchDeity -- Resolve Old State
+        subResolver (Event [ChannelA] (ContentA _value)) = resolver $ dbDeity "" Nothing -- resolve New State
+        subResolver (Event [ChannelA] (ContentB value))  = resolver $ dbDeity value Nothing -- resolve New State
+        subResolver _                                    = fetchDeity -- Resolve Old State
 ```
 
 ## Morpheus `GraphQL Client` with Template haskell QuasiQuotes
@@ -397,7 +421,6 @@
 
 - Medium future:
   - Stabilize API
-  - Specification-isomorphic introspection
   - Specification-isomorphic error handling
 - Long term:
   - Support all possible GQL features
diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,33 +1,117 @@
+## [0.3.0] - 04.10.2019
+
+### Added
+
+- user can import GraphQL Document and generate types with it.
+
+  ```haskell
+    importGQLDocument "API.gql"
+  ```
+
+  this will generate types defined in `API.gql`
+
+### Fixed
+
+- `String` defined in GQLDcoument will be converted to `Text` by template haskell
+
+- `importGQLDocument` and `gqlDocument` supports Mutation, Subscription and Resolvers with custom Monad
+
+  for example. if we have:
+
+  ```gql
+  type Deity {
+    name: String!
+    power: Power!
+  }
+  ```
+
+  where `Power` is another object defined by gql schema.
+  template haskell will represent this type as:
+
+  ```haskell
+     data Deity m = Deity {
+       name :: () -> m String
+       power :: () -> m (Power m)
+     }
+  ```
+
+  where `m` is resolver Monad.
+
+- `importGQLDocumentWithNamespace` generates namespaced haskell records. so that you have no more problem with name collision.
+  from this gql type:
+
+  ```gql
+  type Deity {
+    name: (id:Int)String!
+    power: Power!
+  }
+  ```
+
+  will be generated.
+
+  ```haskell
+  $(importGQLDocumentWithNamespace "examples/Sophisticated/api.gql")
+
+  data Deity m = Deity {
+    DeityName :: DeityNameArgs -> m String
+    DeityPower :: () -> m (Power m)
+  }
+
+  data DeityNameArgs = DeityNameArgs {
+    deityNameId :: Int
+  }
+  ```
+
+### Changed
+
+- `GQLType` is mandatory for every GQL Type (including Query, Mutation and Subscription)
+- subscription Resolver changed
+
+  from:
+
+  ```haskell
+    Subscription {newDeity = \args -> Event {channels = [ChannelA], content = newDeityResolver } }
+  ```
+
+  to:
+
+  ```haskell
+    Subscription {newDeity = \args -> SubResolver {subChannels = [ChannelA], subResolver = newDeityResolver } }
+  ```
+
 ## [0.2.2] - 30.08.2019
 
 ### Fixed
+
 - Parser Supports GraphQL multiline comments
 - Morpheus GraphQL Client: Support GraphQL Alias
 - Support of GraphQL Interfaces on GraphQL Document:
-    ```gql
-    # simple.gql
-    interface Node {
-      nodeId: ID!
-    }
 
-    type SimpleType implements Node {
-      nodeId: ID!
-      name: String!
-    }
-    ```
+  ```gql
+  # simple.gql
+  interface Node {
+    nodeId: ID!
+  }
 
-    morpheus compiler will read interfaces and validate implements.
-    template haskell will generate haskell types only for types not for interfaces.
+  type SimpleType implements Node {
+    nodeId: ID!
+    name: String!
+  }
+  ```
 
-    haskell type from `simple.gql`:
-    ```haskell
-     data SimpleType = SimpleType {
-        nodeId :: ID!
-        name   :: Text!
-      }  deriving (Generic)
-    ```
+  morpheus compiler will read interfaces and validate implements.
+  template haskell will generate haskell types only for types not for interfaces.
 
-    at the time compiler does not validates field Arguments by interface
+  haskell type from `simple.gql`:
+
+  ```haskell
+   data SimpleType = SimpleType {
+      nodeId :: ID!
+      name   :: Text!
+    }  deriving (Generic)
+  ```
+
+  at the time compiler does not validates field Arguments by interface
 
 ## [0.2.1] - 23.08.2019
 
diff --git a/examples/Client/Client.hs b/examples/Client/Client.hs
new file mode 100644
--- /dev/null
+++ b/examples/Client/Client.hs
@@ -0,0 +1,71 @@
+{-# LANGUAGE DeriveAnyClass        #-}
+{-# LANGUAGE DeriveGeneric         #-}
+{-# LANGUAGE DerivingStrategies    #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE NamedFieldPuns        #-}
+{-# LANGUAGE OverloadedStrings     #-}
+{-# LANGUAGE QuasiQuotes           #-}
+{-# LANGUAGE TemplateHaskell       #-}
+{-# LANGUAGE TypeFamilies          #-}
+
+module Client.Client
+  ( fetchHero
+  , fetUser
+  ) where
+
+import           Data.ByteString.Lazy.Char8 (ByteString)
+import           Data.Morpheus.Client       (Fetch (..), defineByDocumentFile, defineByIntrospectionFile, gql)
+import           Data.Morpheus.Types        (ScalarValue (..))
+
+defineByIntrospectionFile
+  "./assets/introspection.json"
+  [gql|
+    # Query Hero with Compile time Validation
+    query GetUser ($userCoordinates: Coordinates!)
+      {
+        myUser: user {
+           boo3: name
+           email
+           address (coordinates: $userCoordinates ){
+            city
+           }
+        }
+      }
+  |]
+
+defineByDocumentFile
+  "./assets/simple.gql"
+  [gql|
+    # Query Hero with Compile time Validation
+    query GetHero ($god: Realm, $charID: String!)
+      {
+        deity (mythology:$god) {
+          power
+          fullName
+        }
+        character(characterID: $charID ) {
+          ...on Creature {
+            creatureName
+          }
+          ...on Human {
+            lifetime
+            profession
+          }
+        }
+      }
+  |]
+
+ioRes :: ByteString -> IO ByteString
+ioRes req = do
+  print req
+  return
+    "{\"data\":{\"deity\":{ \"fullName\": \"name\" }, \"character\":{ \"__typename\":\"Human\", \"lifetime\": \"Lifetime\", \"profession\": \"Artist\" }  }}"
+
+fetchHero :: IO (Either String GetHero)
+fetchHero = fetch ioRes GetHeroArgs {god = Just Realm {owner = "Zeus", surface = Just 10}, charID = "Hercules"}
+
+fetUser :: (ByteString -> IO ByteString) -> IO (Either String GetUser)
+fetUser api = fetch api userArgs
+  where
+    userArgs :: Args GetUser
+    userArgs = GetUserArgs {userCoordinates = Coordinates {longitude = [], latitude = String "1"}}
diff --git a/examples/Deprecated/API.hs b/examples/Deprecated/API.hs
deleted file mode 100644
--- a/examples/Deprecated/API.hs
+++ /dev/null
@@ -1,241 +0,0 @@
-{-# LANGUAGE DataKinds         #-}
-{-# LANGUAGE DeriveGeneric     #-}
-{-# LANGUAGE NamedFieldPuns    #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE PolyKinds         #-}
-{-# LANGUAGE RankNTypes        #-}
-{-# LANGUAGE TypeFamilies      #-}
-{-# LANGUAGE TypeInType        #-}
-{-# LANGUAGE TypeOperators     #-}
-
-module Deprecated.API
-  ( gqlRoot
-  , Channel
-  , Content
-  ) where
-
-import           Data.Map            (Map)
-import qualified Data.Map            as M (fromList)
-import           Data.Set            (Set)
-import qualified Data.Set            as S (fromList)
-import           Data.Text           (Text, pack)
-import           Data.Typeable       (Typeable)
-import           GHC.Generics        (Generic)
-
--- MORPHEUS
-import           Data.Morpheus.Kind  (ENUM, INPUT_OBJECT, INPUT_UNION, OBJECT, SCALAR, UNION)
-import           Data.Morpheus.Types (Event (..), GQLRootResolver (..), GQLScalar (..), GQLType (..), ID, IOMutRes,
-                                      IORes, IOSubRes, Resolver, ScalarValue (..), mutResolver, resolver)
-
-newtype Cat = Cat
-  { catName :: Text
-  } deriving (Show, Generic)
-
-instance GQLType Cat where
-  type KIND Cat = INPUT_OBJECT
-
-newtype Dog = Dog
-  { dogName :: Text
-  } deriving (Show, Generic)
-
-instance GQLType Dog where
-  type KIND Dog = INPUT_OBJECT
-
-newtype Bird = Bird
-  { birdName :: Text
-  } deriving (Show, Generic)
-
-instance GQLType Bird where
-  type KIND Bird = INPUT_OBJECT
-
-data Animal
-  = CAT Cat
-  | DOG Dog
-  | BIRD Bird
-  deriving (Show, Generic)
-
-instance GQLType Animal where
-  type KIND Animal = INPUT_UNION
-
-newtype UniqueID = UniqueID
-  { uid :: Text
-  } deriving (Show, Generic)
-
-instance GQLType UniqueID where
-  type KIND UniqueID = INPUT_OBJECT
-
-data MyUnion res
-  = USER (User res)
-  | ADDRESS Address
-  deriving (Generic)
-
-instance Typeable a => GQLType (MyUnion a) where
-  type KIND (MyUnion a) = UNION
-
-data CityID
-  = Paris
-  | BLN
-  | HH
-  deriving (Generic)
-
-instance GQLType CityID where
-  type KIND CityID = ENUM
-
-data Euro =
-  Euro Int
-       Int
-  deriving (Generic)
-
-instance GQLType Euro where
-  type KIND Euro = SCALAR
-
-instance GQLScalar Euro where
-  parseValue _ = pure (Euro 1 0)
-  serialize (Euro x y) = Int (x * 100 + y)
-
-data Coordinates = Coordinates
-  { latitude  :: Euro
-  , longitude :: [Maybe [[UniqueID]]]
-  } deriving (Generic)
-
-instance GQLType Coordinates where
-  type KIND Coordinates = INPUT_OBJECT
-  description _ = "just random latitude and longitude"
-
-data Address = Address
-  { city        :: Text
-  , street      :: Text
-  , houseNumber :: Int
-  } deriving (Generic)
-
-instance GQLType Address where
-  type KIND Address = OBJECT
-
-data AddressArgs = AddressArgs
-  { coordinates :: Coordinates
-  , comment     :: Maybe Text
-  } deriving (Generic)
-
-data OfficeArgs = OfficeArgs
-  { zipCode :: Maybe [[Maybe [ID]]]
-  , cityID  :: CityID
-  } deriving (Generic)
-
-data User m = User
-  { name    :: Text
-  , email   :: Text
-  , address :: AddressArgs -> m Address
-  , office  :: OfficeArgs -> m Address
-  , myUnion :: () -> m (MyUnion m)
-  , home    :: CityID
-  } deriving (Generic)
-
-instance Typeable a => GQLType (User a) where
-  type KIND (User a) = OBJECT
-  description _ = "Custom Description for Client Defined User Type"
-
-instance Typeable a => GQLType (A a) where
-  type KIND (A a) = OBJECT
-
-newtype A a = A
-  { wrappedA :: a
-  } deriving (Generic)
-
-fetchAddress :: Monad m => Euro -> m (Either String Address)
-fetchAddress _ = return $ Right $ Address " " "" 0
-
-fetchUser :: Monad m => m (Either String (User (Resolver m)))
-fetchUser =
-  return $
-  Right $
-  User
-    { name = "George"
-    , email = "George@email.com"
-    , address = const resolveAddress
-    , office = resolveOffice
-    , home = HH
-    , myUnion = const $ return $ USER unionUser
-    }
-  where
-    unionAddress = Address {city = "Hamburg", street = "Street", houseNumber = 20}
-  -- Office
-    resolveOffice OfficeArgs {cityID = Paris} = resolver $ fetchAddress (Euro 1 1)
-    resolveOffice OfficeArgs {cityID = BLN}   = resolver $ fetchAddress (Euro 1 2)
-    resolveOffice OfficeArgs {cityID = HH}    = resolver $ fetchAddress (Euro 1 3)
-    resolveAddress = resolver $ fetchAddress (Euro 1 0)
-    unionUser =
-      User
-        { name = "David"
-        , email = "David@email.com"
-        , address = const resolveAddress
-        , office = resolveOffice
-        , home = BLN
-        , myUnion = const $ return $ ADDRESS unionAddress
-        }
-
-newtype AnimalArgs = AnimalArgs
-  { animal :: Animal
-  } deriving (Show, Generic)
-
-setAnimalResolver :: AnimalArgs -> IORes Text
-setAnimalResolver AnimalArgs {animal} = return $ pack $ show animal
-
-data Query = Query
-  { user       :: () -> IORes (User IORes)
-  , wrappedA1  :: A (Int, Text)
-  , setAnimal  :: AnimalArgs -> IORes Text
-  , wrappedA2  :: A Text
-  , integerSet :: Set Int
-  , textIntMap :: Map Text Int
-  } deriving (Generic)
-
-data Channel
-  = UPDATE_USER
-  | UPDATE_ADDRESS
-  deriving (Show, Eq, Ord)
-
-data Content = Update
-  { contentID      :: Int
-  , contentMessage :: Text
-  }
-
-type MutRes = IOMutRes Channel Content
-
-type SubRes a = IOSubRes Channel Content a
-
-data Mutation = Mutation
-  { createUser    :: () -> MutRes (User MutRes)
-  , createAddress :: () -> MutRes Address
-  } deriving (Generic)
-
-data Subscription = Subscription
-  { newAddress :: () -> SubRes Address
-  , newUser    :: () -> SubRes (User IORes)
-  } deriving (Generic)
-
-gqlRoot :: GQLRootResolver IO Channel Content Query Mutation Subscription
-gqlRoot =
-  GQLRootResolver
-    { queryResolver =
-        return
-          Query
-            { user = const $ resolver fetchUser
-            , wrappedA1 = A (0, "")
-            , setAnimal = setAnimalResolver
-            , wrappedA2 = A ""
-            , integerSet = S.fromList [1, 2]
-            , textIntMap = M.fromList [("robin", 1), ("carl", 2)]
-            }
-    , mutationResolver = return Mutation {createAddress, createUser}
-    , subscriptionResolver = return Subscription {newAddress, newUser}
-    }
-  where
-    newUser _ = Event [UPDATE_USER] $ \(Event _ Update {}) -> resolver fetchUser
-    newAddress _ = Event [UPDATE_ADDRESS] $ \(Event _ Update {contentID}) -> resolver $ fetchAddress (Euro contentID 0)
-    createUser _ =
-      mutResolver [Event [UPDATE_USER] (Update {contentID = 12, contentMessage = "some message for user"})] fetchUser
-    createAddress :: () -> MutRes Address
-    createAddress _ =
-      mutResolver
-        [Event [UPDATE_ADDRESS] (Update {contentID = 10, contentMessage = "message for address"})]
-        (fetchAddress (Euro 1 0))
diff --git a/examples/Deprecated/Model.hs b/examples/Deprecated/Model.hs
deleted file mode 100644
--- a/examples/Deprecated/Model.hs
+++ /dev/null
@@ -1,33 +0,0 @@
-{-# LANGUAGE DeriveAnyClass        #-}
-{-# LANGUAGE DeriveGeneric         #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE TypeOperators         #-}
-
-module Deprecated.Model
-  ( jsonAddress
-  , jsonUser
-  , JSONUser(..)
-  , JSONAddress(..)
-  ) where
-
-import           Data.Aeson   (FromJSON)
-import           Data.Text    (Text)
-import           Files        (getJson)
-import           GHC.Generics (Generic)
-
-data JSONUser = JSONUser
-  { name  :: Text
-  , email :: Text
-  } deriving (Show, Generic, FromJSON)
-
-data JSONAddress = JSONAddress
-  { city        :: Text
-  , street      :: Text
-  , houseNumber :: Int
-  } deriving (Generic, Show, FromJSON)
-
-jsonUser :: IO (Either String JSONUser)
-jsonUser = getJson "deprecated/user"
-
-jsonAddress :: IO (Either String JSONAddress)
-jsonAddress = getJson "deprecated/address"
diff --git a/examples/Main.hs b/examples/Main.hs
--- a/examples/Main.hs
+++ b/examples/Main.hs
@@ -1,93 +1,34 @@
-{-# LANGUAGE DeriveAnyClass        #-}
-{-# LANGUAGE DeriveGeneric         #-}
 {-# LANGUAGE DerivingStrategies    #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE NamedFieldPuns        #-}
 {-# LANGUAGE OverloadedStrings     #-}
-{-# LANGUAGE QuasiQuotes           #-}
-{-# LANGUAGE TemplateHaskell       #-}
 {-# LANGUAGE TypeFamilies          #-}
 
 module Main
   ( main
   ) where
 
+import           Client.Client                  (fetUser, fetchHero)
 import           Control.Monad.IO.Class         (liftIO)
-import           Data.ByteString.Lazy           (ByteString)
 import           Data.Functor.Identity          (Identity (..))
 import           Data.Morpheus                  (Interpreter (..))
-import           Data.Morpheus.Client           (Fetch (..), defineByDocumentFile, defineByIntrospectionFile, gql)
 import           Data.Morpheus.Document         (toGraphQLDocument)
 import           Data.Morpheus.Server           (GQLState, gqlSocketApp, initGQLState)
-import           Data.Morpheus.Types            (ScalarValue (..))
-import           Deprecated.API                 (Channel, Content, gqlRoot)
 import           Mythology.API                  (mythologyApi)
 import qualified Network.Wai                    as Wai
 import qualified Network.Wai.Handler.Warp       as Warp
 import qualified Network.Wai.Handler.WebSockets as WaiWs
 import           Network.WebSockets             (defaultConnectionOptions)
-import           TH.API                         (thApi)
+import           Sophisticated.API              (Channel, Content, gqlRoot)
+import           TH.Simple                      (thSimpleApi)
 import           Web.Scotty                     (body, file, get, post, raw, scottyApp)
 
-ioRes :: ByteString -> IO ByteString
-ioRes req = do
-  print req
-  return
-    "{\"data\":{\"deity\":{ \"fullName\": \"name\" }, \"character\":{ \"__typename\":\"Human\", \"lifetime\": \"Lifetime\", \"profession\": \"Artist\" }  }}"
-
-defineByIntrospectionFile
-  "./assets/introspection.json"
-  [gql|
-    # Query Hero with Compile time Validation
-    query GetUser ($userCoordinates: Coordinates!)
-      {
-        myUser: user {
-           boo3: name
-           email
-           address (coordinates: $userCoordinates ){
-            city
-           }
-        }
-      }
-  |]
-
-defineByDocumentFile
-  "./assets/simple.gql"
-  [gql|
-    # Query Hero with Compile time Validation
-    query GetHero ($god: Realm, $charID: String!)
-      {
-        deity (mythology:$god) {
-          power
-          fullName
-        }
-        character(characterID: $charID ) {
-          ...on Creature {
-            creatureName
-          }
-          ...on Human {
-            lifetime
-            profession
-          }
-        }
-      }
-  |]
-
-fetchHero :: IO (Either String GetHero)
-fetchHero = fetch ioRes GetHeroArgs {god = Just Realm {owner = "Zeus", surface = Just 10}, charID = "Hercules"}
-
-fetUser :: GQLState IO Channel Content -> IO (Either String GetUser)
-fetUser state = fetch (interpreter gqlRoot state) userArgs
-  where
-    userArgs :: Args GetUser
-    userArgs = GetUserArgs {userCoordinates = Coordinates {longitude = [], latitude = String "1"}}
-
 main :: IO ()
 main = do
-  fetchHero >>= print
   state <- initGQLState
   httpApp <- httpServer state
-  fetUser state >>= print
+  fetchHero >>= print
+  fetUser (interpreter gqlRoot state) >>= print
   Warp.runSettings settings $ WaiWs.websocketsOr defaultConnectionOptions (wsApp state) httpApp
   where
     settings = Warp.setPort 3000 Warp.defaultSettings
@@ -100,5 +41,5 @@
         get "/schema.gql" $ raw $ toGraphQLDocument $ Identity gqlRoot
         post "/mythology" $ raw =<< (liftIO . mythologyApi =<< body)
         get "/mythology" $ file "examples/index.html"
-        post "/th" $ raw =<< (liftIO . thApi =<< body)
+        post "/th" $ raw =<< (liftIO . thSimpleApi =<< body)
         get "/th" $ file "examples/index.html"
diff --git a/examples/Mythology/API.hs b/examples/Mythology/API.hs
--- a/examples/Mythology/API.hs
+++ b/examples/Mythology/API.hs
@@ -1,4 +1,5 @@
-{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE DeriveAnyClass #-}
+{-# LANGUAGE DeriveGeneric  #-}
 
 module Mythology.API
   ( mythologyApi
@@ -7,14 +8,14 @@
 import qualified Data.ByteString.Lazy.Char8 as B
 
 import           Data.Morpheus              (interpreter)
-import           Data.Morpheus.Types        (GQLRootResolver (..), IORes, resolver)
+import           Data.Morpheus.Types        (GQLRootResolver (..), GQLType, IORes, resolver)
 import           Data.Text                  (Text)
 import           GHC.Generics               (Generic)
 import           Mythology.Character.Deity  (Deity (..), dbDeity)
 
 newtype Query = Query
   { deity :: DeityArgs -> IORes Deity
-  } deriving (Generic)
+  } deriving (Generic, GQLType)
 
 data DeityArgs = DeityArgs
   { name      :: Text -- Required Argument
diff --git a/examples/Mythology/Character/Deity.hs b/examples/Mythology/Character/Deity.hs
--- a/examples/Mythology/Character/Deity.hs
+++ b/examples/Mythology/Character/Deity.hs
@@ -22,7 +22,7 @@
 
 instance GQLType Deity where
   type KIND Deity = OBJECT
-  description _ = "Custom Description for Client Defined User Type"
+  description _ = Just "Custom Description for Client Defined User Type"
 
 dbDeity :: Text -> Maybe Text -> IO (Either String Deity)
 dbDeity _ _ = return $ Right $ Deity {fullName = "Morpheus", power = Just "Shapeshifting", realm = Dream}
diff --git a/examples/Sophisticated/API.hs b/examples/Sophisticated/API.hs
new file mode 100644
--- /dev/null
+++ b/examples/Sophisticated/API.hs
@@ -0,0 +1,150 @@
+{-# LANGUAGE DeriveGeneric         #-}
+{-# LANGUAGE DerivingStrategies    #-}
+{-# LANGUAGE FlexibleContexts      #-}
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE NamedFieldPuns        #-}
+{-# LANGUAGE OverloadedStrings     #-}
+{-# LANGUAGE ScopedTypeVariables   #-}
+{-# LANGUAGE TemplateHaskell       #-}
+{-# LANGUAGE TypeFamilies          #-}
+
+module Sophisticated.API
+  ( gqlRoot
+  , Channel
+  , Content
+  ) where
+
+import           Data.Map               (Map)
+import qualified Data.Map               as M (fromList)
+import           Data.Set               (Set)
+import qualified Data.Set               as S (fromList)
+import           Data.Text              (Text, pack)
+import           Data.Typeable          (Typeable)
+import           GHC.Generics           (Generic)
+
+-- MORPHEUS
+import           Data.Morpheus.Document (importGQLDocumentWithNamespace)
+import           Data.Morpheus.Kind     (INPUT_UNION, OBJECT, SCALAR)
+import           Data.Morpheus.Types    (Event (..), GQLRootResolver (..), GQLScalar (..), GQLType (..), ID, IOMutRes,
+                                         IORes, IOSubRes, Resolver, ScalarValue (..), SubResolver (..), constRes,
+                                         mutResolver, resolver)
+
+$(importGQLDocumentWithNamespace "examples/Sophisticated/api.gql")
+
+type AIntText = A (Int, Text)
+
+type AText = A Text
+
+type SetInt = Set Int
+
+type MapTextInt = Map Text Int
+
+data Animal
+  = CAT Cat
+  | DOG Dog
+  | BIRD Bird
+  deriving (Show, Generic)
+
+instance GQLType Animal where
+  type KIND Animal = INPUT_UNION
+
+data Euro =
+  Euro Int
+       Int
+  deriving (Show, Generic)
+
+instance GQLType Euro where
+  type KIND Euro = SCALAR
+
+instance GQLScalar Euro where
+  parseValue _ = pure (Euro 1 0)
+  serialize (Euro x y) = Int (x * 100 + y)
+
+instance Typeable a => GQLType (A a) where
+  type KIND (A a) = OBJECT
+
+newtype A a = A
+  { wrappedA :: a
+  } deriving (Generic)
+
+data Channel
+  = UPDATE_USER
+  | UPDATE_ADDRESS
+  deriving (Show, Eq, Ord)
+
+data Content = Update
+  { contentID      :: Int
+  , contentMessage :: Text
+  }
+
+type MutRes = IOMutRes Channel Content
+
+type SubRes = IOSubRes Channel Content
+
+gqlRoot :: GQLRootResolver IO Channel Content (Query IORes) (Mutation MutRes) (Subscription SubRes)
+gqlRoot = GQLRootResolver {queryResolver, mutationResolver, subscriptionResolver}
+  where
+    queryResolver =
+      return
+        Query
+          { queryUser = const $ resolver fetchUser
+          , queryAnimal = \QueryAnimalArgs {queryAnimalArgsAnimal} -> return (pack $ show queryAnimalArgsAnimal)
+          , querySet = constRes $ S.fromList [1, 2]
+          , queryMap = constRes $ M.fromList [("robin", 1), ("carl", 2)]
+          , queryWrapped1 = constRes $ A (0, "")
+          , queryWrapped2 = constRes $ A ""
+          }
+    -------------------------------------------------------------
+    mutationResolver = return Mutation {mutationCreateAddress, mutationCreateUser}
+      where
+        mutationCreateUser _ =
+          mutResolver
+            [Event [UPDATE_USER] (Update {contentID = 12, contentMessage = "some message for user"})]
+            fetchUser
+        --mutationCreateAddress :: () -> MutRes (Address MutRes)
+        mutationCreateAddress _ =
+          mutResolver
+            [Event [UPDATE_ADDRESS] (Update {contentID = 10, contentMessage = "message for address"})]
+            (fetchAddress (Euro 1 0))
+    ----------------------------------------------------------------
+    subscriptionResolver = return Subscription {subscriptionNewAddress, subscriptionNewUser}
+      where
+        subscriptionNewUser () = SubResolver {subChannels = [UPDATE_USER], subResolver}
+          where
+            subResolver (Event _ Update {}) = resolver fetchUser
+        subscriptionNewAddress () = SubResolver {subChannels = [UPDATE_ADDRESS], subResolver}
+          where
+            subResolver (Event _ Update {contentID}) = resolver $ fetchAddress (Euro contentID 0)
+
+fetchAddress :: Monad m => Euro -> m (Either String (Address (Resolver m)))
+fetchAddress _ =
+  return $ Right Address {addressCity = constRes "", addressStreet = constRes "", addressHouseNumber = constRes 0}
+
+fetchUser :: Monad m => m (Either String (User (Resolver m)))
+fetchUser =
+  return $
+  Right $
+  User
+    { userName = constRes "George"
+    , userEmail = constRes "George@email.com"
+    , userAddress = const resolveAddress
+    , userOffice = resolveOffice
+    , userHome = constRes HH
+    , userEntity = constRes $ MyUnionUser unionUser
+    }
+  where
+    unionAddress =
+      Address {addressCity = constRes "Hamburg", addressStreet = constRes "Street", addressHouseNumber = constRes 20}
+  -- Office
+    resolveOffice _officeArgs = resolver $ fetchAddress (Euro 1 1)
+    resolveAddress = resolver $ fetchAddress (Euro 1 0)
+    unionUser =
+      User
+        { userName = constRes "David"
+        , userEmail = constRes "David@email.com"
+        , userAddress = const resolveAddress
+        , userOffice = resolveOffice
+        , userHome = constRes BLN
+        , userEntity = const $ return $ MyUnionAddress unionAddress
+        }
diff --git a/examples/Sophisticated/Model.hs b/examples/Sophisticated/Model.hs
new file mode 100644
--- /dev/null
+++ b/examples/Sophisticated/Model.hs
@@ -0,0 +1,33 @@
+{-# LANGUAGE DeriveAnyClass        #-}
+{-# LANGUAGE DeriveGeneric         #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE TypeOperators         #-}
+
+module Sophisticated.Model
+  ( jsonAddress
+  , jsonUser
+  , JSONUser(..)
+  , JSONAddress(..)
+  ) where
+
+import           Data.Aeson   (FromJSON)
+import           Data.Text    (Text)
+import           Files        (getJson)
+import           GHC.Generics (Generic)
+
+data JSONUser = JSONUser
+  { name  :: Text
+  , email :: Text
+  } deriving (Show, Generic, FromJSON)
+
+data JSONAddress = JSONAddress
+  { city        :: Text
+  , street      :: Text
+  , houseNumber :: Int
+  } deriving (Generic, Show, FromJSON)
+
+jsonUser :: IO (Either String JSONUser)
+jsonUser = getJson "deprecated/user"
+
+jsonAddress :: IO (Either String JSONAddress)
+jsonAddress = getJson "deprecated/address"
diff --git a/examples/Sophisticated/api.gql b/examples/Sophisticated/api.gql
new file mode 100644
--- /dev/null
+++ b/examples/Sophisticated/api.gql
@@ -0,0 +1,66 @@
+# for Input Union
+
+input Cat {
+  name: String!
+}
+
+input Dog {
+  name: String!
+}
+
+input Bird {
+  name: String!
+}
+
+# Main APi
+
+enum CityID {
+  Paris
+  BLN
+  HH
+}
+
+input Coordinates {
+  latitude: Euro!
+  longitude: [[[UniqueID!]!]]!
+}
+
+input UniqueID {
+  id: String!
+}
+
+type Address {
+  city: String!
+  street: String!
+  houseNumber: Int!
+}
+
+type User {
+  name: String!
+  email: String!
+  address(coordinates: Coordinates!, comment: String): Address!
+  office(zipCode: [[[ID!]]!], id: CityID!): Address!
+  entity: MyUnion!
+  home: CityID!
+}
+
+union MyUnion = User | Address
+
+type Query {
+  user: User!
+  animal(animal: Animal): String!
+  wrapped1: AIntText!
+  wrapped2: AText!
+  set: SetInt!
+  map: MapTextInt!
+}
+
+type Mutation {
+  createUser: User!
+  createAddress: Address!
+}
+
+type Subscription {
+  newAddress: Address!
+  newUser: User!
+}
diff --git a/examples/Subscription/SimpleSubscription.hs b/examples/Subscription/SimpleSubscription.hs
--- a/examples/Subscription/SimpleSubscription.hs
+++ b/examples/Subscription/SimpleSubscription.hs
@@ -1,11 +1,11 @@
 {-# LANGUAGE DeriveGeneric     #-}
 {-# LANGUAGE NamedFieldPuns    #-}
-{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE OverloadedStrings , ScopedTypeVariables , RankNTypes #-}
 
 module Subscription.SimpleSubscription where
 
-import           Data.Morpheus.Types       (Event (..), GQLRootResolver (..), IOMutRes, IORes, IOSubRes, resolver,
-                                            toMutResolver)
+import           Data.Morpheus.Types       (Event (..), GQLRootResolver (..), IOMutRes, IORes, IOSubRes,
+                                            SubResolver (..), resolver, toMutResolver)
 import           Data.Text                 (Text)
 import           GHC.Generics              (Generic)
 import           Mythology.Character.Deity (Deity (..), dbDeity)
@@ -40,8 +40,8 @@
   where
     fetchDeity = resolver $ dbDeity "" Nothing
     createDeity _args = toMutResolver [Event {channels = [ChannelA], content = ContentA 1}] fetchDeity
-    newDeity _args = Event {channels = [ChannelA], content}
+    newDeity _args = SubResolver {subChannels = [ChannelA], subResolver}
       where
-        content (Event [ChannelA] (ContentA _value)) = resolver $ dbDeity "" Nothing -- resolve New State
-        content (Event [ChannelA] (ContentB value))  = resolver $ dbDeity value Nothing -- resolve New State
-        content _                                    = fetchDeity -- Resolve Old State
+        subResolver (Event [ChannelA] (ContentA _value)) = resolver $ dbDeity "" Nothing -- resolve New State
+        subResolver (Event [ChannelA] (ContentB value))  = resolver $ dbDeity value Nothing -- resolve New State
+        subResolver _                                    = fetchDeity -- Resolve Old State
diff --git a/examples/TH/API.hs b/examples/TH/API.hs
deleted file mode 100644
--- a/examples/TH/API.hs
+++ /dev/null
@@ -1,109 +0,0 @@
-{-# LANGUAGE DeriveGeneric     #-}
-{-# LANGUAGE NamedFieldPuns    #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE QuasiQuotes       #-}
-{-# LANGUAGE TypeFamilies      #-}
-
-module TH.API
-  ( thApi
-  ) where
-
-import qualified Data.ByteString.Lazy.Char8 as B
-import           Data.Text                  (Text)
-import           GHC.Generics               (Generic)
-
--- MORPHEUS
-import           Data.Morpheus              (interpreter)
-import           Data.Morpheus.Document     (gqlDocument)
-import           Data.Morpheus.Kind         (SCALAR)
-import           Data.Morpheus.Types        (GQLRootResolver (..), GQLScalar (..), GQLType (..), ID, IORes,
-                                             ScalarValue (..))
-
-newtype Euro =
-  Euro Int
-  deriving (Show, Generic)
-
-instance GQLType Euro where
-  type KIND Euro = SCALAR
-
-instance GQLScalar Euro where
-  parseValue _ = pure (Euro 0)
-  serialize (Euro x) = Int (x * 100)
-
-[gqlDocument|
-   # GraphQL  Types Generated By Template Haskell
-
-  type Query {
-    user : User!
-  }
-
-
-  """
-    GraphQL Multiline Comment
-  """
-  type User {
-    name                                      : Text!
-    email                                     : Text!
-    address (zipCode: UID!, cityID : CityID ) : Address!
-    myUnion (coordinates: Coordinates)        : MyUnion!
-    home                                      : CityID!
-  }
-
-  type Address {
-    city        : Text!
-    street      : Text!
-    houseNumber : Int!
-  }
-
-  union MyUnion = User | Address
-
-  enum CityID {
-    Paris
-    BLN
-    HH
-  }
-
-  input Coordinates {
-    latitude  : Euro!
-    longitude : [[UID!]]!
-  }
-
-  # simple.gql
-  interface Node {
-      nodeId: ID!
-  }
-
-  type SimpleType implements Node {
-    nodeId: ID!
-    interfaceName: String!
-  }
-
-  input UID {
-    uid: Text!
-  }
-|]
-
-gqlRoot :: GQLRootResolver IO () () Query () ()
-gqlRoot = GQLRootResolver {queryResolver, mutationResolver = return (), subscriptionResolver = return ()}
-  where
-    queryResolver :: IORes Query
-    queryResolver = return Query {user}
-      where
-        user :: () -> IORes User
-        user _ =
-          return
-            User
-              { name = const $ pure "David"
-              , email = const $ pure "David@email.com"
-              , address
-              , home = const $ pure HH
-              , myUnion = const $ pure $ MyUnionAddress $ simpleAddress "boo"
-              }
-        address :: AddressArgs -> IORes Address
-        address AddressArgs {zipCode = UID {uid}} = return $ simpleAddress uid
-        --------------------------------
-        simpleAddress streetID =
-          Address {city = const $ pure "Hamburg", street = const $ pure streetID, houseNumber = const $ pure 20}
-
-thApi :: B.ByteString -> IO B.ByteString
-thApi = interpreter gqlRoot
diff --git a/examples/TH/Simple.hs b/examples/TH/Simple.hs
--- a/examples/TH/Simple.hs
+++ b/examples/TH/Simple.hs
@@ -1,41 +1,35 @@
-{-# LANGUAGE DeriveGeneric     #-}
-{-# LANGUAGE NamedFieldPuns    #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE QuasiQuotes       #-}
-{-# LANGUAGE TypeFamilies      #-}
+{-# LANGUAGE DeriveGeneric         #-}
+{-# LANGUAGE FlexibleContexts      #-}
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE NamedFieldPuns        #-}
+{-# LANGUAGE OverloadedStrings     #-}
+{-# LANGUAGE ScopedTypeVariables   #-}
+{-# LANGUAGE TemplateHaskell       #-}
+{-# LANGUAGE TypeFamilies          #-}
 
 module TH.Simple
-  ( mythologyApi
+  ( thSimpleApi
   ) where
 
 import qualified Data.ByteString.Lazy.Char8 as B
 
 import           Data.Morpheus              (interpreter)
-import           Data.Morpheus.Document     (gqlDocument)
+import           Data.Morpheus.Document     (importGQLDocumentWithNamespace)
 import           Data.Morpheus.Types        (GQLRootResolver (..), IORes)
 import           Data.Text                  (Text)
 
-[gqlDocument|
-
-  type Query {
-    deity (uid: Text! ) : Deity!
-  }
-
-  type Deity {
-    name : Text!
-    power    : Text
-  }
-
-|]
+importGQLDocumentWithNamespace "examples/TH/simple.gql"
 
-rootResolver :: GQLRootResolver IO () () Query () ()
+rootResolver :: GQLRootResolver IO () () (Query IORes) () ()
 rootResolver =
-  GQLRootResolver {queryResolver = return Query {deity}, mutationResolver = pure (), subscriptionResolver = pure ()}
+  GQLRootResolver
+    {queryResolver = return Query {queryDeity}, mutationResolver = pure (), subscriptionResolver = pure ()}
   where
-    deity DeityArgs {uid} = pure Deity {name, power}
+    queryDeity QueryDeityArgs {queryDeityArgsName} = pure Deity {deityName, deityPower}
       where
-        name _ = pure "Morpheus"
-        power _ = pure (Just "Shapeshifting")
+        deityName _ = pure "Morpheus"
+        deityPower _ = pure (Just "Shapeshifting")
 
-mythologyApi :: B.ByteString -> IO B.ByteString
-mythologyApi = interpreter rootResolver
+thSimpleApi :: B.ByteString -> IO B.ByteString
+thSimpleApi = interpreter rootResolver
diff --git a/examples/TH/simple.gql b/examples/TH/simple.gql
new file mode 100644
--- /dev/null
+++ b/examples/TH/simple.gql
@@ -0,0 +1,8 @@
+type Query {
+  deity(name: String!): Deity!
+}
+
+type Deity {
+  name: String!
+  power: String
+}
diff --git a/morpheus-graphql.cabal b/morpheus-graphql.cabal
--- a/morpheus-graphql.cabal
+++ b/morpheus-graphql.cabal
@@ -2,10 +2,10 @@
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: e5802f5202e1f3d85dbcbbfa5bbeccbe45394f9039335d2315915df0cee9d49a
+-- hash: 9eb00b52c6088e489408ff248d45e1402e955f2885390bbcc2fbd26944051b36
 
 name:           morpheus-graphql
-version:        0.2.2
+version:        0.3.0
 synopsis:       Morpheus GraphQL
 description:    Build GraphQL APIs with your favourite functional language!
 category:       web, graphql
@@ -24,6 +24,8 @@
     assets/pubsub.gql
     assets/simple.gql
     changelog.md
+    examples/Sophisticated/api.gql
+    examples/TH/simple.gql
     README.md
 data-files:
     test/Feature/Holistic/API.gql
@@ -246,8 +248,12 @@
       Data.Morpheus.Execution.Document.Compile
       Data.Morpheus.Execution.Document.Convert
       Data.Morpheus.Execution.Document.Declare
+      Data.Morpheus.Execution.Document.Decode
+      Data.Morpheus.Execution.Document.Encode
       Data.Morpheus.Execution.Document.GQLType
+      Data.Morpheus.Execution.Document.Introspect
       Data.Morpheus.Execution.Internal.Declare
+      Data.Morpheus.Execution.Internal.Decode
       Data.Morpheus.Execution.Internal.Utils
       Data.Morpheus.Execution.Server.Decode
       Data.Morpheus.Execution.Server.Encode
@@ -265,27 +271,22 @@
       Data.Morpheus.Parsing.Internal.Internal
       Data.Morpheus.Parsing.Internal.Terms
       Data.Morpheus.Parsing.JSONSchema.Parse
+      Data.Morpheus.Parsing.JSONSchema.Types
       Data.Morpheus.Parsing.Request.Arguments
       Data.Morpheus.Parsing.Request.Body
       Data.Morpheus.Parsing.Request.Fragment
       Data.Morpheus.Parsing.Request.Operation
       Data.Morpheus.Parsing.Request.Parser
       Data.Morpheus.Parsing.Request.Value
-      Data.Morpheus.Rendering.GQL
       Data.Morpheus.Rendering.Haskell.Render
+      Data.Morpheus.Rendering.Haskell.RenderHS
       Data.Morpheus.Rendering.Haskell.Terms
       Data.Morpheus.Rendering.Haskell.Types
       Data.Morpheus.Rendering.Haskell.Values
-      Data.Morpheus.Schema.Directive
-      Data.Morpheus.Schema.DirectiveLocation
-      Data.Morpheus.Schema.EnumValue
-      Data.Morpheus.Schema.Field
-      Data.Morpheus.Schema.InputValue
-      Data.Morpheus.Schema.Internal.RenderIntrospection
-      Data.Morpheus.Schema.JSONType
+      Data.Morpheus.Rendering.RenderGQL
+      Data.Morpheus.Rendering.RenderIntrospection
       Data.Morpheus.Schema.Schema
       Data.Morpheus.Schema.SchemaAPI
-      Data.Morpheus.Schema.Type
       Data.Morpheus.Schema.TypeKind
       Data.Morpheus.Types.Custom
       Data.Morpheus.Types.GQLScalar
@@ -343,15 +344,15 @@
 executable api
   main-is: Main.hs
   other-modules:
-      Deprecated.API
-      Deprecated.Model
+      Client.Client
       Files
       Mythology.API
       Mythology.Character.Deity
       Mythology.Character.Human
       Mythology.Place.Places
+      Sophisticated.API
+      Sophisticated.Model
       Subscription.SimpleSubscription
-      TH.API
       TH.Simple
       Paths_morpheus_graphql
   hs-source-dirs:
diff --git a/src/Data/Morpheus.hs b/src/Data/Morpheus.hs
--- a/src/Data/Morpheus.hs
+++ b/src/Data/Morpheus.hs
diff --git a/src/Data/Morpheus/Document.hs b/src/Data/Morpheus/Document.hs
--- a/src/Data/Morpheus/Document.hs
+++ b/src/Data/Morpheus/Document.hs
@@ -6,6 +6,8 @@
   , toMorpheusHaskellAPi
   , gqlDocument
   , parseFullGQLDocument
+  , importGQLDocument
+  , importGQLDocumentWithNamespace
   ) where
 
 import           Control.Monad                                ((>=>))
@@ -13,14 +15,14 @@
 import           Data.Text                                    (Text)
 import qualified Data.Text.Lazy                               as LT (toStrict)
 import           Data.Text.Lazy.Encoding                      (decodeUtf8)
-import           Language.Haskell.TH.Quote
+import           Language.Haskell.TH
 
 --
 -- MORPHEUS
-import           Data.Morpheus.Execution.Document.Compile     (compileDec, compileExp)
+import           Data.Morpheus.Execution.Document.Compile     (compileDocument, gqlDocument)
 import           Data.Morpheus.Execution.Server.Resolve       (RootResCon, fullSchema)
-import           Data.Morpheus.Rendering.GQL                  (renderGraphQLDocument)
 import           Data.Morpheus.Rendering.Haskell.Render       (renderHaskellDocument)
+import           Data.Morpheus.Rendering.RenderGQL            (renderGraphQLDocument)
 import           Data.Morpheus.Types                          (GQLRootResolver)
 
 import           Data.Morpheus.Parsing.Document.Parser        (parseTypes)
@@ -52,9 +54,8 @@
     Left errors -> Left $ pack (show errors)
     Right lib   -> Right $ renderHaskellDocument moduleName lib
 
-gqlDocument :: QuasiQuoter
-gqlDocument =
-  QuasiQuoter
-    {quoteExp = compileExp, quotePat = notHandled "Patterns", quoteType = notHandled "Types", quoteDec = compileDec}
-  where
-    notHandled things = error $ things ++ " are not supported by the GraphQL QuasiQuoter"
+importGQLDocument :: String -> Q [Dec]
+importGQLDocument src = runIO (readFile src) >>= compileDocument False
+
+importGQLDocumentWithNamespace :: String -> Q [Dec]
+importGQLDocumentWithNamespace src = runIO (readFile src) >>= compileDocument True
diff --git a/src/Data/Morpheus/Error/Selection.hs b/src/Data/Morpheus/Error/Selection.hs
--- a/src/Data/Morpheus/Error/Selection.hs
+++ b/src/Data/Morpheus/Error/Selection.hs
@@ -6,14 +6,18 @@
   , duplicateQuerySelections
   , hasNoSubfields
   , fieldNotResolved
+  , resolverError
   ) where
 
 import           Data.Morpheus.Error.Utils               (errorMessage)
 import           Data.Morpheus.Types.Internal.Base       (EnhancedKey (..), Position)
 import           Data.Morpheus.Types.Internal.Validation (GQLError (..), GQLErrors)
-import           Data.Text                               (Text)
+import           Data.Text                               (Text, pack)
 import qualified Data.Text                               as T (concat)
 
+resolverError :: Position -> Text -> String -> GQLErrors
+resolverError pos name message = fieldNotResolved pos name (pack message)
+
 fieldNotResolved :: Position -> Text -> Text -> GQLErrors
 fieldNotResolved position' key' message' = errorMessage position' text
   where
@@ -23,44 +27,21 @@
 hasNoSubfields :: Text -> Text -> Position -> GQLErrors
 hasNoSubfields key typeName position = errorMessage position text
   where
-    text =
-      T.concat
-        [ "Field \""
-        , key
-        , "\" must not have a selection since type \""
-        , typeName
-        , "\" has no subfields."
-        ]
+    text = T.concat ["Field \"", key, "\" must not have a selection since type \"", typeName, "\" has no subfields."]
 
 cannotQueryField :: Text -> Text -> Position -> GQLErrors
 cannotQueryField key typeName position = errorMessage position text
   where
-    text =
-      T.concat ["Cannot query field \"", key, "\" on type \"", typeName, "\"."]
+    text = T.concat ["Cannot query field \"", key, "\" on type \"", typeName, "\"."]
 
 duplicateQuerySelections :: Text -> [EnhancedKey] -> GQLErrors
 duplicateQuerySelections parentType = map keyToError
   where
-    keyToError (EnhancedKey key' pos) =
-      GQLError {desc = toMessage key', positions = [pos]}
-    toMessage key' =
-      T.concat
-        [ "duplicate selection of key \""
-        , key'
-        , "\" on type \""
-        , parentType
-        , "\"."
-        ]
+    keyToError (EnhancedKey key' pos) = GQLError {desc = toMessage key', positions = [pos]}
+    toMessage key' = T.concat ["duplicate selection of key \"", key', "\" on type \"", parentType, "\"."]
 
 -- GQL:: Field \"hobby\" of type \"Hobby!\" must have a selection of subfields. Did you mean \"hobby { ... }\"?
 subfieldsNotSelected :: Text -> Text -> Position -> GQLErrors
 subfieldsNotSelected key typeName position = errorMessage position text
   where
-    text =
-      T.concat
-        [ "Field \""
-        , key
-        , "\" of type \""
-        , typeName
-        , "\" must have a selection of subfields"
-        ]
+    text = T.concat ["Field \"", key, "\" of type \"", typeName, "\" must have a selection of subfields"]
diff --git a/src/Data/Morpheus/Execution/Client/Aeson.hs b/src/Data/Morpheus/Execution/Client/Aeson.hs
--- a/src/Data/Morpheus/Execution/Client/Aeson.hs
+++ b/src/Data/Morpheus/Execution/Client/Aeson.hs
@@ -15,14 +15,16 @@
 
 import           Data.Aeson
 import           Data.Aeson.Types
-import qualified Data.HashMap.Lazy                   as H (lookup)
-import           Data.Semigroup                      ((<>))
-import           Data.Text                           (unpack)
+import qualified Data.HashMap.Lazy                  as H (lookup)
+import           Data.Semigroup                     ((<>))
+import           Data.Text                          (unpack)
 import           Language.Haskell.TH
 
 --
 -- MORPHEUS
-import Data.Morpheus.Types.Internal.DataD (AppD (..), ConsD (..), FieldD (..), TypeD (..))
+import           Data.Morpheus.Types.Internal.Data  (DataField (..), isFieldNullable)
+import           Data.Morpheus.Types.Internal.DataD (ConsD (..), TypeD (..))
+import           Data.Morpheus.Types.Internal.TH    (instanceFunD, instanceHeadT)
 
 deriveFromJSON :: TypeD -> Q Dec
 deriveFromJSON TypeD {tCons = []} = fail "Type Should Have at least one Constructor"
@@ -38,14 +40,17 @@
 aesonObjectBody ConsD {cName, cFields} = handleFields cFields
   where
     consName = mkName cName
+    ------------------------------------------
     handleFields [] = fail $ "No Empty Object"
     handleFields fields = startExp fields
     ----------------------------------------------------------------------------------
-         -- Optional Field
+      -- Optional Field
       where
-        defField FieldD {fieldNameD, fieldTypeD = MaybeD _} = [|o .:? fieldNameD|]
-        -- Required Field
-        defField FieldD {fieldNameD}                        = [|o .: fieldNameD|]
+        defField field@DataField {fieldName}
+          | isFieldNullable field = [|o .:? fName|]
+          | otherwise = [|o .: fName|]
+          where
+            fName = unpack fieldName
             -------------------------------------------------------------------
         startExp fNames = uInfixE (conE consName) (varE '(<$>)) (applyFields fNames)
           where
@@ -70,11 +75,11 @@
 takeValueType _ _ = fail $ "expected Object"
 
 defineFromJSON :: String -> (t -> ExpQ) -> t -> DecQ
-defineFromJSON tName func inp =
-  instanceD (cxt []) (appT (conT ''FromJSON) (conT $ mkName tName)) [parseJSONExp func inp]
+defineFromJSON tName parseJ cFields = instanceD (cxt []) iHead [method]
   where
-    parseJSONExp :: (t -> ExpQ) -> t -> DecQ
-    parseJSONExp parseJ cFields = funD 'parseJSON [clause [] (normalB $ parseJ cFields) []]
+    iHead = instanceHeadT ''FromJSON tName []
+    -----------------------------------------
+    method = instanceFunD 'parseJSON [] (parseJ cFields)
 
 isEnum :: [ConsD] -> Bool
 isEnum = not . isEmpty . filter (isEmpty . cFields)
diff --git a/src/Data/Morpheus/Execution/Client/Fetch.hs b/src/Data/Morpheus/Execution/Client/Fetch.hs
--- a/src/Data/Morpheus/Execution/Client/Fetch.hs
+++ b/src/Data/Morpheus/Execution/Client/Fetch.hs
@@ -10,15 +10,16 @@
   , deriveFetch
   ) where
 
-import           Control.Monad          ((>=>))
-import           Data.Aeson             (FromJSON, ToJSON (..), eitherDecode, encode)
-import           Data.ByteString.Lazy   (ByteString)
-import           Data.Text              (pack)
+import           Control.Monad                   ((>=>))
+import           Data.Aeson                      (FromJSON, ToJSON (..), eitherDecode, encode)
+import           Data.ByteString.Lazy            (ByteString)
+import           Data.Text                       (pack)
 import           Language.Haskell.TH
 
 --
 -- MORPHEUS
-import           Data.Morpheus.Types.IO (GQLRequest (..), JSONResponse (..))
+import           Data.Morpheus.Types.Internal.TH (instanceHeadT)
+import           Data.Morpheus.Types.IO          (GQLRequest (..), JSONResponse (..))
 
 class Fetch a where
   type Args a :: *
@@ -32,16 +33,16 @@
   __fetch strQuery opName trans vars = (eitherDecode >=> processResponse) <$> trans (encode gqlReq)
     where
       gqlReq = GQLRequest {operationName = Just (pack opName), query = pack strQuery, variables = Just (toJSON vars)}
-      ----
+      -------------------------------------------------------------
       processResponse JSONResponse {responseData = Just x} = pure x
       processResponse invalidResponse                      = fail $ show invalidResponse
   fetch :: (Monad m, FromJSON a) => (ByteString -> m ByteString) -> Args a -> m (Either String a)
 
 deriveFetch :: Type -> String -> String -> Q [Dec]
-deriveFetch argDatatype typeName query =
-  pure <$> instanceD (cxt []) (appT (conT ''Fetch) (conT $ mkName typeName)) methods
+deriveFetch argDatatype typeName query = pure <$> instanceD (cxt []) iHead methods
   where
+    iHead = instanceHeadT ''Fetch typeName []
     methods =
-      [ funD (mkName "fetch") [clause [] (normalB [|__fetch query typeName|]) []]
+      [ funD 'fetch [clause [] (normalB [|__fetch query typeName|]) []]
       , pure $ TySynInstD ''Args (TySynEqn [ConT $ mkName typeName] argDatatype)
       ]
diff --git a/src/Data/Morpheus/Execution/Client/Selection.hs b/src/Data/Morpheus/Execution/Client/Selection.hs
--- a/src/Data/Morpheus/Execution/Client/Selection.hs
+++ b/src/Data/Morpheus/Execution/Client/Selection.hs
@@ -18,9 +18,9 @@
                                                              VariableDefinitions)
 import           Data.Morpheus.Types.Internal.AST.Selection (Selection (..), SelectionRec (..))
 import           Data.Morpheus.Types.Internal.Data          (DataField (..), DataFullType (..), DataLeaf (..),
-                                                             DataType (..), DataTypeLib (..), DataTypeWrapper,
+                                                             DataTyCon (..), DataTypeLib (..), TypeAlias (..),
                                                              allDataTypes)
-import           Data.Morpheus.Types.Internal.DataD         (ConsD (..), FieldD (..), TypeD (..), gqlToHSWrappers)
+import           Data.Morpheus.Types.Internal.DataD         (ConsD (..), TypeD (..))
 import           Data.Morpheus.Types.Internal.Validation    (GQLErrors, Validation)
 import           Data.Morpheus.Validation.Internal.Utils    (lookupType)
 
@@ -33,15 +33,15 @@
     queryDataType = OutputObject $ snd $ query lib
     -----------------------------------------------------
     typeByField :: Text -> DataFullType -> Validation DataFullType
-    typeByField key datatype = fst <$> fieldDataType datatype key
+    typeByField key datatype = fst <$> lookupFieldType datatype key
     ------------------------------------------------------
-    fieldDataType :: DataFullType -> Text -> Validation (DataFullType, [DataTypeWrapper])
-    fieldDataType (OutputObject DataType {typeData}) key =
+    lookupFieldType :: DataFullType -> Text -> Validation (DataFullType, TypeAlias)
+    lookupFieldType (OutputObject DataTyCon {typeData}) key =
       case lookup key typeData of
-        Just DataField {fieldTypeWrappers, fieldType} -> trans <$> getType lib fieldType
-          where trans x = (x, fieldTypeWrappers)
+        Just DataField {fieldType = alias@TypeAlias {aliasTyCon}} -> trans <$> getType lib aliasTyCon
+          where trans x = (x, alias {aliasTyCon = typeFrom x, aliasArgs = Nothing})
         Nothing -> Left (compileError key)
-    fieldDataType _ key = Left (compileError key)
+    lookupFieldType _ key = Left (compileError key)
     -----------------------------------------------------
     genOperation Operation {operationName, operationSelection} = do
       argTypes <- rootArguments (operationName <> "Args")
@@ -51,22 +51,20 @@
     genInputType :: Text -> Validation [TypeD]
     genInputType name = getType lib name >>= subTypes
       where
-        subTypes (InputObject DataType {typeName, typeData}) = do
+        subTypes (InputObject DataTyCon {typeName, typeData}) = do
           types <- concat <$> mapM toInputTypeD typeData
           fields <- traverse toFieldD typeData
           pure $ typeD fields : types
           where
             typeD fields = TypeD {tName = unpack typeName, tCons = [ConsD {cName = unpack typeName, cFields = fields}]}
             ---------------------------------------------------------------
-            toInputTypeD :: (Text, DataField a) -> Validation [TypeD]
-            toInputTypeD (_, DataField {fieldType}) = genInputType fieldType
+            toInputTypeD :: (Text, DataField) -> Validation [TypeD]
+            toInputTypeD (_, DataField {fieldType}) = genInputType $ aliasTyCon fieldType
             ----------------------------------------------------------------
-            toFieldD :: (Text, DataField a) -> Validation FieldD
-            toFieldD (key, DataField {fieldType, fieldTypeWrappers}) = do
-              fType <- typeFrom <$> getType lib fieldType
-              pure $ FieldD (unpack key) (wrType fType)
-              where
-                wrType fieldT = gqlToHSWrappers fieldTypeWrappers (unpack fieldT)
+            toFieldD :: (Text, DataField) -> Validation DataField
+            toFieldD (_, field@DataField {fieldType}) = do
+              aliasTyCon <- typeFrom <$> getType lib (aliasTyCon fieldType)
+              pure $ field {fieldType = fieldType {aliasTyCon}}
         subTypes (Leaf x) = buildLeaf x
         subTypes _ = pure []
     -------------------------------------------
@@ -78,10 +76,16 @@
         typeD :: TypeD
         typeD = TypeD {tName = unpack name, tCons = [ConsD {cName = unpack name, cFields = map fieldD variables}]}
         ---------------------------------------
-        fieldD :: (Text, Variable ()) -> FieldD
-        fieldD (key, Variable {variableType, variableTypeWrappers}) = FieldD (unpack key) wrType
-          where
-            wrType = gqlToHSWrappers variableTypeWrappers (unpack variableType)
+        fieldD :: (Text, Variable ()) -> DataField
+        fieldD (key, Variable {variableType, variableTypeWrappers}) =
+          DataField
+            { fieldName = key
+            , fieldArgs = []
+            , fieldArgsType = Nothing
+            , fieldType =
+                TypeAlias {aliasWrappers = variableTypeWrappers, aliasTyCon = variableType, aliasArgs = Nothing}
+            , fieldHidden = False
+            }
     -------------------------------------------
     getCon name dataType selectionSet = do
       cFields <- genFields dataType selectionSet
@@ -91,14 +95,13 @@
       where
         genFields datatype = mapM typeNameFromField
           where
-            typeNameFromField :: (Text, Selection) -> Validation FieldD
-            typeNameFromField (key, Selection {selectionRec = SelectionAlias {aliasFieldName}}) =
-              FieldD (unpack key) <$> lookupFieldType aliasFieldName
-            typeNameFromField (key, _) = FieldD (unpack key) <$> lookupFieldType key
-            ------------------------------------------------------------
-            lookupFieldType key = do
-              (newType, wrappers) <- fieldDataType datatype key
-              pure $ gqlToHSWrappers wrappers (unpack $ typeFrom newType)
+            typeNameFromField :: (Text, Selection) -> Validation DataField
+            typeNameFromField (fieldName, Selection {selectionRec = SelectionAlias {aliasFieldName}}) = do
+              fieldType <- snd <$> lookupFieldType datatype aliasFieldName
+              pure $ DataField {fieldName, fieldArgs = [], fieldArgsType = Nothing, fieldType, fieldHidden = False}
+            typeNameFromField (fieldName, _) = do
+              fieldType <- snd <$> lookupFieldType datatype fieldName
+              pure $ DataField {fieldName, fieldArgs = [], fieldArgsType = Nothing, fieldType, fieldHidden = False}
     --------------------------------------------
     genRecordType name dataType selectionSet = do
       (con, subTypes) <- getCon name dataType selectionSet
@@ -127,7 +130,7 @@
               getCon typeKey conDatatype selSet
 
 buildLeaf :: DataLeaf -> Validation [TypeD]
-buildLeaf (LeafEnum DataType {typeName, typeData}) =
+buildLeaf (LeafEnum DataTyCon {typeName, typeData}) =
   pure [TypeD {tName = unpack typeName, tCons = map enumOption typeData}]
   where
     enumOption name = ConsD {cName = unpack name, cFields = []}
@@ -146,7 +149,7 @@
 
 typeFrom :: DataFullType -> Text
 typeFrom (Leaf (BaseScalar x)) = typeName x
-typeFrom (Leaf (CustomScalar DataType {typeName}))
+typeFrom (Leaf (CustomScalar DataTyCon {typeName}))
   | isPrimitive typeName = typeName
   | otherwise = "ScalarValue"
 typeFrom (Leaf (LeafEnum x)) = typeName x
diff --git a/src/Data/Morpheus/Execution/Document/Compile.hs b/src/Data/Morpheus/Execution/Document/Compile.hs
--- a/src/Data/Morpheus/Execution/Document/Compile.hs
+++ b/src/Data/Morpheus/Execution/Document/Compile.hs
@@ -1,14 +1,14 @@
-{-# LANGUAGE NamedFieldPuns  #-}
-{-# LANGUAGE QuasiQuotes     #-}
-{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE NamedFieldPuns #-}
 
 module Data.Morpheus.Execution.Document.Compile
-  ( compileExp
-  , compileDec
+  ( compileDocument
+  , gqlDocument
+  , gqlDocumentNamespace
   ) where
 
 import qualified Data.Text                                    as T (pack)
 import           Language.Haskell.TH
+import           Language.Haskell.TH.Quote
 
 --
 --  Morpheus
@@ -18,14 +18,30 @@
 import           Data.Morpheus.Parsing.Document.Parser        (parseTypes)
 import           Data.Morpheus.Validation.Document.Validation
 
-compileExp :: String -> Q Exp
-compileExp documentTXT =
-  case parseTypes (T.pack documentTXT) >>= validatePartialDocument >>= renderTHTypes of
-    Left errors -> fail (renderGQLErrors errors)
-    Right root  -> [|root|]
+gqlDocumentNamespace :: QuasiQuoter
+gqlDocumentNamespace =
+  QuasiQuoter
+    { quoteExp = notHandled "Expressions"
+    , quotePat = notHandled "Patterns"
+    , quoteType = notHandled "Types"
+    , quoteDec = compileDocument True
+    }
+  where
+    notHandled things = error $ things ++ " are not supported by the GraphQL QuasiQuoter"
 
-compileDec :: String -> Q [Dec]
-compileDec documentTXT =
-  case parseTypes (T.pack documentTXT) >>= validatePartialDocument >>= renderTHTypes of
-    Left errors -> fail (renderGQLErrors errors)
-    Right root  -> declareTypes root
+gqlDocument :: QuasiQuoter
+gqlDocument =
+  QuasiQuoter
+    { quoteExp = notHandled "Expressions"
+    , quotePat = notHandled "Patterns"
+    , quoteType = notHandled "Types"
+    , quoteDec = compileDocument False
+    }
+  where
+    notHandled things = error $ things ++ " are not supported by the GraphQL QuasiQuoter"
+
+compileDocument :: Bool -> String -> Q [Dec]
+compileDocument namespace documentTXT =
+  case parseTypes (T.pack documentTXT) >>= validatePartialDocument >>= renderTHTypes namespace of
+    Left errors  -> fail (renderGQLErrors errors)
+    Right schema -> declareTypes namespace schema
diff --git a/src/Data/Morpheus/Execution/Document/Convert.hs b/src/Data/Morpheus/Execution/Document/Convert.hs
--- a/src/Data/Morpheus/Execution/Document/Convert.hs
+++ b/src/Data/Morpheus/Execution/Document/Convert.hs
@@ -5,72 +5,136 @@
 {-# LANGUAGE TypeOperators       #-}
 
 module Data.Morpheus.Execution.Document.Convert
-  ( renderTHTypes
+  ( renderTHTypes , sysTypes
   ) where
 
 import           Data.Semigroup                          ((<>))
-import           Data.Text                               (Text, unpack)
+import           Data.Text                               (Text, pack, unpack)
 
 --
 -- MORPHEUS
 import           Data.Morpheus.Error.Internal            (internalError)
 import           Data.Morpheus.Execution.Internal.Utils  (capital)
-import           Data.Morpheus.Types.Internal.Data       (DataField (..), DataFullType (..), DataLeaf (..),
-                                                          DataOutputField, DataType (..), DataTypeKind (..))
-import           Data.Morpheus.Types.Internal.DataD      (AppD (..), ConsD (..), FieldD (..), GQLTypeD, TypeD (..),
-                                                          gqlToHSWrappers)
+import           Data.Morpheus.Types.Internal.Data       (ArgsType (..), DataField (..), DataField, DataFullType (..),
+                                                          DataLeaf (..), DataTyCon (..), DataTypeKind (..),
+                                                          DataTypeKind (..), OperationKind (..), ResolverKind (..),
+                                                          TypeAlias (..))
+import           Data.Morpheus.Types.Internal.DataD      (ConsD (..), GQLTypeD (..), TypeD (..))
 import           Data.Morpheus.Types.Internal.Validation (Validation)
 
-renderTHTypes :: [(Text, DataFullType)] -> Validation [GQLTypeD]
-renderTHTypes = traverse renderTHType
+sysTypes :: [Text]
+sysTypes =
+  ["__Schema", "__Type", "__Directive", "__TypeKind", "__Field", "__DirectiveLocation", "__InputValue", "__EnumValue"]
 
-renderTHType :: (Text, DataFullType) -> Validation GQLTypeD
-renderTHType (_, x) = genType x
+renderTHTypes :: Bool -> [(Text, DataFullType)] -> Validation [GQLTypeD]
+renderTHTypes namespace lib = traverse renderTHType lib
   where
-    argsTypeName fieldName = capital (unpack fieldName) <> "Args"
-    genArgumentType :: (Text, DataField [(Text, DataField ())]) -> Validation [TypeD]
-    genArgumentType (_, DataField {fieldArgs = []}) = pure []
-    genArgumentType (fieldName, DataField {fieldArgs}) =
-      pure [TypeD {tName, tCons = [ConsD {cName = tName, cFields = map genField fieldArgs}]}]
-      where
-        tName = argsTypeName fieldName
-    ---------------------------------------------------------------------------------------------
-    genField :: (Text, DataField a) -> FieldD
-    genField (key, DataField {fieldType, fieldTypeWrappers}) = FieldD (unpack key) fType
-      where
-        fType = gqlToHSWrappers fieldTypeWrappers (unpack fieldType)
-    ---------------------------------------------------------------------------------------------
-    genResField :: (Text, DataOutputField) -> FieldD
-    genResField (key, DataField {fieldName, fieldArgs, fieldType, fieldTypeWrappers}) = FieldD (unpack key) fType
-      where
-        fType = ResD (argsTName fieldArgs) "IORes" $ gqlToHSWrappers fieldTypeWrappers (unpack fieldType)
-        argsTName [] = "()"
-        argsTName _  = argsTypeName fieldName
-    --------------------------------------------
-    genType (Leaf (LeafEnum DataType {typeName, typeData})) =
-      pure (TypeD {tName = unpack typeName, tCons = map enumOption typeData}, KindEnum, [])
-      where
-        enumOption name = ConsD {cName = unpack name, cFields = []}
-    genType (Leaf _) = internalError "Scalar Types should defined By Native Haskell Types"
-    genType (InputUnion _) = internalError "Input Unions not Supported"
-    genType (InputObject DataType {typeName, typeData}) =
-      pure
-        ( TypeD {tName = unpack typeName, tCons = [ConsD {cName = unpack typeName, cFields = map genField typeData}]}
-        , KindInputObject
-        , [])
-    genType (OutputObject DataType {typeName, typeData}) = do
-      subTypes <- concat <$> traverse genArgumentType typeData
-      pure
-        ( TypeD {tName = unpack typeName, tCons = [ConsD {cName = unpack typeName, cFields = map genResField typeData}]}
-        , KindObject
-        , subTypes)
-    genType (Union DataType {typeName, typeData}) = do
-      let tCons = map unionCon typeData
-      pure (TypeD {tName = unpack typeName, tCons}, KindUnion, [])
+    renderTHType :: (Text, DataFullType) -> Validation GQLTypeD
+    renderTHType (tyConName, x) = genType x
       where
-        unionCon DataField {fieldType} =
-          ConsD {cName, cFields = [FieldD {fieldNameD = "un" <> cName, fieldTypeD = BaseD utName}]}
+        genArgsTypeName fieldName
+          | namespace = sysName tyConName <> argTName
+          | otherwise = argTName
           where
-            cName = unpack typeName <> utName
-            utName = unpack fieldType
-    ------------------------------------------------------------------------------------------------------------
+            argTName = capital fieldName <> "Args"
+        genArgumentType :: (Text, DataField) -> Validation [TypeD]
+        genArgumentType (_, DataField {fieldArgs = []}) = pure []
+        genArgumentType (fieldName, DataField {fieldArgs}) =
+          pure [TypeD {tName, tCons = [ConsD {cName = sysName $ pack tName, cFields = map genField fieldArgs}]}]
+          where
+            tName = genArgsTypeName $ sysName fieldName
+        -------------------------------------------
+        genFieldTypeName = genTypeName
+        ------------------------------
+        --genTypeName :: Text -> Text
+        genTypeName "String" = "Text"
+        genTypeName "Boolean" = "Bool"
+        genTypeName name
+          | name `elem` sysTypes = "S" <> name
+        genTypeName name = name
+        ----------------------------------------
+        sysName = unpack . genTypeName
+        ---------------------------------------------------------------------------------------------
+        genField :: (Text, DataField) -> DataField
+        genField (_, field@DataField {fieldType = alias@TypeAlias {aliasTyCon}}) =
+          field {fieldType = alias {aliasTyCon = genFieldTypeName aliasTyCon}}
+        ---------------------------------------------------------------------------------------------
+        genResField :: (Text, DataField) -> DataField
+        genResField (_, field@DataField {fieldName, fieldArgs, fieldType = alias@TypeAlias {aliasTyCon}}) =
+          field {fieldType = alias {aliasTyCon = ftName, aliasArgs}, fieldArgsType}
+          where
+            ftName = genFieldTypeName aliasTyCon
+            ---------------------------------------
+            aliasArgs =
+              case lookup aliasTyCon lib of
+                Just OutputObject {} -> Just "m"
+                Just Union {}        -> Just "m"
+                _                    -> Nothing
+            -----------------------------------
+            fieldArgsType = Just $ ArgsType {argsTypeName, resKind = getFieldType ftName}
+              where
+                argsTypeName
+                  | null fieldArgs = "()"
+                  | otherwise = pack $ genArgsTypeName $ unpack fieldName
+                --------------------------------------
+                getFieldType key =
+                  case lookup key lib of
+                    Nothing              -> ExternalResolver
+                    Just OutputObject {} -> TypeVarResolver
+                    Just Union {}        -> TypeVarResolver
+                    Just _               -> PlainResolver
+        --------------------------------------------
+        genType (Leaf (LeafEnum DataTyCon {typeName, typeData})) =
+          pure
+            GQLTypeD
+              { typeD = TypeD {tName = sysName typeName, tCons = map enumOption typeData}
+              , typeKindD = KindEnum
+              , typeArgD = []
+              }
+          where
+            enumOption name = ConsD {cName = sysName name, cFields = []}
+        genType (Leaf _) = internalError "Scalar Types should defined By Native Haskell Types"
+        genType (InputUnion _) = internalError "Input Unions not Supported"
+        genType (InputObject DataTyCon {typeName, typeData}) =
+          pure
+            GQLTypeD
+              { typeD =
+                  TypeD
+                    { tName = sysName typeName
+                    , tCons = [ConsD {cName = sysName typeName, cFields = map genField typeData}]
+                    }
+              , typeKindD = KindInputObject
+              , typeArgD = []
+              }
+        genType (OutputObject DataTyCon {typeName, typeData}) = do
+          typeArgD <- concat <$> traverse genArgumentType typeData
+          pure
+            GQLTypeD
+              { typeD =
+                  TypeD
+                    { tName = sysName typeName
+                    , tCons = [ConsD {cName = sysName typeName, cFields = map genResField typeData}]
+                    }
+              , typeKindD =
+                  if typeName == "Subscription"
+                    then KindObject (Just Subscription)
+                    else KindObject Nothing
+              , typeArgD
+              }
+        genType (Union DataTyCon {typeName, typeData}) = do
+          let tCons = map unionCon typeData
+          pure GQLTypeD {typeD = TypeD {tName = unpack typeName, tCons}, typeKindD = KindUnion, typeArgD = []}
+          where
+            unionCon field@DataField {fieldType} =
+              ConsD
+                { cName
+                , cFields =
+                    [ field
+                        { fieldName = pack $ "un" <> cName
+                        , fieldType = TypeAlias {aliasTyCon = pack utName, aliasArgs = Just "m", aliasWrappers = []}
+                        }
+                    ]
+                }
+              where
+                cName = sysName typeName <> utName
+                utName = sysName $ aliasTyCon fieldType
diff --git a/src/Data/Morpheus/Execution/Document/Declare.hs b/src/Data/Morpheus/Execution/Document/Declare.hs
--- a/src/Data/Morpheus/Execution/Document/Declare.hs
+++ b/src/Data/Morpheus/Execution/Document/Declare.hs
@@ -1,24 +1,54 @@
-{-# LANGUAGE DataKinds      #-}
-{-# LANGUAGE NamedFieldPuns #-}
+{-# LANGUAGE DataKinds       #-}
+{-# LANGUAGE NamedFieldPuns  #-}
+{-# LANGUAGE TemplateHaskell #-}
 
 module Data.Morpheus.Execution.Document.Declare
   ( declareTypes
   ) where
 
-import           Data.Semigroup                           ((<>))
+import           Data.Semigroup                              ((<>))
 import           Language.Haskell.TH
 
 --
 -- MORPHEUS
-import           Data.Morpheus.Execution.Document.GQLType (deriveGQLType)
-import           Data.Morpheus.Execution.Internal.Declare (declareType)
-import           Data.Morpheus.Types.Internal.DataD       (GQLTypeD)
+import           Data.Morpheus.Execution.Document.Decode     (deriveDecode)
+import           Data.Morpheus.Execution.Document.Encode     (deriveEncode)
+import           Data.Morpheus.Execution.Document.GQLType    (deriveGQLType)
+import           Data.Morpheus.Execution.Document.Introspect (deriveObjectRep)
+import           Data.Morpheus.Execution.Internal.Declare    (declareGQLT)
+import           Data.Morpheus.Types.Internal.Data           (isInput, isObject)
+import           Data.Morpheus.Types.Internal.DataD          (GQLTypeD (..))
 
-declareTypes :: [GQLTypeD] -> Q [Dec]
-declareTypes = fmap concat . traverse declareGQLType
+declareTypes :: Bool -> [GQLTypeD] -> Q [Dec]
+declareTypes namespace = fmap concat . traverse (declareGQLType namespace)
 
-declareGQLType :: GQLTypeD -> Q [Dec]
-declareGQLType gqlType@(typeD, _, argTypes) = do
-  let types = map (declareType []) (typeD : argTypes)
+declareGQLType :: Bool -> GQLTypeD -> Q [Dec]
+declareGQLType namespace gqlType@GQLTypeD {typeD, typeKindD, typeArgD} = do
+  mainType <- declareMainType
+  argTypes <- declareArgTypes
+  gqlInstances <- deriveGQLInstances
   typeClasses <- deriveGQLType gqlType
-  pure $ types <> typeClasses
+  pure $ mainType <> typeClasses <> argTypes <> gqlInstances
+  where
+    deriveGQLInstances = concat <$> sequence gqlInstances
+      where
+        gqlInstances
+          | isObject typeKindD && isInput typeKindD = [deriveObjectRep (typeD, Just typeKindD), deriveDecode typeD]
+          | isObject typeKindD = [deriveObjectRep (typeD, Just typeKindD), deriveEncode gqlType]
+          | otherwise = []
+    --------------------------------------------------
+    declareArgTypes = do
+      introspectArgs <- concat <$> traverse deriveArgsRep typeArgD
+      decodeArgs <- concat <$> traverse deriveDecode typeArgD
+      return $ argsTypeDecs <> decodeArgs <> introspectArgs
+      where
+        deriveArgsRep args = deriveObjectRep (args, Nothing)
+        ----------------------------------------------------
+        argsTypeDecs = map (declareGQLT namespace Nothing []) typeArgD
+        --------------------------------------------------
+    declareMainType = declareT
+      where
+        declareT = pure [declareGQLT namespace (Just typeKindD) derivingClasses typeD]
+        derivingClasses
+          | isInput typeKindD = [''Show]
+          | otherwise = []
diff --git a/src/Data/Morpheus/Execution/Document/Decode.hs b/src/Data/Morpheus/Execution/Document/Decode.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Morpheus/Execution/Document/Decode.hs
@@ -0,0 +1,35 @@
+{-# LANGUAGE FlexibleContexts  #-}
+{-# LANGUAGE MonoLocalBinds    #-}
+{-# LANGUAGE NamedFieldPuns    #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE QuasiQuotes       #-}
+{-# LANGUAGE TemplateHaskell   #-}
+
+module Data.Morpheus.Execution.Document.Decode
+  ( deriveDecode
+  ) where
+
+import           Data.Text                               (Text)
+import           Language.Haskell.TH
+
+--
+-- MORPHEUS
+import           Data.Morpheus.Execution.Internal.Decode (decodeFieldWith, decodeObjectExpQ)
+import           Data.Morpheus.Execution.Server.Decode   (Decode (..), DecodeObject (..))
+import           Data.Morpheus.Types.Internal.DataD      (TypeD (..))
+import           Data.Morpheus.Types.Internal.TH         (instanceHeadT)
+import           Data.Morpheus.Types.Internal.Validation (Validation)
+import           Data.Morpheus.Types.Internal.Value      (Object)
+
+(.:) :: Decode a => Object -> Text -> Validation a
+object .: selectorName = decodeFieldWith decode selectorName object
+
+deriveDecode :: TypeD -> Q [Dec]
+deriveDecode TypeD {tName, tCons = [cons]} = pure <$> instanceD (cxt []) appHead methods
+  where
+    appHead = instanceHeadT ''DecodeObject tName []
+    methods = [funD 'decodeObject [clause argsE (normalB body) []]]
+      where
+        argsE = map (varP . mkName) ["o"]
+        body = decodeObjectExpQ [|(.:)|] cons
+deriveDecode _ = pure []
diff --git a/src/Data/Morpheus/Execution/Document/Encode.hs b/src/Data/Morpheus/Execution/Document/Encode.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Morpheus/Execution/Document/Encode.hs
@@ -0,0 +1,66 @@
+{-# LANGUAGE DataKinds         #-}
+{-# LANGUAGE NamedFieldPuns    #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE TemplateHaskell   #-}
+
+module Data.Morpheus.Execution.Document.Encode
+  ( deriveEncode
+  ) where
+
+import           Data.Text                               (unpack)
+import           Data.Typeable                           (Typeable)
+import           Language.Haskell.TH
+
+--
+-- MORPHEUS
+import           Data.Morpheus.Execution.Server.Encode   (Encode (..), ObjectResolvers (..))
+import           Data.Morpheus.Types.GQLType             (TRUE)
+import           Data.Morpheus.Types.Internal.Data       (DataField (..), isSubscription)
+import           Data.Morpheus.Types.Internal.DataD      (ConsD (..), GQLTypeD (..), TypeD (..))
+import           Data.Morpheus.Types.Internal.TH         (applyT, instanceHeadMultiT, typeT)
+import           Data.Morpheus.Types.Internal.Validation (ResolveT)
+import           Data.Morpheus.Types.Internal.Value      (Value)
+import           Data.Morpheus.Types.Resolver
+
+-- @Subscription:
+--
+--     instance (Monad m, Typeable m) => ObjectResolvers 'True (<Subscription> (SubResolver m e c)) (SubResolveT m e c Value) where
+--          objectResolvers _ (<Subscription> x y) = [("newAddress", encode x), ("newUser", encode y)]
+--
+-- @Object:
+--
+--   instance (Monad m, Typeable m) => ObjectResolvers 'True (<Object> (Resolver m)) (ResolveT m Value) where
+--          objectResolvers _ (<Object> x y) = [("field1", encode x), ("field2", encode y)]
+--
+--
+deriveEncode :: GQLTypeD -> Q [Dec]
+deriveEncode GQLTypeD {typeKindD, typeD = TypeD {tName, tCons = [ConsD {cFields}]}} =
+  pure <$> instanceD (cxt constrains) appHead methods
+  where
+    result = appT resultMonad (conT ''Value)
+      where
+        resultMonad
+          | isSubscription typeKindD = typeT ''SubResolveT ["m", "e", "c"] -- (SubResolveT m e c Value)
+          | otherwise = typeT ''ResolveT ["m"] -- (ResolveT m Value)
+    mainType = applyT (mkName tName) [mainTypeArg] -- defines  (<Type> (SubResolver m e c)) or (<Type> (Resolver m))
+      where
+        mainTypeArg
+          | isSubscription typeKindD = typeT ''SubResolver ["m", "e", "c"] -- (SubResolver m e c)
+          | otherwise = typeT ''Resolver ["m"] -- (Resolver m)
+    -----------------------------------------------------------------------------------------
+    -- defines Constraint: (Typeable m, Monad m)
+    constrains = [typeT ''Monad ["m"], typeT ''Typeable ["m"]]
+    -------------------------------------------------------------------
+    -- defines: instance <constraint> =>  ObjectResolvers ('TRUE) (<Type> (ResolveT m)) (ResolveT m value) where
+    appHead = instanceHeadMultiT ''ObjectResolvers (conT ''TRUE) [mainType, result]
+    ------------------------------------------------------------------
+    -- defines: objectResolvers <Type field1 field2 ...> = [("field1",encode field1),("field2",encode field2), ...]
+    methods = [funD 'objectResolvers [clause argsE (normalB body) []]]
+      where
+        argsE = [varP (mkName "_"), conP (mkName tName) (map (varP . mkName) varNames)]
+        body = listE $ map decodeVar varNames
+        decodeVar name = [|(name, encode $(varName))|]
+          where
+            varName = varE $ mkName name
+        varNames = map (unpack . fieldName) cFields
+deriveEncode _ = pure []
diff --git a/src/Data/Morpheus/Execution/Document/GQLType.hs b/src/Data/Morpheus/Execution/Document/GQLType.hs
--- a/src/Data/Morpheus/Execution/Document/GQLType.hs
+++ b/src/Data/Morpheus/Execution/Document/GQLType.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE DataKinds         #-}
 {-# LANGUAGE NamedFieldPuns    #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE QuasiQuotes       #-}
@@ -7,26 +8,65 @@
   ( deriveGQLType
   ) where
 
+import           Data.Text                                (pack)
 import           Language.Haskell.TH
 
-import           Data.Morpheus.Kind                 (ENUM, INPUT_OBJECT, INPUT_UNION, OBJECT, SCALAR, UNION, WRAPPER)
+import           Data.Morpheus.Execution.Document.Convert (sysTypes)
 
 --
 -- MORPHEUS
-import           Data.Morpheus.Types.GQLType        (GQLType (..))
-import           Data.Morpheus.Types.Internal.Data  (DataTypeKind (..))
-import           Data.Morpheus.Types.Internal.DataD (GQLTypeD, TypeD (..))
+import           Data.Morpheus.Execution.Internal.Declare (tyConArgs)
+import           Data.Morpheus.Kind                       (ENUM, INPUT_OBJECT, INPUT_UNION, OBJECT, SCALAR, UNION,
+                                                           WRAPPER)
+import           Data.Morpheus.Types.GQLType              (GQLType (..), TRUE)
+import           Data.Morpheus.Types.Internal.Data        (DataTypeKind (..), isObject)
+import           Data.Morpheus.Types.Internal.DataD       (GQLTypeD (..), TypeD (..))
+import           Data.Morpheus.Types.Internal.TH          (instanceHeadT, typeT)
+import           Data.Typeable                            (Typeable)
 
+genTypeName :: String -> String
+genTypeName ('S':name)
+  | pack name `elem` sysTypes = name
+genTypeName name = name
+
 deriveGQLType :: GQLTypeD -> Q [Dec]
-deriveGQLType (TypeD {tName}, gqlKind, _) =
-  pure <$> instanceD (cxt []) (appT (conT ''GQLType) (conT $ mkName tName)) methods
+deriveGQLType GQLTypeD {typeD = TypeD {tName}, typeKindD} =
+  pure <$> instanceD (cxt constrains) iHead (def__typeName : typeFamilies)
   where
-    methods = [pure $ TySynInstD ''KIND (TySynEqn [ConT $ mkName tName] (ConT $ toKIND gqlKind))]
-    toKIND KindScalar      = ''SCALAR
-    toKIND KindEnum        = ''ENUM
-    toKIND KindObject      = ''OBJECT
-    toKIND KindUnion       = ''UNION
-    toKIND KindInputObject = ''INPUT_OBJECT
-    toKIND KindList        = ''WRAPPER
-    toKIND KindNonNull     = ''WRAPPER
-    toKIND KindInputUnion  = ''INPUT_UNION
+    def__typeName = funD '__typeName [clause argsE (normalB body) []]
+    -- defines method: __typeName _ = tName
+      where
+        argsE = map (varP . mkName) ["_"]
+        body = [|pack name|]
+          where
+            name = genTypeName tName
+    typeArgs = tyConArgs typeKindD
+    ----------------------------------------------
+    iHead = instanceHeadT ''GQLType tName typeArgs
+    headSig = typeT (mkName tName) typeArgs
+    -----------------------------------------------
+    constrains = map conTypeable typeArgs
+      where
+        conTypeable name = typeT ''Typeable [name]
+    -----------------------------------------------
+    typeFamilies
+      | isObject typeKindD = [deriveCUSTOM, deriveKind]
+      | otherwise = [deriveKind]
+    ---------------------------------------------
+      where
+        deriveCUSTOM = do
+          typeN <- headSig
+          pure $ TySynInstD ''CUSTOM (TySynEqn [typeN] (ConT ''TRUE))
+        ---------------------------------------------------------------
+        deriveKind = do
+          typeN <- headSig
+          pure $ TySynInstD ''KIND (TySynEqn [typeN] (ConT $ toKIND typeKindD))
+        ---------------------------------
+        toKIND KindScalar      = ''SCALAR
+        toKIND KindEnum        = ''ENUM
+        toKIND (KindObject _)  = ''OBJECT
+        toKIND KindUnion       = ''UNION
+        toKIND KindInputObject = ''INPUT_OBJECT
+        toKIND KindList        = ''WRAPPER
+        toKIND KindNonNull     = ''WRAPPER
+        toKIND KindInputUnion  = ''INPUT_UNION
diff --git a/src/Data/Morpheus/Execution/Document/Introspect.hs b/src/Data/Morpheus/Execution/Document/Introspect.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Morpheus/Execution/Document/Introspect.hs
@@ -0,0 +1,76 @@
+{-# LANGUAGE NamedFieldPuns    #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE QuasiQuotes       #-}
+{-# LANGUAGE TemplateHaskell   #-}
+
+module Data.Morpheus.Execution.Document.Introspect
+  ( deriveObjectRep
+  ) where
+
+import           Data.Proxy                                (Proxy (..))
+import           Data.Text                                 (unpack)
+import           Data.Typeable                             (Typeable)
+import           Language.Haskell.TH
+
+-- MORPHEUS
+import           Data.Morpheus.Execution.Internal.Declare  (tyConArgs)
+import           Data.Morpheus.Execution.Server.Introspect (Introspect (..), ObjectFields (..))
+import           Data.Morpheus.Types.GQLType               (GQLType (__typeName), TRUE)
+import           Data.Morpheus.Types.Internal.Data         (ArgsType (..), DataField (..), DataTypeKind, TypeAlias (..))
+import           Data.Morpheus.Types.Internal.DataD        (ConsD (..), TypeD (..))
+import           Data.Morpheus.Types.Internal.TH           (instanceFunD, instanceHeadMultiT, typeT)
+
+-- [((Text, DataField), TypeUpdater)]
+deriveObjectRep :: (TypeD, Maybe DataTypeKind) -> Q [Dec]
+deriveObjectRep (TypeD {tName, tCons = [ConsD {cFields}]}, tKind) =
+  pure <$> instanceWithOverlapD overlapping (cxt constrains) iHead methods
+  where
+    overlapping = Just Overlapping
+    typeArgs =
+      case tKind of
+        Just typeKind -> tyConArgs typeKind
+        Nothing       -> []
+    constrains = map conTypeable typeArgs
+      where
+        conTypeable name = typeT ''Typeable [name]
+    -----------------------------------------------
+    iHead = instanceHeadMultiT ''ObjectFields (conT ''TRUE) [typeT (mkName tName) typeArgs]
+    methods = [instanceFunD 'objectFields ["_proxy1", "_proxy2"] body]
+      where
+        body = [|($(buildFields cFields), concat $(buildTypes cFields))|]
+deriveObjectRep _ = pure []
+
+buildTypes :: [DataField] -> ExpQ
+buildTypes = listE . concatMap introspectField
+  where
+    introspectField DataField {fieldType, fieldArgsType} =
+      [|[introspect $(proxyT fieldType)]|] : inputTypes fieldArgsType
+      where
+        inputTypes (Just ArgsType {argsTypeName})
+          | argsTypeName /= "()" = [[|snd $ objectFields (Proxy :: Proxy TRUE) $(proxyT tAlias)|]]
+          where
+            tAlias = TypeAlias {aliasTyCon = argsTypeName, aliasWrappers = [], aliasArgs = Nothing}
+        inputTypes _ = []
+
+proxyT :: TypeAlias -> Q Exp
+proxyT TypeAlias {aliasTyCon, aliasArgs} = [|(Proxy :: Proxy $(genSig aliasArgs))|]
+  where
+    genSig (Just m) = appT (conT $ mkName $ unpack aliasTyCon) (varT $ mkName $ unpack m)
+    genSig _        = conT $ mkName $ unpack aliasTyCon
+
+buildFields :: [DataField] -> ExpQ
+buildFields = listE . map buildField
+  where
+    buildField DataField {fieldName, fieldArgs, fieldType = alias@TypeAlias {aliasArgs, aliasWrappers}} =
+      [|( fName
+        , DataField
+            { fieldName = fName
+            , fieldArgs = fArgs
+            , fieldArgsType = Nothing
+            , fieldType = TypeAlias {aliasTyCon = __typeName $(proxyT alias), aliasArgs = aArgs, aliasWrappers}
+            , fieldHidden = False
+            })|]
+      where
+        fName = unpack fieldName
+        fArgs = map (\(k, v) -> (unpack k, v)) fieldArgs
+        aArgs = unpack <$> aliasArgs
diff --git a/src/Data/Morpheus/Execution/Internal/Declare.hs b/src/Data/Morpheus/Execution/Internal/Declare.hs
--- a/src/Data/Morpheus/Execution/Internal/Declare.hs
+++ b/src/Data/Morpheus/Execution/Internal/Declare.hs
@@ -9,34 +9,78 @@
 
 module Data.Morpheus.Execution.Internal.Declare
   ( declareType
+  , declareGQLT
+  , tyConArgs
   ) where
 
+import           Data.Maybe                             (maybe)
+import           Data.Text                              (unpack)
+import           GHC.Generics                           (Generic)
 import           Language.Haskell.TH
 
---
 -- MORPHEUS
-import           Data.Morpheus.Types.Internal.DataD (AppD (..), ConsD (..), FieldD (..), TypeD (..))
-import           GHC.Generics                       (Generic)
+import           Data.Morpheus.Execution.Internal.Utils (nameSpaceWith)
+import           Data.Morpheus.Types.Internal.Data      (ArgsType (..), DataField (..), DataTypeKind (..),
+                                                         DataTypeKind (..), TypeAlias (..), WrapperD (..),
+                                                         isOutputObject, isSubscription)
+import           Data.Morpheus.Types.Internal.DataD     (ConsD (..), TypeD (..))
+import           Data.Morpheus.Types.Resolver           (UnSubResolver)
 
 type FUNC = (->)
 
---
---
 declareType :: [Name] -> TypeD -> Dec
-declareType derivingList TypeD {tName, tCons} =
-  DataD [] (mkName tName) [] Nothing (map cons tCons) $ map derive (''Generic : derivingList)
+declareType = declareGQLT False Nothing
+
+declareTypeAlias :: Bool -> TypeAlias -> Type
+declareTypeAlias isSub TypeAlias {aliasTyCon, aliasWrappers, aliasArgs} = wrappedT aliasWrappers
   where
+    wrappedT :: [WrapperD] -> Type
+    wrappedT (ListD:xs)  = AppT (ConT ''[]) $ wrappedT xs
+    wrappedT (MaybeD:xs) = AppT (ConT ''Maybe) $ wrappedT xs
+    wrappedT []          = decType aliasArgs
+    ------------------------------------------------------
+    typeName = ConT (mkName $ unpack aliasTyCon)
+    --------------------------------------------
+    decType _
+      | isSub = AppT typeName (AppT (ConT ''UnSubResolver) (VarT $ mkName "m"))
+    decType (Just par) = AppT typeName (VarT $ mkName $ unpack par)
+    decType _ = typeName
+
+tyConArgs :: DataTypeKind -> [String]
+tyConArgs kindD
+  | isOutputObject kindD || kindD == KindUnion = ["m"]
+  | otherwise = []
+
+-- declareType
+declareGQLT :: Bool -> Maybe DataTypeKind -> [Name] -> TypeD -> Dec
+declareGQLT namespace kindD derivingList TypeD {tName, tCons} =
+  DataD [] (mkName tName) tVars Nothing (map cons tCons) $ map derive (''Generic : derivingList)
+  where
+    tVars = maybe [] (declareTyVar . tyConArgs) kindD
+      where
+        declareTyVar = map (PlainTV . mkName)
     defBang = Bang NoSourceUnpackedness NoSourceStrictness
     derive className = DerivClause Nothing [ConT className]
-    cons ConsD {cName, cFields} = RecC (mkName cName) (map genField cFields)
+    cons ConsD {cName, cFields} = RecC (mkName cName) (map declareField cFields)
       where
-        genField FieldD {fieldNameD, fieldTypeD} = (mkName fieldNameD, defBang, genFieldT fieldTypeD)
+        declareField DataField {fieldName, fieldArgsType, fieldType} = (fName, defBang, fiType)
           where
-            genFieldT (ListD td) = AppT (ConT ''[]) (genFieldT td)
-            genFieldT (MaybeD td) = AppT (ConT ''Maybe) (genFieldT td)
-            genFieldT (BaseD name) = ConT (mkName name)
-            genFieldT (ResD arg mon td) = AppT (AppT arrowType argType) resultType
+            fName
+              | namespace = mkName (nameSpaceWith tName (unpack fieldName))
+              | otherwise = mkName (unpack fieldName)
+            fiType = genFieldT fieldArgsType
               where
-                argType = ConT $ mkName arg
-                arrowType = ConT ''FUNC
-                resultType = AppT (ConT $ mkName mon) (genFieldT td)
+                monadVar = VarT $ mkName "m"
+                ---------------------------
+                genFieldT Nothing = fType False
+                genFieldT (Just ArgsType {argsTypeName}) = AppT (AppT arrowType argType) (fType True)
+                  where
+                    argType = ConT $ mkName (unpack argsTypeName)
+                    arrowType = ConT ''FUNC
+                ------------------------------------------------
+                fType isResolver
+                  | maybe False isSubscription kindD = AppT monadVar result
+                  | isResolver = AppT monadVar result
+                  | otherwise = result
+                ------------------------------------------------
+                result = declareTypeAlias (maybe False isSubscription kindD) fieldType
diff --git a/src/Data/Morpheus/Execution/Internal/Decode.hs b/src/Data/Morpheus/Execution/Internal/Decode.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Morpheus/Execution/Internal/Decode.hs
@@ -0,0 +1,71 @@
+{-# LANGUAGE NamedFieldPuns    #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE TemplateHaskell   #-}
+
+module Data.Morpheus.Execution.Internal.Decode
+  ( withObject
+  , withMaybe
+  , withList
+  , withEnum
+  , withUnion
+  , decodeFieldWith
+  , decodeObjectExpQ
+  ) where
+
+import           Data.Semigroup                          ((<>))
+import           Data.Text                               (unpack)
+import           Language.Haskell.TH                     (ExpQ, conE, mkName, uInfixE, varE)
+
+-- MORPHEUS
+import           Data.Morpheus.Error.Internal            (internalArgumentError, internalTypeMismatch)
+import           Data.Morpheus.Types.Internal.Data       (DataField (..), Key)
+import           Data.Morpheus.Types.Internal.DataD      (ConsD (..))
+import           Data.Morpheus.Types.Internal.Validation (Validation)
+import           Data.Morpheus.Types.Internal.Value      (Object, Value (..))
+
+decodeObjectExpQ :: ExpQ -> ConsD -> ExpQ
+decodeObjectExpQ fieldDecoder ConsD {cName, cFields} = handleFields cFields
+  where
+    consName = conE (mkName cName)
+    ----------------------------------------------------------------------------------
+    handleFields fNames = uInfixE consName (varE '(<$>)) (applyFields fNames)
+      where
+        applyFields []     = fail "No Empty fields"
+        applyFields [x]    = defField x
+        applyFields (x:xs) = uInfixE (defField x) (varE '(<*>)) (applyFields xs)
+        ------------------------------------------------------------------------
+        defField DataField {fieldName} = uInfixE (varE (mkName "o")) fieldDecoder [|fName|]
+          where
+            fName = unpack fieldName
+
+withObject :: (Object -> Validation a) -> Value -> Validation a
+withObject f (Object object) = f object
+withObject _ isType          = internalTypeMismatch "Object" isType
+
+withMaybe :: Monad m => (Value -> m a) -> Value -> m (Maybe a)
+withMaybe _ Null   = pure Nothing
+withMaybe decode x = Just <$> decode x
+
+withList :: (Value -> Validation a) -> Value -> Validation [a]
+withList decode (List li) = mapM decode li
+withList _ isType         = internalTypeMismatch "List" isType
+
+withEnum :: (Key -> Validation a) -> Value -> Validation a
+withEnum decode (Enum value) = decode value
+withEnum _ isType            = internalTypeMismatch "Enum" isType
+
+withUnion :: (Key -> Object -> Object -> Validation a) -> Object -> Validation a
+withUnion decoder unions =
+  case lookup "tag" unions of
+    Just (Enum key) ->
+      case lookup key unions of
+        Nothing    -> internalArgumentError ("type \"" <> key <> "\" was not provided on object")
+        Just value -> withObject (decoder key unions) value
+    Just _ -> internalArgumentError "tag must be Enum"
+    Nothing -> internalArgumentError "tag not found on Input Union"
+
+decodeFieldWith :: (Value -> Validation a) -> Key -> Object -> Validation a
+decodeFieldWith decoder name object =
+  case lookup name object of
+    Nothing    -> internalArgumentError ("Missing Field: \"" <> name <> "\"")
+    Just value -> decoder value
diff --git a/src/Data/Morpheus/Execution/Server/Decode.hs b/src/Data/Morpheus/Execution/Server/Decode.hs
--- a/src/Data/Morpheus/Execution/Server/Decode.hs
+++ b/src/Data/Morpheus/Execution/Server/Decode.hs
@@ -11,172 +11,122 @@
 {-# LANGUAGE UndecidableInstances  #-}
 
 module Data.Morpheus.Execution.Server.Decode
-  ( ArgumentsConstraint
-  , decodeArguments
+  ( decodeArguments
+  , Decode(..)
+  , DecodeObject(..)
   ) where
 
 import           Data.Proxy                                      (Proxy (..))
 import           Data.Semigroup                                  ((<>))
-import           Data.Text                                       (Text, pack)
+import           Data.Text                                       (pack)
 import           GHC.Generics
 
 -- MORPHEUS
 import           Data.Morpheus.Error.Internal                    (internalArgumentError, internalTypeMismatch)
+import           Data.Morpheus.Execution.Internal.Decode         (decodeFieldWith, withEnum, withList, withMaybe,
+                                                                  withObject, withUnion)
 import           Data.Morpheus.Execution.Server.Generics.EnumRep (EnumRep (..))
-import           Data.Morpheus.Kind                              (ENUM, GQL_KIND, INPUT_OBJECT, INPUT_UNION, SCALAR,
-                                                                  WRAPPER)
+import           Data.Morpheus.Kind                              (ENUM, GQL_KIND, INPUT_OBJECT, INPUT_UNION, SCALAR)
 import           Data.Morpheus.Types.GQLScalar                   (GQLScalar (..), toScalar)
 import           Data.Morpheus.Types.GQLType                     (GQLType (KIND, __typeName))
 import           Data.Morpheus.Types.Internal.AST.Selection      (Argument (..), Arguments)
+import           Data.Morpheus.Types.Internal.Base               (Key)
 import           Data.Morpheus.Types.Internal.Validation         (Validation)
-import           Data.Morpheus.Types.Internal.Value              (Value (..))
-
---
--- GENERIC UNION
---
-class DecodeInputUnion f where
-  decodeUnion :: Value -> Validation (f a)
-  unionTags :: Proxy f -> [Text]
-
-instance (Datatype c, DecodeInputUnion f) => DecodeInputUnion (M1 D c f) where
-  decodeUnion = fmap M1 . decodeUnion
-  unionTags _ = unionTags (Proxy @f)
-
-instance (Constructor c, DecodeInputUnion f) =>
-         DecodeInputUnion (M1 C c f) where
-  decodeUnion = fmap M1 . decodeUnion
-  unionTags _ = unionTags (Proxy @f)
-
-instance (Selector c, DecodeInputUnion f) => DecodeInputUnion (M1 S c f) where
-  decodeUnion = fmap M1 . decodeUnion
-  unionTags _ = unionTags (Proxy @f)
-
-instance (DecodeInputUnion a, DecodeInputUnion b) =>
-         DecodeInputUnion (a :+: b) where
-  decodeUnion (Object pairs) =
-    case lookup "tag" pairs of
-      Nothing -> internalArgumentError "tag not found on Input Union"
-      Just (Enum name) ->
-        case lookup name pairs of
-          Nothing ->
-            internalArgumentError
-              ("type \"" <> name <> "\" was not provided on object")
-          -- Decodes first Matching Union Type Value
-          Just value
-            | [name] == l1Tags -> L1 <$> decodeUnion value
-          -- Decodes last Matching Union Type Value
-          Just value
-            | [name] == r1Tags -> R1 <$> decodeUnion value
-          Just _
-            -- JUMPS to Next Union Pair
-            | name `elem` r1Tags -> R1 <$> decodeUnion (Object pairs)
-          Just _ ->
-            internalArgumentError
-              ("type \"" <> name <> "\" could not find in union")
-        where l1Tags = unionTags $ Proxy @a
-              r1Tags = unionTags $ Proxy @b
-      Just _ -> internalArgumentError "tag must be Enum"
-  decodeUnion _ = internalArgumentError "Expected Input Object Union!"
-  unionTags _ = unionTags (Proxy @a) ++ unionTags (Proxy @b)
-
-instance (GQLType a, Decode a (KIND a)) => DecodeInputUnion (K1 i a) where
-  decodeUnion value = K1 <$> decode value
-  unionTags _ = [__typeName (Proxy @a)]
-
---
---  GENERIC INPUT OBJECT AND ARGUMENTS
---
-type ArgumentsConstraint a = (Generic a, DecodeInputObject (Rep a))
-
-decodeArguments ::
-     (Generic p, DecodeInputObject (Rep p)) => Arguments -> Validation p
-decodeArguments args =
-  to <$> decodeObject (Object $ fmap (\(x, y) -> (x, argumentValue y)) args)
-
-class DecodeInputObject f where
-  decodeObject :: Value -> Validation (f a)
-
-instance DecodeInputObject U1 where
-  decodeObject _ = pure U1
-
-type Sel s = M1 S s
-
-proxySelName ::
-     forall s. Selector s
-  => Proxy (M1 S s)
-  -> Text
-proxySelName _ = pack $ selName (undefined :: M1 S s f a)
-
-instance (Selector s, DecodeInputObject f) => DecodeInputObject (M1 S s f) where
-  decodeObject (Object object) = M1 <$> selectFromObject
-    where
-      selectorName = proxySelName (Proxy @(Sel s))
-      selectFromObject =
-        case lookup selectorName object of
-          Nothing    -> internalArgumentError ("Missing Field: " <> selectorName)
-          Just value -> decodeObject value
-  decodeObject isType = internalTypeMismatch "InputObject" isType
-
-instance DecodeInputObject f => DecodeInputObject (M1 D c f) where
-  decodeObject = fmap M1 . decodeObject
+import           Data.Morpheus.Types.Internal.Value              (Object, Value (..))
 
-instance DecodeInputObject f => DecodeInputObject (M1 C c f) where
-  decodeObject = fmap M1 . decodeObject
+-- | Decode GraphQL query arguments and input values
+class Decode a where
+  decode :: Value -> Validation a
 
-instance (DecodeInputObject f, DecodeInputObject g) =>
-         DecodeInputObject (f :*: g) where
-  decodeObject gql = (:*:) <$> decodeObject gql <*> decodeObject gql
+instance {-# OVERLAPPABLE #-} DecodeKind (KIND a) a => Decode a where
+  decode = decodeKind (Proxy @(KIND a))
 
-instance (Decode a (KIND a)) => DecodeInputObject (K1 i a) where
-  decodeObject = fmap K1 . decode
+instance Decode a => Decode (Maybe a) where
+  decode = withMaybe decode
 
-decode ::
-     forall a. Decode a (KIND a)
-  => Value
-  -> Validation a
-decode = __decode (Proxy @(KIND a))
+instance Decode a => Decode [a] where
+  decode = withList decode
 
--- | Decode GraphQL query arguments and input values
-class Decode a (b :: GQL_KIND) where
-  __decode :: Proxy b -> Value -> Validation a
+-- | Decode GraphQL type with Specific Kind
+class DecodeKind (kind :: GQL_KIND) a where
+  decodeKind :: Proxy kind -> Value -> Validation a
 
---
 -- SCALAR
---
-instance (GQLScalar a) => Decode a SCALAR where
-  __decode _ value =
+instance (GQLScalar a) => DecodeKind SCALAR a where
+  decodeKind _ value =
     case toScalar value >>= parseValue of
       Right scalar      -> return scalar
       Left errorMessage -> internalTypeMismatch errorMessage value
 
---
 -- ENUM
---
-instance (Generic a, EnumRep (Rep a)) => Decode a ENUM where
-  __decode _ (Enum value) = to <$> decodeEnum value
-  __decode _ isType       = internalTypeMismatch "Enum" isType
+instance (Generic a, EnumRep (Rep a)) => DecodeKind ENUM a where
+  decodeKind _ = withEnum (fmap to . decodeEnum)
 
---
 -- INPUT_OBJECT
---
-instance (Generic a, DecodeInputObject (Rep a)) => Decode a INPUT_OBJECT where
-  __decode _ (Object x) = to <$> decodeObject (Object x)
-  __decode _ isType     = internalTypeMismatch "InputObject" isType
+instance DecodeObject a => DecodeKind INPUT_OBJECT a where
+  decodeKind _ = withObject decodeObject
 
---
 -- INPUT_UNION
---
-instance (Generic a, DecodeInputUnion (Rep a)) => Decode a INPUT_UNION where
-  __decode _ (Object x) = to <$> decodeUnion (Object x)
-  __decode _ isType     = internalTypeMismatch "InputObject" isType
+instance (Generic a, GDecode (Rep a)) => DecodeKind INPUT_UNION a where
+  decodeKind _ = withObject (fmap to . decodeUnion)
 
+-- GENERIC
+decodeArguments :: DecodeObject p => Arguments -> Validation p
+decodeArguments = decodeObject . fmap toObject
+  where
+    toObject (x, y) = (x, argumentValue y)
+
+class DecodeObject a where
+  decodeObject :: Object -> Validation a
+
+instance {-# OVERLAPPABLE #-} (Generic a, GDecode (Rep a)) => DecodeObject a where
+  decodeObject = fmap to . __decodeObject . Object
+
 --
--- WRAPPERS: Maybe, List
+-- GENERICS
 --
-instance Decode a (KIND a) => Decode (Maybe a) WRAPPER where
-  __decode _ Null = pure Nothing
-  __decode _ x    = Just <$> decode x
+class GDecode f where
+  unionTags :: Proxy f -> [Key]
+  decodeUnion :: Object -> Validation (f a)
+  __decodeObject :: Value -> Validation (f a)
 
-instance Decode a (KIND a) => Decode [a] WRAPPER where
-  __decode _ (List li) = mapM decode li
-  __decode _ isType    = internalTypeMismatch "List" isType
+instance GDecode U1 where
+  unionTags _ = []
+  __decodeObject _ = pure U1
+  decodeUnion _ = pure U1
+
+-- Recursive Decoding: (Selector (Rec1 ))
+instance (Selector s, GQLType a, Decode a) => GDecode (M1 S s (K1 i a)) where
+  unionTags _ = [__typeName (Proxy @a)]
+  decodeUnion = fmap (M1 . K1) . decode . Object
+  __decodeObject = fmap (M1 . K1) . decodeRec
+    where
+      fieldName = pack $ selName (undefined :: M1 S s f a)
+      decodeRec = withObject (decodeFieldWith decode fieldName)
+
+instance (Datatype c, GDecode f) => GDecode (M1 D c f) where
+  decodeUnion = fmap M1 . decodeUnion
+  unionTags _ = unionTags (Proxy @f)
+  __decodeObject = fmap M1 . __decodeObject
+
+instance (Constructor c, GDecode f) => GDecode (M1 C c f) where
+  decodeUnion = fmap M1 . decodeUnion
+  unionTags _ = unionTags (Proxy @f)
+  __decodeObject = fmap M1 . __decodeObject
+
+instance (GDecode f, GDecode g) => GDecode (f :*: g) where
+  __decodeObject gql = (:*:) <$> __decodeObject gql <*> __decodeObject gql
+
+instance (GDecode a, GDecode b) => GDecode (a :+: b) where
+  decodeUnion = withUnion handleUnion
+    where
+      handleUnion name unions object
+        | [name] == l1Tags = L1 <$> decodeUnion object
+        | [name] == r1Tags = R1 <$> decodeUnion object
+        | name `elem` l1Tags = L1 <$> decodeUnion unions
+        | name `elem` r1Tags = R1 <$> decodeUnion unions
+        | otherwise = internalArgumentError ("type \"" <> name <> "\" could not find in union")
+        where
+          l1Tags = unionTags $ Proxy @a
+          r1Tags = unionTags $ Proxy @b
+  unionTags _ = unionTags (Proxy @a) ++ unionTags (Proxy @b)
diff --git a/src/Data/Morpheus/Execution/Server/Encode.hs b/src/Data/Morpheus/Execution/Server/Encode.hs
--- a/src/Data/Morpheus/Execution/Server/Encode.hs
+++ b/src/Data/Morpheus/Execution/Server/Encode.hs
@@ -16,333 +16,220 @@
   ( EncodeCon
   , EncodeMutCon
   , EncodeSubCon
+  , GResolver(..)
+  , Encode(..)
   , encodeQuery
-  , encodeMut
-  , encodeSub
+  , encodeOperation
+  , ObjectResolvers(..)
+  , OBJ_RES
   ) where
 
 import           Control.Monad                                   ((>=>))
-import           Control.Monad.Trans.Except
+import           Control.Monad.Except                            (liftEither, runExceptT, withExceptT)
 import           Data.Map                                        (Map)
 import qualified Data.Map                                        as M (toList)
 import           Data.Maybe                                      (fromMaybe)
 import           Data.Proxy                                      (Proxy (..))
 import           Data.Set                                        (Set)
 import qualified Data.Set                                        as S (toList)
-import           Data.Text                                       (Text, pack)
-import           Data.Typeable                                   (Typeable)
+import           Data.Text                                       (pack)
 import           GHC.Generics
 
 -- MORPHEUS
 import           Data.Morpheus.Error.Internal                    (internalErrorT)
-import           Data.Morpheus.Error.Selection                   (fieldNotResolved, subfieldsNotSelected)
-import           Data.Morpheus.Execution.Server.Decode           (ArgumentsConstraint, decodeArguments)
+import           Data.Morpheus.Error.Selection                   (resolverError, subfieldsNotSelected)
+import           Data.Morpheus.Execution.Server.Decode           (DecodeObject, decodeArguments)
 import           Data.Morpheus.Execution.Server.Generics.EnumRep (EnumRep (..))
-import           Data.Morpheus.Kind                              (ENUM, GQL_KIND, OBJECT, SCALAR, UNION, WRAPPER)
+import           Data.Morpheus.Kind                              (Context (..), ENUM, GQL_KIND, OBJECT, SCALAR, UNION,
+                                                                  VContext (..))
 import           Data.Morpheus.Types.Custom                      (MapKind, Pair (..), mapKindFromList)
 import           Data.Morpheus.Types.GQLScalar                   (GQLScalar (..))
-import           Data.Morpheus.Types.GQLType                     (GQLType (KIND, __typeName))
+import           Data.Morpheus.Types.GQLType                     (GQLType (CUSTOM, KIND, __typeName))
 import           Data.Morpheus.Types.Internal.AST.Operation      (Operation (..), ValidOperation)
 import           Data.Morpheus.Types.Internal.AST.Selection      (Selection (..), SelectionRec (..), SelectionSet)
-import           Data.Morpheus.Types.Internal.Base               (Position)
-import           Data.Morpheus.Types.Internal.Stream             (PublishStream, StreamState (..), StreamT (..),
-                                                                  SubscribeStream)
+import           Data.Morpheus.Types.Internal.Base               (Key)
+import           Data.Morpheus.Types.Internal.Stream             (PublishStream, StreamT (..), SubscribeStream,
+                                                                  initExceptStream, injectEvents)
 import           Data.Morpheus.Types.Internal.Validation         (GQLErrors, ResolveT, failResolveT)
-import           Data.Morpheus.Types.Internal.Value              (ScalarValue (..), Value (..))
-import           Data.Morpheus.Types.Resolver                    (Event (..), Resolver, SubResolveT, SubResolver)
-
-type EncodeOperator m a value
-   = Resolver m a -> ValidOperation -> m (Either GQLErrors value)
-
--- EXPORT -------------------------------------------------------
-type EncodeCon m a v
-   = (Generic a, Typeable a, ObjectFieldResolvers (Rep a) (ResolveT m v))
+import           Data.Morpheus.Types.Internal.Value              (GQLValue (..), Value (..))
+import           Data.Morpheus.Types.Resolver                    (Event (..), Resolver, SubResolveT, SubResolver (..))
 
-type EncodeMutCon m event con mut
-   = EncodeCon (PublishStream m event con) mut Value
+class Encode resolver value where
+  encode :: resolver -> (Key, Selection) -> value
 
-type EncodeSubCon m event con sub
-   = EncodeCon (SubscribeStream m event) sub (Event event con -> ResolveT m Value)
+instance {-# OVERLAPPABLE #-} EncodeKind (KIND a) a res => Encode a res where
+  encode resolver = encodeKind (VContext resolver :: VContext (KIND a) a)
 
-encodeQuery ::
-     (Monad m, EncodeCon m schema Value, EncodeCon m a Value)
-  => schema
-  -> EncodeOperator m a Value
-encodeQuery types rootResolver operator@Operation {operationSelection} =
-  runExceptT
-    (fmap resolversBy (operatorToResolveT operator rootResolver) >>=
-     resolveBySelection operationSelection . (++) (resolversBy types))
+-- MAYBE
+instance (GQLValue value, Encode a value) => Encode (Maybe a) value where
+  encode Nothing      = const gqlNull
+  encode (Just value) = encode value
 
-encodeMut :: (Monad m, EncodeCon m a Value) => EncodeOperator m a Value
-encodeMut = encodeOperator resolveBySelection
+--  Tuple  (a,b)
+instance Encode (Pair k v) value => Encode (k, v) value where
+  encode (key, value) = encode (Pair key value)
 
-encodeSub ::
-     (Monad m, EncodeSubCon m event con a)
-  => EncodeOperator (SubscribeStream m event) a (Event event con -> ResolveT m Value)
-encodeSub = encodeOperator (flip resolveSelection)
-  where
-    resolveSelection resolvers =
-      fmap toObj . mapM (selectResolver (const $ pure Null) resolvers)
-      where
-        toObj pairs args =
-          Object <$> mapM (\(key, valFunc) -> (key, ) <$> valFunc args) pairs
+--  Set
+instance Encode [a] value => Encode (Set a) value where
+  encode = encode . S.toList
 
----------------------------------------------------------
---
---  OBJECT
--- | Derives resolvers by object fields
-class ObjectFieldResolvers f o where
-  objectFieldResolvers :: f a -> [(Text, (Text, Selection) -> o)]
+--  Map
+instance (Eq k, Monad m, Encode (MapKind k v (Resolver m)) (ResolveT m value)) =>
+         Encode (Map k v) (ResolveT m value) where
+  encode value = encode ((mapKindFromList $ M.toList value) :: MapKind k v (Resolver m))
 
-instance ObjectFieldResolvers U1 res where
-  objectFieldResolvers _ = []
+-- LIST []
+instance (Monad m, GQLValue value, Encode a (m value)) => Encode [a] (m value) where
+  encode list query = gqlList <$> traverse (`encode` query) list
 
-instance (Selector s, Encoder a (KIND a) res) =>
-         ObjectFieldResolvers (M1 S s (K1 s2 a)) res where
-  objectFieldResolvers m@(M1 (K1 src)) = [(pack $ selName m, encode src)]
+--  GQL a -> b
+instance (DecodeObject a, Monad m, Encode b (ResolveT m value)) => Encode (a -> b) (ResolveT m value) where
+  encode resolver selection = decodeArgs selection >>= (`encode` selection) . resolver
+    where
+      decodeArgs :: (Key, Selection) -> ResolveT m a
+      decodeArgs = liftEither . decodeArguments . selectionArguments . snd
 
-instance ObjectFieldResolvers f res => ObjectFieldResolvers (M1 D c f) res where
-  objectFieldResolvers (M1 src) = objectFieldResolvers src
+-- GQL Either Resolver Monad
+instance (Monad m, Encode a (ResolveT m value)) => Encode (Either String a) (ResolveT m value) where
+  encode resolver = (`encodeResolver` liftEither resolver)
 
-instance ObjectFieldResolvers f res => ObjectFieldResolvers (M1 C c f) res where
-  objectFieldResolvers (M1 src) = objectFieldResolvers src
+--  GQL ExceptT Resolver Monad
+instance (Monad m, Encode b (ResolveT m value)) => Encode (Resolver m b) (ResolveT m value) where
+  encode = flip encodeResolver
 
-instance (ObjectFieldResolvers f res, ObjectFieldResolvers g res) =>
-         ObjectFieldResolvers (f :*: g) res where
-  objectFieldResolvers (a :*: b) =
-    objectFieldResolvers a ++ objectFieldResolvers b
+-- GQL Mutation Resolver Monad
+instance (Monad m, Encode b (ResolveT m value)) => Encode (Resolver m b) (ResolveT (StreamT m c) value) where
+  encode resolver = injectEvents [] . encode resolver
 
---
--- UNION
---
-class UnionResolvers f result where
-  unionResolvers :: f a -> (Text, (Text, Selection) -> result)
+-- GQL Subscription Resolver Monad
+instance (Monad m, Encode b (ResolveT m Value)) => Encode (SubResolver m e c b) (SubResolveT m e c Value) where
+  encode resolver selection = handleResolver resolver
+    where
+      handleResolver SubResolver {subChannels, subResolver} =
+        initExceptStream [subChannels] (encodeResolver selection . subResolver)
 
-instance UnionResolvers f res => UnionResolvers (M1 S s f) res where
-  unionResolvers (M1 x) = unionResolvers x
+-- ENCODE GQL KIND
+class EncodeKind (kind :: GQL_KIND) a value where
+  encodeKind :: VContext kind a -> (Key, Selection) -> value
 
-instance UnionResolvers f res => UnionResolvers (M1 D c f) res where
-  unionResolvers (M1 x) = unionResolvers x
+-- SCALAR
+instance (GQLScalar a, GQLValue value) => EncodeKind SCALAR a value where
+  encodeKind = pure . gqlScalar . serialize . unVContext
 
-instance UnionResolvers f res => UnionResolvers (M1 C c f) res where
-  unionResolvers (M1 x) = unionResolvers x
+-- ENUM
+instance (Generic a, EnumRep (Rep a), GQLValue value) => EncodeKind ENUM a value where
+  encodeKind = pure . gqlString . encodeRep . from . unVContext
 
-instance (UnionResolvers a res, UnionResolvers b res) =>
-         UnionResolvers (a :+: b) res where
-  unionResolvers (L1 x) = unionResolvers x
-  unionResolvers (R1 x) = unionResolvers x
+--  OBJECT
+instance (Monad m, EncodeCon m a value, GQLValue value) => EncodeKind OBJECT a (ResolveT m value) where
+  encodeKind (VContext value) (_, Selection {selectionRec = SelectionSet selection}) =
+    resolveFields selection (__typenameResolver : objectResolvers (Proxy :: Proxy (CUSTOM a)) value)
+    where
+      __typenameResolver = ("__typename", const $ pure $ gqlString $ __typeName (Proxy @a))
+  encodeKind _ (key, Selection {selectionPosition}) = failResolveT $ subfieldsNotSelected key "" selectionPosition
 
-type ObjectConstraint a m
-   = ( Monad m
-     , Generic a
-     , GQLType a
-     , ObjectFieldResolvers (Rep a) (ResolveT m Value))
+-- UNION
+instance (Monad m, GQL_RES a, GResolver UNION (Rep a) (ResolveT m value)) => EncodeKind UNION a (ResolveT m value) where
+  encodeKind (VContext value) (key, sel@Selection {selectionRec = UnionSelection selections}) =
+    resolver (key, sel {selectionRec = SelectionSet lookupSelection})
+      -- SPEC: if there is no any fragment that supports current object Type GQL returns {}
+    where
+      lookupSelection = fromMaybe [] $ lookup typeName selections
+      (typeName, resolver) = unionResolver value
+  encodeKind _ _ = internalErrorT "union Resolver only should recieve UnionSelection"
 
-type UnionConstraint a m
-   = (Monad m, Generic a, GQLType a, UnionResolvers (Rep a) (ResolveT m Value))
+-- Types & Constrains -------------------------------------------------------
+type GQL_RES a = (Generic a, GQLType a)
 
-type EnumConstraint a = (Generic a, EnumRep (Rep a))
+type EncodeOperator m a value = Resolver m a -> ValidOperation -> m (Either GQLErrors value)
 
-newtype WithGQLKind a (b :: GQL_KIND) =
-  WithGQLKind
-    { resolverValue :: a
-    }
+type OBJ_RES m a value = ObjectResolvers (CUSTOM a) a (ResolveT m value)
 
-type GQLKindOf a = WithGQLKind a (KIND a)
+type EncodeCon m a value = (GQL_RES a, OBJ_RES m a value)
 
-encode ::
-     forall a result. Encoder a (KIND a) result
-  => a
-  -> (Text, Selection)
-  -> result
-encode resolver = __encode (WithGQLKind resolver :: GQLKindOf a)
+type EncodeMutCon m event con mut = EncodeCon (PublishStream m event con) mut Value
 
-class Encoder a kind result where
-  __encode :: WithGQLKind a kind -> (Text, Selection) -> result
+type EncodeSubCon m event con sub = EncodeCon (SubscribeStream m event) sub (Event event con -> ResolveT m Value)
 
-type ResValue m = (ResolveT m Value)
+type FieldRes m value = (Key, (Key, Selection) -> ResolveT m value)
 
---
--- SCALAR
---
-instance (GQLScalar a, Monad m) => Encoder a SCALAR (ResValue m) where
-  __encode = pure . pure . Scalar . serialize . resolverValue
+type family GRes (kind :: GQL_KIND) value :: *
 
---
--- ENUM
---
-instance (EnumConstraint a, Monad m) => Encoder a ENUM (ResValue m) where
-  __encode = pure . pure . Scalar . String . encodeRep . from . resolverValue
+type instance GRes OBJECT v = [(Key, (Key, Selection) -> v)]
 
---
---  OBJECTS
---
-instance ObjectConstraint a m => Encoder a OBJECT (ResValue m) where
-  __encode (WithGQLKind value) (_, Selection {selectionRec = SelectionSet selection'}) =
-    resolveBySelection selection' (__typenameResolver : resolversBy value)
-    where
-      __typenameResolver =
-        ("__typename", const $ return $ Scalar $ String $ __typeName (Proxy @a))
-  __encode _ (key, Selection {selectionPosition}) =
-    failResolveT $ subfieldsNotSelected key "" selectionPosition
+type instance GRes UNION v = (Key, (Key, Selection) -> v)
 
--- | Resolves and encodes UNION,
--- Handles all operators: Query, Mutation and Subscription,
-instance UnionConstraint a m => Encoder a UNION (ResValue m) where
-  __encode (WithGQLKind value) (key', sel@Selection {selectionRec = UnionSelection selections'}) =
-    resolver (key', sel {selectionRec = SelectionSet lookupSelection})
-    where
-      lookupSelection :: SelectionSet
-      -- SPEC: if there is no any fragment that supports current object Type GQL returns {}
-      lookupSelection = fromMaybe [] $ lookup typeName selections'
-      (typeName, resolver) = unionResolvers (from value)
-  __encode _ _ =
-    internalErrorT "union Resolver only should recieve UnionSelection"
+--- GENERICS ------------------------------------------------
+class ObjectResolvers (custom :: Bool) a value where
+  objectResolvers :: Proxy custom -> a -> [(Key, (Key, Selection) -> value)]
 
-instance (GQLType a, Encoder a (KIND a) result) =>
-         UnionResolvers (K1 s a) result where
-  unionResolvers (K1 src) = (__typeName (Proxy @a), encode src)
+instance (Generic a, GResolver OBJECT (Rep a) value) => ObjectResolvers 'False a value where
+  objectResolvers _ = getResolvers (Context :: Context OBJECT value) . from
 
---
---  RESOLVERS
---
--- | Handles all operators: Query, Mutation and Subscription,
--- if you use it with Mutation or Subscription all effects inside will be lost
-instance (ArgumentsConstraint a, Monad m, Encoder b (KIND b) (ResValue m)) =>
-         Encoder (a -> Resolver m b) WRAPPER (ResValue m) where
-  __encode (WithGQLKind resolver) selection =
-    decodeArgs selection >>= encodeResolver selection . resolver
+unionResolver :: (Generic a, GResolver UNION (Rep a) value) => a -> (Key, (Key, Selection) -> value)
+unionResolver = getResolvers (Context :: Context UNION value) . from
 
--- packs Monad in StreamMonad
-instance (Monad m, Encoder a (KIND a) (ResValue m), ArgumentsConstraint p) =>
-         Encoder (p -> Either String a) WRAPPER (ResValue m) where
-  __encode (WithGQLKind resolver) selection =
-    decodeArgs selection >>=
-    encodeResolver selection . (ExceptT . pure . resolver)
+-- | Derives resolvers for OBJECT and UNION
+class GResolver (kind :: GQL_KIND) f value where
+  getResolvers :: Context kind value -> f a -> GRes kind value
 
--- packs Monad in StreamMonad
-instance (ArgumentsConstraint a, Monad m, Encoder b (KIND b) (ResValue m)) =>
-         Encoder (a -> Resolver m b) WRAPPER (ResValue (StreamT m c)) where
-  __encode resolver selection =
-    ExceptT $
-    StreamT $ StreamState [] <$> runExceptT (__encode resolver selection)
+instance GResolver kind f value => GResolver kind (M1 D c f) value where
+  getResolvers context (M1 src) = getResolvers context src
 
-instance (ArgumentsConstraint a, Monad m, Encoder b (KIND b) (ResValue m)) =>
-         Encoder (a -> SubResolver m e c b) WRAPPER (SubResolveT m e c Value) where
-  __encode (WithGQLKind resolver) selection =
-    decodeArgs selection >>= handleResolver . resolver
-    where
-      handleResolver Event {channels, content} =
-        ExceptT $
-        StreamT $
-        pure $
-        StreamState [channels] (Right $ encodeResolver selection . content)
+instance GResolver kind f value => GResolver kind (M1 C c f) value where
+  getResolvers context (M1 src) = getResolvers context src
 
---
--- MAYBE
---
-instance (Monad m, Encoder a (KIND a) (ResValue m)) =>
-         Encoder (Maybe a) WRAPPER (ResValue m) where
-  __encode (WithGQLKind Nothing)      = const $ pure Null
-  __encode (WithGQLKind (Just value)) = encode value
+-- OBJECT
+instance GResolver OBJECT U1 value where
+  getResolvers _ _ = []
 
---
--- LIST
---
-instance (Monad m, Encoder a (KIND a) (ResValue m)) =>
-         Encoder [a] WRAPPER (ResValue m) where
-  __encode (WithGQLKind list) query =
-    List <$> mapM (`__encode` query) (map WithGQLKind list :: [GQLKindOf a])
+instance (Selector s, GQLType a, Encode a value) => GResolver OBJECT (M1 S s (K1 s2 a)) value where
+  getResolvers _ m@(M1 (K1 src)) = [(pack (selName m), encode src)]
 
---
---  Tuple
---
-instance Encoder (Pair k v) OBJECT (ResValue m) =>
-         Encoder (k, v) WRAPPER (ResValue m) where
-  __encode (WithGQLKind (key, value)) = encode (Pair key value)
+instance (GResolver OBJECT f value, GResolver OBJECT g value) => GResolver OBJECT (f :*: g) value where
+  getResolvers context (a :*: b) = getResolvers context a ++ getResolvers context b
 
---
---  Set
---
-instance Encoder [a] WRAPPER result => Encoder (Set a) WRAPPER result where
-  __encode (WithGQLKind dataSet) = encode (S.toList dataSet)
+-- UNION
+instance (Selector s, GQLType a, Encode a value) => GResolver UNION (M1 S s (K1 s2 a)) value where
+  getResolvers _ (M1 (K1 src)) = (__typeName (Proxy @a), encode src)
 
---
---  Map
---
-instance (Eq k, Monad m, Encoder (MapKind k v (Resolver m)) OBJECT (ResValue m)) =>
-         Encoder (Map k v) WRAPPER (ResValue m) where
-  __encode (WithGQLKind value) =
-    encode ((mapKindFromList $ M.toList value) :: MapKind k v (Resolver m))
+instance (GResolver UNION a value, GResolver UNION b value) => GResolver UNION (a :+: b) value where
+  getResolvers context (L1 x) = getResolvers context x
+  getResolvers context (R1 x) = getResolvers context x
 
 ----- HELPERS ----------------------------
-type ResolveSel result
-   = SelectionSet -> [(Text, (Text, Selection) -> result)] -> result
+encodeQuery ::
+     forall m a schema. (GQL_RES a, GQL_RES schema, Monad m, EncodeCon m schema Value, EncodeCon m a Value)
+  => schema
+  -> EncodeOperator m a Value
+encodeQuery schema = encodeOperationWith (objectResolvers (Proxy :: Proxy (CUSTOM schema)) schema)
 
-resolverToResolveT ::
-     Monad m => Position -> Text -> Resolver m a -> ResolveT m a
-resolverToResolveT pos name = ExceptT . toResolveM
+encodeOperation :: (Monad m, GQL_RES a, EncodeCon m a value, GQLValue value) => EncodeOperator m a value
+encodeOperation = encodeOperationWith []
+
+encodeOperationWith ::
+     forall m a value. (Monad m, GQL_RES a, GQLValue value, EncodeCon m a value)
+  => [FieldRes m value]
+  -> EncodeOperator m a value
+encodeOperationWith externalRes rootResolver Operation {operationSelection, operationPosition, operationName} =
+  runExceptT $
+  operationResolveT >>=
+  resolveFields operationSelection . (++) externalRes . objectResolvers (Proxy :: Proxy (CUSTOM a))
   where
-    toResolveM :: Monad m => Resolver m a -> m (Either GQLErrors a)
-    toResolveM resolver = runExceptT resolver >>= runExceptT . liftEither
-      where
-        liftEither :: Monad m => Either String a -> ResolveT m a
-        liftEither (Left message) =
-          failResolveT $ fieldNotResolved pos name (pack message)
-        liftEither (Right value) = pure value
+    operationResolveT = withExceptT (resolverError operationPosition operationName) rootResolver
 
-encodeResolver ::
-     (Monad m, Encoder a (KIND a) (ResValue m))
-  => (Text, Selection)
-  -> Resolver m a
-  -> ResValue m
+encodeResolver :: (Monad m, Encode a (ResolveT m res)) => (Key, Selection) -> Resolver m a -> ResolveT m res
 encodeResolver selection@(fieldName, Selection {selectionPosition}) =
-  resolverToResolveT selectionPosition fieldName >=> (`encode` selection)
-
-decodeArgs ::
-     (Monad m, ArgumentsConstraint a) => (Text, Selection) -> ResolveT m a
-decodeArgs (_, Selection {selectionArguments}) =
-  ExceptT $ pure $ decodeArguments selectionArguments
-
-operatorToResolveT :: Monad m => ValidOperation -> Resolver m a -> ResolveT m a
-operatorToResolveT Operation {operationPosition, operationName} =
-  resolverToResolveT operationPosition operationName
-
-encodeOperator ::
-     (Monad m, EncodeCon m a v)
-  => ResolveSel (ResolveT m v)
-  -> EncodeOperator m a v
-encodeOperator resSel rootResolver operation@Operation {operationSelection} =
-  runExceptT
-    (operatorToResolveT operation rootResolver >>=
-     resSel operationSelection . resolversBy)
-
-resolveBySelection :: Monad m => ResolveSel (ResolveT m Value)
-resolveBySelection selection resolvers =
-  Object <$> mapM (selectResolver Null resolvers) selection
+  withExceptT (resolverError selectionPosition fieldName) >=> (`encode` selection)
 
-selectResolver ::
-     Monad m
-  => a
-  -> [(Text, (Text, Selection) -> m a)]
-  -> (Text, Selection)
-  -> m (Text, a)
-selectResolver defaultValue resolvers (key, selection) =
-  case selectionRec selection of
-    SelectionAlias name selectionRec ->
-      unwrapMonadTuple (key, lookupResolver name (selection {selectionRec}))
-    _ -> unwrapMonadTuple (key, lookupResolver key selection)
+resolveFields :: (Monad m, GQLValue a) => SelectionSet -> [FieldRes m a] -> ResolveT m a
+resolveFields selectionSet resolvers = gqlObject <$> traverse selectResolver selectionSet
   where
-    unwrapMonadTuple :: Monad m => (Text, m a) -> m (Text, a)
-    unwrapMonadTuple (text, ioa) = ioa >>= \x -> pure (text, x)
-    -------------------------------------------------------------
-    lookupResolver resolverKey sel =
-      (fromMaybe (const $ return $defaultValue) $ lookup resolverKey resolvers)
-        (key, sel)
-
-resolversBy ::
-     (Generic a, ObjectFieldResolvers (Rep a) result)
-  => a
-  -> [(Text, (Text, Selection) -> result)]
-resolversBy = objectFieldResolvers . from
---------------------------------------------
+    selectResolver (key, selection) =
+      (key, ) <$>
+      case selectionRec selection of
+        SelectionAlias name selectionRec -> lookupRes name (selection {selectionRec})
+        _                                -> lookupRes key selection
+        -------------------------------------------------------------
+      where
+        lookupRes resKey sel = (fromMaybe (const $ return gqlNull) $ lookup resKey resolvers) (key, sel)
diff --git a/src/Data/Morpheus/Execution/Server/Introspect.hs b/src/Data/Morpheus/Execution/Server/Introspect.hs
--- a/src/Data/Morpheus/Execution/Server/Introspect.hs
+++ b/src/Data/Morpheus/Execution/Server/Introspect.hs
@@ -1,4 +1,6 @@
 {-# LANGUAGE ConstraintKinds       #-}
+{-# LANGUAGE DataKinds             #-}
+{-# LANGUAGE DefaultSignatures     #-}
 {-# LANGUAGE FlexibleContexts      #-}
 {-# LANGUAGE FlexibleInstances     #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
@@ -13,10 +15,13 @@
 {-# LANGUAGE UndecidableInstances  #-}
 
 module Data.Morpheus.Execution.Server.Introspect
-  ( introspectOutputType
-  , TypeUpdater
-  , ObjectRep(..)
+  ( TypeUpdater
+  , Introspect(..)
+  , ObjectFields(..)
+  , IntroCon
   , resolveTypes
+  , updateLib
+  , buildType
   ) where
 
 import           Control.Monad                                   (foldM)
@@ -31,349 +36,210 @@
 -- MORPHEUS
 import           Data.Morpheus.Error.Schema                      (nameCollisionError)
 import           Data.Morpheus.Execution.Server.Generics.EnumRep (EnumRep (..))
-import           Data.Morpheus.Kind                              (ENUM, INPUT_OBJECT, INPUT_UNION, OBJECT, SCALAR,
-                                                                  UNION, WRAPPER)
+import           Data.Morpheus.Kind                              (Context (..), ENUM, GQL_KIND, INPUT_OBJECT,
+                                                                  INPUT_UNION, OBJECT, SCALAR, UNION)
 import           Data.Morpheus.Types.Custom                      (MapKind, Pair)
 import           Data.Morpheus.Types.GQLScalar                   (GQLScalar (..))
 import           Data.Morpheus.Types.GQLType                     (GQLType (..))
 import           Data.Morpheus.Types.Internal.Data               (DataArguments, DataField (..), DataFullType (..),
-                                                                  DataInputField, DataLeaf (..), DataType (..),
-                                                                  DataTypeLib, DataTypeWrapper (..), DataValidator,
-                                                                  defineType, isTypeDefined)
+                                                                  DataLeaf (..), DataTyCon (..), DataTypeLib,
+                                                                  TypeAlias (..), defineType, isTypeDefined,
+                                                                  toListField, toNullableField)
 import           Data.Morpheus.Types.Internal.Validation         (SchemaValidation)
-import           Data.Morpheus.Types.Resolver                    (Resolver, SubResolver)
 
-type SelOf s = M1 S s (Rec0 ()) ()
-
-type RecSel s a = M1 S s (Rec0 a)
-
-type TypeUpdater = DataTypeLib -> SchemaValidation DataTypeLib
-
---
---  GENERIC UNION
---
-class UnionRep f t where
-  possibleTypes :: Proxy f -> Proxy t -> [(DataField (), TypeUpdater)]
-
-instance UnionRep f t => UnionRep (M1 D x f) t where
-  possibleTypes _ = possibleTypes (Proxy @f)
-
-instance UnionRep f t => UnionRep (M1 C x f) t where
-  possibleTypes _ = possibleTypes (Proxy @f)
-
-instance (UnionRep a t, UnionRep b t) => UnionRep (a :+: b) t where
-  possibleTypes _ x = possibleTypes (Proxy @a) x ++ possibleTypes (Proxy @b) x
-
---
---  GENERIC OBJECT: INPUT and OUTPUT plus ARGUMENTS
---
-resolveTypes :: DataTypeLib -> [TypeUpdater] -> SchemaValidation DataTypeLib
-resolveTypes = foldM (&)
-
-class ObjectRep rep t where
-  objectFieldTypes :: Proxy rep -> [((Text, DataField t), TypeUpdater)]
-
-instance ObjectRep f t => ObjectRep (M1 D x f) t where
-  objectFieldTypes _ = objectFieldTypes (Proxy @f)
-
-instance ObjectRep f t => ObjectRep (M1 C x f) t where
-  objectFieldTypes _ = objectFieldTypes (Proxy @f)
-
-instance (ObjectRep a t, ObjectRep b t) => ObjectRep (a :*: b) t where
-  objectFieldTypes _ =
-    objectFieldTypes (Proxy @a) ++ objectFieldTypes (Proxy @b)
-
-instance ObjectRep U1 t where
-  objectFieldTypes _ = []
-
--- class Types class
-type GQL_TYPE a = (Generic a, GQLType a)
-
-type EnumConstraint a = (GQL_TYPE a, EnumRep (Rep a))
-
-type InputObjectConstraint a = (GQL_TYPE a, ObjectRep (Rep a) ())
-
-type ObjectConstraint a = (GQL_TYPE a, ObjectRep (Rep a) DataArguments)
-
-scalarTypeOf :: GQLType a => DataValidator -> Proxy a -> DataFullType
-scalarTypeOf validator = Leaf . CustomScalar . buildType validator
-
-enumTypeOf :: GQLType a => [Text] -> Proxy a -> DataFullType
-enumTypeOf tags' = Leaf . LeafEnum . buildType tags'
-
-type InputType = ()
-
-type OutputType = DataArguments
+type IntroCon a = (GQLType a, ObjectFields (CUSTOM a) a)
 
-type InputOf t = Context t (KIND t) InputType
+-- |  Generates internal GraphQL Schema for query validation and introspection rendering
+class Introspect a where
+  field :: proxy a -> Text -> DataField
+  introspect :: proxy a -> TypeUpdater
+  -----------------------------------------------
+  default field :: GQLType a =>
+    proxy a -> Text -> DataField
+  field _ = buildField (Proxy @a) []
 
-type OutputOf t = Context t (KIND t) OutputType
+instance {-# OVERLAPPABLE #-} (GQLType a, IntrospectKind (KIND a) a) => Introspect a where
+  introspect _ = introspectKind (Context :: Context (KIND a) a)
 
-introspectOutputType ::
-     forall a. Introspect a (KIND a) OutputType
-  => Proxy a
-  -> TypeUpdater
-introspectOutputType _ = introspect (Context :: OutputOf a)
+-- Maybe
+instance Introspect a => Introspect (Maybe a) where
+  field _ = toNullableField . field (Proxy @a)
+  introspect _ = introspect (Proxy @a)
 
--- | context , like Proxy with multiple parameters
--- contains types of :
--- * 'a': actual gql type
--- * 'kind': object, scalar, enum ...
--- * 'args': InputType | OutputType
-data Context a kind args =
-  Context
+-- List
+instance Introspect a => Introspect [a] where
+  field _ = toListField . field (Proxy @a)
+  introspect _ = introspect (Proxy @a)
 
-buildField :: GQLType a => Proxy a -> t -> Text -> DataField t
-buildField proxy fieldArgs fieldName =
-  DataField
-    { fieldName
-    , fieldArgs
-    , fieldTypeWrappers = [NonNullType]
-    , fieldType = __typeName proxy
-    , fieldHidden = False
-    }
+-- Tuple
+instance Introspect (Pair k v) => Introspect (k, v) where
+  field _ = field (Proxy @(Pair k v))
+  introspect _ = introspect (Proxy @(Pair k v))
 
-buildType :: GQLType a => t -> Proxy a -> DataType t
-buildType typeData proxy =
-  DataType
-    { typeName = __typeName proxy
-    , typeFingerprint = __typeFingerprint proxy
-    , typeDescription = description proxy
-    , typeVisibility = __typeVisibility proxy
-    , typeData
-    }
+-- Set
+instance Introspect [a] => Introspect (Set a) where
+  field _ = field (Proxy @[a])
+  introspect _ = introspect (Proxy @[a])
 
-updateLib ::
-     GQLType a
-  => (Proxy a -> DataFullType)
-  -> [TypeUpdater]
-  -> Proxy a
-  -> TypeUpdater
-updateLib typeBuilder stack proxy lib' =
-  case isTypeDefined (__typeName proxy) lib' of
-    Nothing ->
-      resolveTypes (defineType (__typeName proxy, typeBuilder proxy) lib') stack
-    Just fingerprint'
-      | fingerprint' == __typeFingerprint proxy -> return lib'
-    -- throw error if 2 different types has same name
-    Just _ -> Left $ nameCollisionError (__typeName proxy)
+-- Map
+instance Introspect (MapKind k v Maybe) => Introspect (Map k v) where
+  field _ = field (Proxy @(MapKind k v Maybe))
+  introspect _ = introspect (Proxy @(MapKind k v Maybe))
 
--- |   Generates internal GraphQL Schema for query validation and introspection rendering
--- * 'kind': object, scalar, enum ...
--- * 'args': type of field arguments
---    * '()' for 'input values' , they are just JSON properties and does not have any argument
---    * 'DataArguments' for field Resolvers Types, where 'DataArguments' is type of arguments
-class Introspect a kind args where
-  __field :: Context a kind args -> Text -> DataField args
-    --   generates data field representation of object field
-    --   according to parameter 'args' it could be
-    --   * input object field: if args is '()'
-    --   * object: if args is 'DataArguments'
-  introspect :: Context a kind args -> TypeUpdater -- Generates internal GraphQL Schema
+-- Resolver : a -> Resolver b
+instance (ObjectFields 'False a, Introspect b) => Introspect (a -> m b) where
+  field _ name = (field (Proxy @b) name) {fieldArgs = fst $ objectFields (Proxy :: Proxy 'False) (Proxy @a)}
+  introspect _ typeLib = resolveTypes typeLib (introspect (Proxy @b) : argTypes)
+    where
+      argTypes :: [TypeUpdater]
+      argTypes = snd $ objectFields (Proxy :: Proxy 'False) (Proxy @a)
 
-type OutputConstraint a = Introspect a (KIND a) DataArguments
+-- | Introspect With specific Kind: 'kind': object, scalar, enum ...
+class IntrospectKind (kind :: GQL_KIND) a where
+  introspectKind :: Context kind a -> TypeUpdater -- Generates internal GraphQL Schema
 
---
 -- SCALAR
---
-instance (GQLScalar a, GQLType a) => Introspect a SCALAR InputType where
-  __field _ = buildField (Proxy @a) ()
-  introspect _ =
-    updateLib (scalarTypeOf (scalarValidator $ Proxy @a)) [] (Proxy @a)
-
-instance (GQLScalar a, GQLType a) => Introspect a SCALAR OutputType where
-  __field _ = buildField (Proxy @a) []
-  introspect _ =
-    updateLib (scalarTypeOf (scalarValidator $ Proxy @a)) [] (Proxy @a)
+instance (GQLType a, GQLScalar a) => IntrospectKind SCALAR a where
+  introspectKind _ = updateLib scalarType [] (Proxy @a)
+    where
+      scalarType = Leaf . CustomScalar . buildType (scalarValidator (Proxy @a))
 
---
 -- ENUM
---
-instance EnumConstraint a => Introspect a ENUM InputType where
-  __field _ = buildField (Proxy @a) ()
-  introspect _ = introspectEnum (Context :: InputOf a)
-
-instance EnumConstraint a => Introspect a ENUM OutputType where
-  __field _ = buildField (Proxy @a) []
-  introspect _ = introspectEnum (Context :: OutputOf a)
-
-introspectEnum ::
-     forall a f. (GQLType a, EnumRep (Rep a))
-  => Context a (KIND a) f
-  -> TypeUpdater
-introspectEnum _ =
-  updateLib (enumTypeOf $ enumTags (Proxy @(Rep a))) [] (Proxy @a)
+instance (GQL_TYPE a, EnumRep (Rep a)) => IntrospectKind ENUM a where
+  introspectKind _ = updateLib enumType [] (Proxy @a)
+    where
+      enumType = Leaf . LeafEnum . buildType (enumTags (Proxy @(Rep a)))
 
---
--- OBJECTS , INPUT_OBJECT
---
-instance InputObjectConstraint a => Introspect a INPUT_OBJECT InputType where
-  __field _ = buildField (Proxy @a) ()
-  introspect _ = updateLib (InputObject . buildType fields') stack' (Proxy @a)
+-- INPUT_OBJECT
+instance (GQL_TYPE a, ObjectFields (CUSTOM a) a) => IntrospectKind INPUT_OBJECT a where
+  introspectKind _ = updateLib (InputObject . buildType fields) types (Proxy @a)
     where
-      (fields', stack') = unzip $ objectFieldTypes (Proxy @(Rep a))
+      (fields, types) = objectFields (Proxy @(CUSTOM a)) (Proxy @a)
 
-instance ObjectConstraint a => Introspect a OBJECT OutputType where
-  __field _ = buildField (Proxy @a) []
-  introspect _ =
-    updateLib
-      (OutputObject . buildType (__typename : fields'))
-      stack'
-      (Proxy @a)
+-- OBJECTS
+instance (GQL_TYPE a, ObjectFields (CUSTOM a) a) => IntrospectKind OBJECT a where
+  introspectKind _ = updateLib (OutputObject . buildType (__typename : fields)) types (Proxy @a)
     where
       __typename =
         ( "__typename"
         , DataField
             { fieldName = "__typename"
             , fieldArgs = []
-            , fieldTypeWrappers = []
-            , fieldType = "String"
+            , fieldArgsType = Nothing
+            , fieldType = buildAlias "String"
             , fieldHidden = True
             })
-      (fields', stack') = unzip $ objectFieldTypes (Proxy @(Rep a))
-
--- | recursion for Object types, both of them : 'INPUT_OBJECT' and 'OBJECT'
--- iterates on field types  and introspects them recursively
-instance (Selector s, Introspect a (KIND a) f) => ObjectRep (RecSel s a) f where
-  objectFieldTypes _ =
-    [ ( (name, __field (Context :: Context a (KIND a) f) name)
-      , introspect (Context :: Context a (KIND a) f))
-    ]
-    where
-      name = pack $ selName (undefined :: SelOf s)
+      (fields, types) = objectFields (Proxy @(CUSTOM a)) (Proxy @a)
 
---
 -- UNION
---
--- | recursion for union types
--- iterates on possible types for UNION and introspects them recursively
-instance (OutputConstraint a, ObjectConstraint a) =>
-         UnionRep (RecSel s a) OutputType where
-  possibleTypes _ _ =
-    [(buildField (Proxy @a) () "", introspect (Context :: OutputOf a))]
-
-instance (GQL_TYPE a, UnionRep (Rep a) OutputType) =>
-         Introspect a UNION OutputType where
-  __field _ = buildField (Proxy @a) []
-  introspect _ = updateLib (Union . buildType fields) stack (Proxy @a)
+instance (GQL_TYPE a, GQLRep UNION (Rep a)) => IntrospectKind UNION a where
+  introspectKind _ = updateLib (Union . buildType fields) stack (Proxy @a)
     where
-      (fields, stack) =
-        unzip $ possibleTypes (Proxy @(Rep a)) (Proxy @OutputType)
+      (fields, stack) = unzip $ gqlRep (Context :: Context UNION (Rep a))
 
---
 -- INPUT_UNION
---
-instance (GQL_TYPE a, Introspect a INPUT_OBJECT InputType) =>
-         UnionRep (RecSel s a) InputType where
-  possibleTypes _ _ =
-    [ ( maybeField $ buildField (Proxy @a) () (__typeName $ Proxy @a)
-      , introspect (Context :: Context a INPUT_OBJECT InputType))
-    ]
-
-instance (GQL_TYPE a, UnionRep (Rep a) InputType) =>
-         Introspect a INPUT_UNION InputType where
-  __field _ = buildField (Proxy @a) ()
-  introspect _ =
-    updateLib
-      (InputUnion . buildType (fieldTag : fields))
-      (tagsEnumType : stack)
-      (Proxy @a)
+instance (GQL_TYPE a, GQLRep UNION (Rep a)) => IntrospectKind INPUT_UNION a where
+  introspectKind _ = updateLib (InputUnion . buildType (fieldTag : fields)) (tagsEnumType : stack) (Proxy @a)
     where
-      (fields, stack) =
-        unzip $ possibleTypes (Proxy @(Rep a)) (Proxy @InputType)
+      (inputUnions, stack) = unzip $ gqlRep (Context :: Context UNION (Rep a))
+      fields = map toNullableField inputUnions
       -- for every input Union 'User' adds enum type of possible TypeNames 'UserTags'
       tagsEnumType :: TypeUpdater
-      tagsEnumType x =
-        pure $ defineType (enumTypeName, Leaf $ LeafEnum tagsEnum) x
+      tagsEnumType x = pure $ defineType (typeName, Leaf $ LeafEnum tagsEnum) x
         where
           tagsEnum =
-            DataType
-              { typeName = enumTypeName
-              -- has same fingerprint as object because it depends on it
+            DataTyCon
+              { typeName
+                -- has same fingerprint as object because it depends on it
               , typeFingerprint = __typeFingerprint (Proxy @a)
               , typeVisibility = __typeVisibility (Proxy @a)
-              , typeDescription = ""
-              , typeData = map fieldName fields
+              , typeDescription = Nothing
+              , typeData = map fieldName inputUnions
               }
-      enumTypeName = __typeName (Proxy @a) <> "Tags"
+      typeName = __typeName (Proxy @a) <> "Tags"
       fieldTag =
         DataField
           { fieldName = "tag"
-          , fieldArgs = ()
-          , fieldTypeWrappers = [NonNullType]
-          , fieldType = enumTypeName
+          , fieldArgs = []
+          , fieldArgsType = Nothing
+          , fieldType = buildAlias typeName
           , fieldHidden = False
           }
 
---
--- WRAPPER : Maybe, LIST , Resolver
---
-maybeField :: DataField f -> DataField f
-maybeField field@DataField {fieldTypeWrappers = NonNullType:xs} =
-  field {fieldTypeWrappers = xs}
-maybeField field = field
+-- Types
+type TypeUpdater = DataTypeLib -> SchemaValidation DataTypeLib
 
-instance Introspect a (KIND a) f => Introspect (Maybe a) WRAPPER f where
-  __field _ name = maybeField $ __field (Context :: Context a (KIND a) f) name
-  introspect _ = introspect (Context :: Context a (KIND a) f)
+type GQL_TYPE a = (Generic a, GQLType a)
 
-instance Introspect a (KIND a) f => Introspect [a] WRAPPER f where
-  __field _ name = listField (__field (Context :: Context a (KIND a) f) name)
-    where
-      listField :: DataField f -> DataField f
-      listField x =
-        x {fieldTypeWrappers = [NonNullType, ListType] ++ fieldTypeWrappers x}
-  introspect _ = introspect (Context :: Context a (KIND a) f)
+-- Object Fields
+class ObjectFields (custom :: Bool) a where
+  objectFields :: proxy1 custom -> proxy2 a -> ([(Text, DataField)], [TypeUpdater])
 
---
--- CUSTOM Types: Tuple, Map, Set
---
-instance Introspect (Pair k v) OBJECT f => Introspect (k, v) WRAPPER f where
-  __field _ = __field (Context :: Context (Pair k v) OBJECT f)
-  introspect _ = introspect (Context :: Context (Pair k v) OBJECT f)
+instance GQLRep OBJECT (Rep a) => ObjectFields 'False a where
+  objectFields _ _ = unzip $ gqlRep (Context :: Context OBJECT (Rep a))
 
-instance Introspect [a] WRAPPER f => Introspect (Set a) WRAPPER f where
-  __field _ = __field (Context :: Context [a] WRAPPER f)
-  introspect _ = introspect (Context :: Context [a] WRAPPER f)
+type family GQLRepResult (a :: GQL_KIND) :: *
 
--- | introspection Does not care about resolving monad, some fake monad just for mocking
-type MockRes = (Resolver Maybe)
+type instance GQLRepResult OBJECT = (Text, DataField)
 
-instance Introspect (MapKind k v MockRes) OBJECT f =>
-         Introspect (Map k v) WRAPPER f where
-  __field _ = __field (Context :: Context (MapKind k v MockRes) OBJECT f)
-  introspect _ = introspect (Context :: Context (MapKind k v MockRes) OBJECT f)
+type instance GQLRepResult UNION = DataField
 
--- |introspects Of Resolver 'a' as argument and 'b' as output type
-instance (ObjectRep (Rep a) (), OutputConstraint b) =>
-         Introspect (a -> Resolver m b) WRAPPER OutputType where
-  __field _ name =
-    (__field (Context :: OutputOf b) name)
-      {fieldArgs = map fst $ objectFieldTypes (Proxy @(Rep a))}
-  introspect _ typeLib =
-    resolveTypes typeLib $ map snd args ++ [introspect (Context :: OutputOf b)]
-    where
-      args :: [((Text, DataInputField), TypeUpdater)]
-      args = objectFieldTypes (Proxy @(Rep a))
+--  GENERIC UNION
+class GQLRep (kind :: GQL_KIND) f where
+  gqlRep :: Context kind f -> [(GQLRepResult kind, TypeUpdater)]
 
-instance (ObjectRep (Rep a) (), OutputConstraint b) =>
-         Introspect (a -> Either String b) WRAPPER OutputType where
-  __field _ name =
-    (__field (Context :: OutputOf b) name)
-      {fieldArgs = map fst $ objectFieldTypes (Proxy @(Rep a))}
-  introspect _ typeLib =
-    resolveTypes typeLib $ map snd args ++ [introspect (Context :: OutputOf b)]
-    where
-      args :: [((Text, DataInputField), TypeUpdater)]
-      args = objectFieldTypes (Proxy @(Rep a))
+instance GQLRep kind f => GQLRep kind (M1 D d f) where
+  gqlRep _ = gqlRep (Context :: Context kind f)
 
-instance (ObjectRep (Rep a) (), OutputConstraint b) =>
-         Introspect (a -> SubResolver m c v b) WRAPPER OutputType where
-  __field _ name =
-    (__field (Context :: OutputOf b) name)
-      {fieldArgs = map fst $ objectFieldTypes (Proxy @(Rep a))}
-  introspect _ typeLib =
-    resolveTypes typeLib $ map snd args ++ [introspect (Context :: OutputOf b)]
+instance GQLRep kind f => GQLRep kind (M1 C c f) where
+  gqlRep _ = gqlRep (Context :: Context kind f)
+
+-- | recursion for Object types, both of them : 'UNION' and 'INPUT_UNION'
+instance (GQLRep UNION a, GQLRep UNION b) => GQLRep UNION (a :+: b) where
+  gqlRep _ = gqlRep (Context :: Context UNION a) ++ gqlRep (Context :: Context UNION b)
+
+instance (GQL_TYPE a, Introspect a) => GQLRep UNION (M1 S s (Rec0 a)) where
+  gqlRep _ = [(buildField (Proxy @a) [] (__typeName (Proxy @a)), introspect (Proxy @a))]
+
+-- | recursion for Object types, both of them : 'INPUT_OBJECT' and 'OBJECT'
+instance (GQLRep OBJECT a, GQLRep OBJECT b) => GQLRep OBJECT (a :*: b) where
+  gqlRep _ = gqlRep (Context :: Context OBJECT a) ++ gqlRep (Context :: Context OBJECT b)
+
+instance (Selector s, Introspect a) => GQLRep OBJECT (M1 S s (Rec0 a)) where
+  gqlRep _ = [((name, field (Proxy @a) name), introspect (Proxy @a))]
     where
-      args :: [((Text, DataInputField), TypeUpdater)]
-      args = objectFieldTypes (Proxy @(Rep a))
+      name = pack $ selName (undefined :: M1 S s (Rec0 ()) ())
+
+instance GQLRep OBJECT U1 where
+  gqlRep _ = []
+
+buildAlias :: Text -> TypeAlias
+buildAlias aliasTyCon = TypeAlias {aliasTyCon, aliasWrappers = [], aliasArgs = Nothing}
+
+-- Helper Functions
+resolveTypes :: DataTypeLib -> [TypeUpdater] -> SchemaValidation DataTypeLib
+resolveTypes = foldM (&)
+
+buildField :: GQLType a => Proxy a -> DataArguments -> Text -> DataField
+buildField proxy fieldArgs fieldName =
+  DataField
+    {fieldName, fieldArgs, fieldArgsType = Nothing, fieldType = buildAlias $ __typeName proxy, fieldHidden = False}
+
+buildType :: GQLType a => t -> Proxy a -> DataTyCon t
+buildType typeData proxy =
+  DataTyCon
+    { typeName = __typeName proxy
+    , typeFingerprint = __typeFingerprint proxy
+    , typeDescription = description proxy
+    , typeVisibility = __typeVisibility proxy
+    , typeData
+    }
+
+updateLib :: GQLType a => (Proxy a -> DataFullType) -> [TypeUpdater] -> Proxy a -> TypeUpdater
+updateLib typeBuilder stack proxy lib' =
+  case isTypeDefined (__typeName proxy) lib' of
+    Nothing -> resolveTypes (defineType (__typeName proxy, typeBuilder proxy) lib') stack
+    Just fingerprint'
+      | fingerprint' == __typeFingerprint proxy -> return lib'
+    -- throw error if 2 different types has same name
+    Just _ -> Left $ nameCollisionError (__typeName proxy)
diff --git a/src/Data/Morpheus/Execution/Server/Resolve.hs b/src/Data/Morpheus/Execution/Server/Resolve.hs
--- a/src/Data/Morpheus/Execution/Server/Resolve.hs
+++ b/src/Data/Morpheus/Execution/Server/Resolve.hs
@@ -4,6 +4,7 @@
 {-# LANGUAGE OverloadedStrings   #-}
 {-# LANGUAGE RankNTypes          #-}
 {-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications    #-}
 
 module Data.Morpheus.Execution.Server.Resolve
   ( statelessResolver
@@ -15,6 +16,7 @@
   ) where
 
 import qualified Codec.Binary.UTF8.String                            as UTF8
+import           Control.Monad.Except                                (liftEither)
 import           Control.Monad.Trans.Except                          (ExceptT (..), runExceptT)
 import           Data.Aeson                                          (Result (..), encode, fromJSON)
 import           Data.Aeson.Parser                                   (jsonNoDup)
@@ -22,39 +24,41 @@
 import qualified Data.ByteString                                     as S
 import qualified Data.ByteString.Lazy.Char8                          as L
 import           Data.Functor.Identity                               (Identity (..))
-import           Data.Proxy
-import           GHC.Generics
+import           Data.Proxy                                          (Proxy (..))
 
 -- MORPHEUS
 import           Data.Morpheus.Error.Utils                           (badRequestError, renderErrors)
-import           Data.Morpheus.Execution.Server.Encode               (EncodeCon, EncodeMutCon, EncodeSubCon, encodeMut,
-                                                                      encodeQuery, encodeSub)
-import           Data.Morpheus.Execution.Server.Introspect           (ObjectRep (..), resolveTypes)
+import           Data.Morpheus.Execution.Server.Encode               (EncodeCon, EncodeMutCon, EncodeSubCon, OBJ_RES,
+                                                                      encodeOperation, encodeQuery)
+import           Data.Morpheus.Execution.Server.Introspect           (IntroCon, ObjectFields (..), resolveTypes)
 import           Data.Morpheus.Execution.Subscription.ClientRegister (GQLState, publishUpdates)
 import           Data.Morpheus.Parsing.Request.Parser                (parseGQL)
+import           Data.Morpheus.Schema.Schema                         (Root)
 import           Data.Morpheus.Schema.SchemaAPI                      (defaultTypes, hiddenRootFields, schemaAPI)
-import           Data.Morpheus.Types.Internal.AST.Operation          (Operation (..), OperationKind (..))
-import           Data.Morpheus.Types.Internal.Data                   (DataArguments, DataFingerprint (..),
-                                                                      DataType (..), DataTypeLib (..), initTypeLib)
+import           Data.Morpheus.Types.GQLType                         (GQLType (CUSTOM))
+import           Data.Morpheus.Types.Internal.AST.Operation          (Operation (..), ValidOperation)
+import           Data.Morpheus.Types.Internal.Data                   (DataFingerprint (..), DataTyCon (..),
+                                                                      DataTypeLib (..), OperationKind (..), initTypeLib)
 import           Data.Morpheus.Types.Internal.Stream                 (Event (..), ResponseEvent (..), ResponseStream,
                                                                       StreamState (..), StreamT (..), closeStream, mapS)
-import           Data.Morpheus.Types.Internal.Validation             (SchemaValidation)
+import           Data.Morpheus.Types.Internal.Validation             (Validation)
 import           Data.Morpheus.Types.Internal.Value                  (Value (..))
 import           Data.Morpheus.Types.IO                              (GQLRequest (..), GQLResponse (..))
-import           Data.Morpheus.Types.Resolver                        (GQLRootResolver (..))
+import           Data.Morpheus.Types.Resolver                        (GQLRootResolver (..), Resolver, ResponseT)
 import           Data.Morpheus.Validation.Internal.Utils             (VALIDATION_MODE (..))
 import           Data.Morpheus.Validation.Query.Validation           (validateRequest)
+import           Data.Typeable                                       (Typeable)
 
 type EventCon event = Eq event
 
-type IntroCon a = (Generic a, ObjectRep (Rep a) DataArguments)
-
 type RootResCon m event cont query mutation subscription
    = ( EventCon event
+     , Typeable m
       -- Introspection
      , IntroCon query
      , IntroCon mutation
      , IntroCon subscription
+     , OBJ_RES m (Root (Resolver m)) Value
      -- Resolving
      , EncodeCon m query Value
      , EncodeMutCon m event cont mutation
@@ -80,27 +84,35 @@
 statelessResolver root = fmap snd . closeStream . streamResolver root
 
 streamResolver ::
-     (Monad m, RootResCon m s cont query mut sub)
-  => GQLRootResolver m s cont query mut sub
+     (Monad m, RootResCon m event cont query mut sub)
+  => GQLRootResolver m event cont query mut sub
   -> GQLRequest
-  -> ResponseStream m s cont GQLResponse
+  -> ResponseStream m event cont GQLResponse
 streamResolver root@GQLRootResolver {queryResolver, mutationResolver, subscriptionResolver} request =
-  renderResponse <$> runExceptT (ExceptT (pure validRequest) >>= ExceptT . execOperator)
+  renderResponse <$> runExceptT (validRequest >>= execOperator)
+  ------------------------------------------------------------
   where
     renderResponse (Left errors) = Errors $ renderErrors errors
     renderResponse (Right value) = Data value
     ---------------------------------------------------------
-    validRequest = do
-      schema <- fullSchema $ Identity root
-      query <- parseGQL request >>= validateRequest schema FULL_VALIDATION
-      return (schema, query)
+    validRequest :: Monad m => ResponseT m event cont (DataTypeLib, ValidOperation)
+    validRequest =
+      liftEither $ do
+        schema <- fullSchema $ Identity root
+        query <- parseGQL request >>= validateRequest schema FULL_VALIDATION
+        Right (schema, query)
     ----------------------------------------------------------
-    execOperator (schema, operation@Operation {operationKind = QUERY}) =
-      StreamT $ StreamState [] <$> encodeQuery (schemaAPI schema) queryResolver operation
-    execOperator (_, operation@Operation {operationKind = MUTATION}) =
-      mapS Publish (encodeMut mutationResolver operation)
-    execOperator (_, operation@Operation {operationKind = SUBSCRIPTION}) =
-      StreamT $ handleActions <$> closeStream (encodeSub subscriptionResolver operation)
+    execOperator (schema, operation@Operation {operationKind = Query}) =
+      ExceptT $
+      StreamT
+        (StreamState [] <$>
+         runExceptT
+           (do schemaRes <- schemaAPI schema
+               ExceptT (encodeQuery schemaRes queryResolver operation)))
+    execOperator (_, operation@Operation {operationKind = Mutation}) =
+      ExceptT $ mapS Publish (encodeOperation mutationResolver operation)
+    execOperator (_, operation@Operation {operationKind = Subscription}) =
+      ExceptT $ StreamT $ handleActions <$> closeStream (encodeOperation subscriptionResolver operation)
       where
         handleActions (_, Left gqlError) = StreamState [] (Left gqlError)
         handleActions (channels, Right subResolver) =
@@ -125,30 +137,30 @@
 fullSchema ::
      forall proxy m s cont query mutation subscription. (IntroCon query, IntroCon mutation, IntroCon subscription)
   => proxy (GQLRootResolver m s cont query mutation subscription)
-  -> SchemaValidation DataTypeLib
+  -> Validation DataTypeLib
 fullSchema _ = querySchema >>= mutationSchema >>= subscriptionSchema
   where
     querySchema = resolveTypes (initTypeLib (operatorType (hiddenRootFields ++ fields) "Query")) (defaultTypes : types)
       where
-        (fields, types) = unzip $ objectFieldTypes (Proxy :: Proxy (Rep query))
+        (fields, types) = objectFields (Proxy @(CUSTOM query)) (Proxy @query)
     ------------------------------
     mutationSchema lib = resolveTypes (lib {mutation = maybeOperator fields "Mutation"}) types
       where
-        (fields, types) = unzip $ objectFieldTypes (Proxy :: Proxy (Rep mutation))
+        (fields, types) = objectFields (Proxy @(CUSTOM mutation)) (Proxy @mutation)
     ------------------------------
     subscriptionSchema lib = resolveTypes (lib {subscription = maybeOperator fields "Subscription"}) types
       where
-        (fields, types) = unzip $ objectFieldTypes (Proxy :: Proxy (Rep subscription))
-     -- maybeOperator :: [a] -> Text -> Maybe (Text, DataType [a])
+        (fields, types) = objectFields (Proxy @(CUSTOM subscription)) (Proxy @subscription)
+     -- maybeOperator :: [a] -> Text -> Maybe (Text, DataTyCon[a])
     maybeOperator []     = const Nothing
     maybeOperator fields = Just . operatorType fields
-    -- operatorType :: [a] -> Text -> (Text, DataType [a])
+    -- operatorType :: [a] -> Text -> (Text, DataTyCon[a])
     operatorType typeData typeName =
       ( typeName
-      , DataType
+      , DataTyCon
           { typeData
           , typeVisibility = True
           , typeName
           , typeFingerprint = SystemFingerprint typeName
-          , typeDescription = ""
+          , typeDescription = Nothing
           })
diff --git a/src/Data/Morpheus/Kind.hs b/src/Data/Morpheus/Kind.hs
--- a/src/Data/Morpheus/Kind.hs
+++ b/src/Data/Morpheus/Kind.hs
@@ -1,4 +1,5 @@
 {-# LANGUAGE DataKinds     #-}
+{-# LANGUAGE PolyKinds     #-}
 {-# LANGUAGE TypeFamilies  #-}
 {-# LANGUAGE TypeOperators #-}
 
@@ -12,6 +13,8 @@
   , INPUT_OBJECT
   , INPUT_UNION
   , GQL_KIND
+  , Context(..)
+  , VContext(..)
   ) where
 
 data GQL_KIND
@@ -22,6 +25,17 @@
   | UNION
   | INPUT_UNION
   | WRAPPER
+
+--type ObjectConstraint a =
+-- | context , like Proxy with multiple parameters
+-- * 'kind': object, scalar, enum ...
+-- * 'a': actual gql type
+data Context (kind :: GQL_KIND) a =
+  Context
+
+newtype VContext (kind :: GQL_KIND) a = VContext
+  { unVContext :: a
+  }
 
 -- | GraphQL Scalar: Int, Float, String, Boolean or any user defined custom Scalar type
 type SCALAR = 'SCALAR
diff --git a/src/Data/Morpheus/Parsing/Document/DataType.hs b/src/Data/Morpheus/Parsing/Document/DataType.hs
--- a/src/Data/Morpheus/Parsing/Document/DataType.hs
+++ b/src/Data/Morpheus/Parsing/Document/DataType.hs
@@ -11,8 +11,8 @@
 import           Data.Morpheus.Parsing.Internal.Terms    (parseAssignment, parseMaybeTuple, parseNonNull,
                                                           parseWrappedType, pipeLiteral, qualifier, setOf,
                                                           spaceAndComments, token)
-import           Data.Morpheus.Types.Internal.Data       (DataArgument, DataFullType (..), DataOutputField, Key,
-                                                          RawDataType (..))
+import           Data.Morpheus.Types.Internal.Data       (DataArgument, DataField, DataFullType (..), Key,
+                                                          RawDataType (..), toHSWrappers)
 import           Data.Text                               (Text)
 import           Text.Megaparsec                         (label, sepBy1, some, (<|>))
 import           Text.Megaparsec.Char                    (char, space1, string)
@@ -22,7 +22,7 @@
   label "Argument" $ do
     ((fieldName, _), (wrappers, fieldType)) <- parseAssignment qualifier parseWrappedType
     nonNull <- parseNonNull
-    pure $ createArgument fieldName (nonNull ++ wrappers, fieldType)
+    pure $ createArgument fieldName (toHSWrappers $ nonNull ++ wrappers, fieldType)
 
 typeDef :: Text -> Parser Text
 typeDef kind = do
@@ -44,9 +44,9 @@
       label "entry" $ do
         ((fieldName, _), (wrappers, fieldType)) <- parseAssignment qualifier parseWrappedType
         nonNull <- parseNonNull
-        return (fieldName, createField () fieldName (nonNull ++ wrappers, fieldType))
+        return (fieldName, createField [] fieldName (toHSWrappers $ nonNull ++ wrappers, fieldType))
 
-outputObjectEntries :: Parser [(Key, DataOutputField)]
+outputObjectEntries :: Parser [(Key, DataField)]
 outputObjectEntries = label "entries" $ setOf entry
   where
     fieldWithArgs =
@@ -58,7 +58,7 @@
       label "entry" $ do
         ((fieldName, fieldArgs), (wrappers, fieldType)) <- parseAssignment fieldWithArgs parseWrappedType
         nonNull <- parseNonNull
-        return (fieldName, createField fieldArgs fieldName (nonNull ++ wrappers, fieldType))
+        return (fieldName, createField fieldArgs fieldName (toHSWrappers $ nonNull ++ wrappers, fieldType))
 
 dataObject :: Parser (Text, RawDataType)
 dataObject =
diff --git a/src/Data/Morpheus/Parsing/Internal/Create.hs b/src/Data/Morpheus/Parsing/Internal/Create.hs
--- a/src/Data/Morpheus/Parsing/Internal/Create.hs
+++ b/src/Data/Morpheus/Parsing/Internal/Create.hs
@@ -11,21 +11,29 @@
   , createDataTypeLib
   ) where
 
-import           Data.Morpheus.Types.Internal.Data (DataField (..), DataFingerprint (..), DataFullType (..),
-                                                    DataLeaf (..), DataType (..), DataTypeLib (..), DataTypeWrapper,
-                                                    DataValidator (..), defineType, initTypeLib)
+import           Data.Morpheus.Types.Internal.Data (DataArguments, DataField (..), DataFingerprint (..),
+                                                    DataFullType (..), DataLeaf (..), DataTyCon (..), DataTypeLib (..),
+                                                    DataValidator (..), TypeAlias (..), WrapperD, defineType,
+                                                    initTypeLib)
 import           Data.Text                         (Text)
 
-createField :: a -> Text -> ([DataTypeWrapper], Text) -> DataField a
-createField fieldArgs fieldName (fieldTypeWrappers, fieldType) =
-  DataField {fieldArgs, fieldName, fieldType, fieldTypeWrappers, fieldHidden = False}
+createField :: DataArguments -> Text -> ([WrapperD], Text) -> DataField
+createField fieldArgs fieldName (aliasWrappers, aliasTyCon) =
+  DataField
+    { fieldArgs
+    , fieldArgsType = Nothing
+    , fieldName
+    , fieldType = TypeAlias {aliasTyCon, aliasWrappers, aliasArgs = Nothing}
+    , fieldHidden = False
+    }
 
-createArgument :: Text -> ([DataTypeWrapper], Text) -> (Text, DataField ())
-createArgument fieldName x = (fieldName, createField () fieldName x)
+createArgument :: Text -> ([WrapperD], Text) -> (Text, DataField)
+createArgument fieldName x = (fieldName, createField [] fieldName x)
 
-createType :: Text -> a -> DataType a
+createType :: Text -> a -> DataTyCon a
 createType typeName typeData =
-  DataType {typeName, typeDescription = "", typeFingerprint = SystemFingerprint "", typeVisibility = True, typeData}
+  DataTyCon
+    {typeName, typeDescription = Nothing, typeFingerprint = SystemFingerprint "", typeVisibility = True, typeData}
 
 createScalarType :: Text -> (Text, DataFullType)
 createScalarType typeName = (typeName, Leaf $ CustomScalar $ createType typeName (DataValidator pure))
@@ -36,7 +44,7 @@
 createUnionType :: Text -> [Text] -> (Text, DataFullType)
 createUnionType typeName typeData = (typeName, Union $ createType typeName $ map unionField typeData)
   where
-    unionField fieldType = createField () "" ([], fieldType)
+    unionField fieldType = createField [] "" ([], fieldType)
 
 createDataTypeLib :: Monad m => [(Text, DataFullType)] -> m DataTypeLib
 createDataTypeLib types =
diff --git a/src/Data/Morpheus/Parsing/JSONSchema/Parse.hs b/src/Data/Morpheus/Parsing/JSONSchema/Parse.hs
--- a/src/Data/Morpheus/Parsing/JSONSchema/Parse.hs
+++ b/src/Data/Morpheus/Parsing/JSONSchema/Parse.hs
@@ -1,6 +1,8 @@
-{-# LANGUAGE NamedFieldPuns    #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE TypeOperators     #-}
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE NamedFieldPuns        #-}
+{-# LANGUAGE OverloadedStrings     #-}
+{-# LANGUAGE TypeOperators         #-}
 
 module Data.Morpheus.Parsing.JSONSchema.Parse
   ( decodeIntrospection
@@ -11,63 +13,66 @@
 import           Data.Morpheus.Error.Internal            (internalError)
 import           Data.Morpheus.Parsing.Internal.Create   (createArgument, createDataTypeLib, createEnumType,
                                                           createField, createScalarType, createType, createUnionType)
-import qualified Data.Morpheus.Schema.EnumValue          as E (EnumValue (..))
-import qualified Data.Morpheus.Schema.Field              as F (Field (..))
-import qualified Data.Morpheus.Schema.InputValue         as I (InputValue (..))
-import           Data.Morpheus.Schema.JSONType           (JSONIntro (..), JSONSchema (..), JSONType (..))
+import           Data.Morpheus.Parsing.JSONSchema.Types  (EnumValue (..), Field (..), InputValue (..),
+                                                          Introspection (..), Schema (..), Type (..))
 import           Data.Morpheus.Schema.TypeKind           (TypeKind (..))
-import           Data.Morpheus.Types.Internal.Data       (DataFullType (..), DataTypeLib, DataTypeWrapper (..))
+import           Data.Morpheus.Types.Internal.Data       (DataField, DataFullType (..), DataTypeLib,
+                                                          DataTypeWrapper (..), Key, WrapperD, toHSWrappers)
 import           Data.Morpheus.Types.Internal.Validation (Validation)
 import           Data.Morpheus.Types.IO                  (JSONResponse (..))
 import           Data.Semigroup                          ((<>))
 import           Data.Text                               (Text, pack)
 
-typeFromJSON :: JSONType -> Validation (Text, DataFullType)
-typeFromJSON JSONType {name = Just typeName, kind = SCALAR} = pure $ createScalarType typeName
-typeFromJSON JSONType {name = Just typeName, kind = ENUM, enumValues = Just enums} =
-  pure $ createEnumType typeName (map E.name enums)
-typeFromJSON JSONType {name = Just typeName, kind = UNION, possibleTypes = Just unions} =
-  case traverse name unions of
-    Nothing  -> fail "ERROR: GQL ERROR"
-    Just uni -> pure $ createUnionType typeName uni
-typeFromJSON JSONType {name = Just typeName, kind = INPUT_OBJECT, inputFields = Just iFields} = do
-  fields <- traverse iField iFields
-  pure (typeName, InputObject $ createType typeName fields)
-  where
-    iField I.InputValue {I.name = fieldName, I.type' = fType} = do
-      fieldType <- fieldTypeFromJSON fType
-      pure (fieldName, createField () fieldName fieldType)
-typeFromJSON JSONType {name = Just typeName, kind = OBJECT, fields = Just oFields} = do
-  fields <- traverse oField oFields
-  pure (typeName, OutputObject $ createType typeName fields)
-  where
-    oField F.Field {F.name = fieldName, F.args = fArgs, F.type' = fType} = do
-      fieldType <- fieldTypeFromJSON fType
-      args <- traverse genArg fArgs
-      pure (fieldName, createField args fieldName fieldType)
-      where
-        genArg I.InputValue {I.name = argName, I.type' = argType} = createArgument argName <$> fieldTypeFromJSON argType
-typeFromJSON x = internalError $ "Unsuported type" <> pack (show x)
-
-fieldTypeFromJSON :: JSONType -> Validation ([DataTypeWrapper], Text)
-fieldTypeFromJSON = fieldTypeRec []
-  where
-    fieldTypeRec :: [DataTypeWrapper] -> JSONType -> Validation ([DataTypeWrapper], Text)
-    fieldTypeRec acc JSONType {kind = LIST, ofType = Just ofType} = fieldTypeRec (ListType : acc) ofType
-    fieldTypeRec acc JSONType {kind = NON_NULL, ofType = Just ofType} = fieldTypeRec (NonNullType : acc) ofType
-    fieldTypeRec acc JSONType {name = Just name} = pure (acc, name)
-    fieldTypeRec _ x = internalError $ "Unsuported Field" <> pack (show x)
-
-schemaFromJSON :: [JSONType] -> Validation [(Text, DataFullType)]
-schemaFromJSON = traverse typeFromJSON
-
 decodeIntrospection :: ByteString -> Validation DataTypeLib
 decodeIntrospection jsonDoc =
   case jsonSchema of
     Left errors -> internalError $ pack errors
-    Right JSONResponse {responseData = Just JSONIntro {__schema = JSONSchema {types}}} ->
-      schemaFromJSON types >>= createDataTypeLib
+    Right JSONResponse {responseData = Just Introspection {__schema = Schema {types}}} ->
+      traverse parse types >>= createDataTypeLib
     Right res -> fail $ show res
   where
-    jsonSchema :: Either String (JSONResponse JSONIntro)
+    jsonSchema :: Either String (JSONResponse Introspection)
     jsonSchema = eitherDecode jsonDoc
+
+class ParseJSONSchema a b where
+  parse :: a -> Validation (Key, b)
+
+instance ParseJSONSchema Type DataFullType where
+  parse Type {name = Just typeName, kind = SCALAR} = pure $ createScalarType typeName
+  parse Type {name = Just typeName, kind = ENUM, enumValues = Just enums} =
+    pure $ createEnumType typeName (map enumName enums)
+  parse Type {name = Just typeName, kind = UNION, possibleTypes = Just unions} =
+    case traverse name unions of
+      Nothing  -> fail "ERROR: GQL ERROR"
+      Just uni -> pure $ createUnionType typeName uni
+  parse Type {name = Just typeName, kind = INPUT_OBJECT, inputFields = Just iFields} = do
+    fields <- traverse parse iFields
+    pure (typeName, InputObject $ createType typeName fields)
+  parse Type {name = Just typeName, kind = OBJECT, fields = Just oFields} = do
+    fields <- traverse parse oFields
+    pure (typeName, OutputObject $ createType typeName fields)
+  parse x = internalError $ "Unsuported type" <> pack (show x)
+
+instance ParseJSONSchema Field DataField where
+  parse Field {fieldName, fieldArgs, fieldType} = do
+    fType <- fieldTypeFromJSON fieldType
+    args <- traverse genArg fieldArgs
+    pure (fieldName, createField args fieldName fType)
+    where
+      genArg InputValue {inputName = argName, inputType = argType} =
+        createArgument argName <$> fieldTypeFromJSON argType
+
+instance ParseJSONSchema InputValue DataField where
+  parse InputValue {inputName, inputType} = do
+    fieldType <- fieldTypeFromJSON inputType
+    pure (inputName, createField [] inputName fieldType)
+
+fieldTypeFromJSON :: Type -> Validation ([WrapperD], Text)
+fieldTypeFromJSON = fmap toHs . fieldTypeRec []
+  where
+    toHs (w, t) = (toHSWrappers w, t)
+    fieldTypeRec :: [DataTypeWrapper] -> Type -> Validation ([DataTypeWrapper], Text)
+    fieldTypeRec acc Type {kind = LIST, ofType = Just ofType} = fieldTypeRec (ListType : acc) ofType
+    fieldTypeRec acc Type {kind = NON_NULL, ofType = Just ofType} = fieldTypeRec (NonNullType : acc) ofType
+    fieldTypeRec acc Type {name = Just name} = pure (acc, name)
+    fieldTypeRec _ x = internalError $ "Unsuported Field" <> pack (show x)
diff --git a/src/Data/Morpheus/Parsing/JSONSchema/Types.hs b/src/Data/Morpheus/Parsing/JSONSchema/Types.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Morpheus/Parsing/JSONSchema/Types.hs
@@ -0,0 +1,77 @@
+{-# LANGUAGE DeriveAnyClass    #-}
+{-# LANGUAGE DeriveGeneric     #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE TypeFamilies      #-}
+{-# LANGUAGE TypeOperators     #-}
+
+module Data.Morpheus.Parsing.JSONSchema.Types
+  ( Introspection(..)
+  , Schema(..)
+  , Type(..)
+  , Field(..)
+  , InputValue(..)
+  , EnumValue(..)
+  ) where
+
+import           Data.Aeson
+import           Data.Text                     (Text)
+import           GHC.Generics                  (Generic)
+
+--
+-- MORPHEUS
+import           Data.Morpheus.Schema.TypeKind (TypeKind)
+
+-- TYPES FOR DECODING JSON INTROSPECTION
+--
+newtype Introspection = Introspection
+  { __schema :: Schema
+  } deriving (Generic, Show, FromJSON)
+
+newtype Schema = Schema
+  { types :: [Type]
+  } deriving (Generic, Show, FromJSON)
+
+-- TYPE
+data Type = Type
+  { kind          :: TypeKind
+  , name          :: Maybe Text
+  , fields        :: Maybe [Field]
+  , interfaces    :: Maybe [Type]
+  , possibleTypes :: Maybe [Type]
+  , enumValues    :: Maybe [EnumValue]
+  , inputFields   :: Maybe [InputValue]
+  , ofType        :: Maybe Type
+  } deriving (Generic, Show, FromJSON)
+
+-- FIELD
+data Field = Field
+  { fieldName :: Text
+  , fieldArgs :: [InputValue]
+  , fieldType :: Type
+  } deriving (Show, Generic)
+
+instance FromJSON Field where
+  parseJSON = withObject "Field" objectParser
+    where
+      objectParser o = Field <$> o .: "name" <*> o .: "args" <*> o .: "type"
+
+-- INPUT
+data InputValue = InputValue
+  { inputName :: Text
+  , inputType :: Type
+  } deriving (Show, Generic)
+
+instance FromJSON InputValue where
+  parseJSON = withObject "InputValue" objectParser
+    where
+      objectParser o = InputValue <$> o .: "name" <*> o .: "type"
+
+-- ENUM
+newtype EnumValue = EnumValue
+  { enumName :: Text
+  } deriving (Generic, Show)
+
+instance FromJSON EnumValue where
+  parseJSON = withObject "EnumValue" objectParser
+    where
+      objectParser o = EnumValue <$> o .: "name"
diff --git a/src/Data/Morpheus/Parsing/Request/Operation.hs b/src/Data/Morpheus/Parsing/Request/Operation.hs
--- a/src/Data/Morpheus/Parsing/Request/Operation.hs
+++ b/src/Data/Morpheus/Parsing/Request/Operation.hs
@@ -17,8 +17,8 @@
 import           Data.Morpheus.Parsing.Internal.Terms       (parseAssignment, parseMaybeTuple, parseNonNull,
                                                              parseWrappedType, spaceAndComments1, token, variable)
 import           Data.Morpheus.Parsing.Request.Body         (entries)
-import           Data.Morpheus.Types.Internal.AST.Operation (Operation (..), OperationKind (..), RawOperation,
-                                                             Variable (..))
+import           Data.Morpheus.Types.Internal.AST.Operation (Operation (..), RawOperation, Variable (..))
+import           Data.Morpheus.Types.Internal.Data          (OperationKind (..), toHSWrappers)
 
 operationArgument :: Parser (Text, Variable ())
 operationArgument =
@@ -30,7 +30,7 @@
       , Variable
           { variableType
           , isVariableRequired = 0 < length nonNull
-          , variableTypeWrappers = nonNull ++ wrappers
+          , variableTypeWrappers = toHSWrappers $ nonNull ++ wrappers
           , variablePosition
           , variableValue = ()
           })
@@ -53,7 +53,7 @@
     pure
       (Operation
          { operationName = "AnonymousQuery"
-         , operationKind = QUERY
+         , operationKind = Query
          , operationArgs = []
          , operationSelection
          , operationPosition
@@ -63,6 +63,6 @@
 parseOperationKind :: Parser OperationKind
 parseOperationKind =
   label "operatorKind" $ do
-    kind <- (string "query" $> QUERY) <|> (string "mutation" $> MUTATION) <|> (string "subscription" $> SUBSCRIPTION)
+    kind <- (string "query" $> Query) <|> (string "mutation" $> Mutation) <|> (string "subscription" $> Subscription)
     spaceAndComments1
     return kind
diff --git a/src/Data/Morpheus/Rendering/GQL.hs b/src/Data/Morpheus/Rendering/GQL.hs
deleted file mode 100644
--- a/src/Data/Morpheus/Rendering/GQL.hs
+++ /dev/null
@@ -1,78 +0,0 @@
-{-# LANGUAGE FlexibleContexts  #-}
-{-# LANGUAGE NamedFieldPuns    #-}
-{-# LANGUAGE OverloadedStrings #-}
-
-module Data.Morpheus.Rendering.GQL
-  ( renderGraphQLDocument
-  ) where
-
-import           Data.ByteString.Lazy.Char8        (ByteString)
-import           Data.Semigroup                    ((<>))
-import           Data.Text                         (Text, intercalate)
-import qualified Data.Text.Lazy                    as LT (fromStrict)
-import           Data.Text.Lazy.Encoding           (encodeUtf8)
-
--- MORPHEUS
-import           Data.Morpheus.Types.Internal.Data (DataArgument, DataField (..), DataFullType (..), DataLeaf (..),
-                                                    DataType (..), DataTypeLib, allDataTypes, showWrappedType)
-
-renderGraphQLDocument :: DataTypeLib -> ByteString
-renderGraphQLDocument lib =
-  encodeUtf8 $ LT.fromStrict $ intercalate "\n\n" $ map renderType visibleTypes
-  where
-    visibleTypes = filter (isVisible . snd) (allDataTypes lib)
-
-isVisible :: DataFullType -> Bool
-isVisible (Leaf (BaseScalar DataType {typeVisibility}))   = typeVisibility
-isVisible (Leaf (CustomScalar DataType {typeVisibility})) = typeVisibility
-isVisible (Leaf (LeafEnum DataType {typeVisibility}))     = typeVisibility
-isVisible (Union DataType {typeVisibility})               = typeVisibility
-isVisible (InputObject DataType {typeVisibility})         = typeVisibility
-isVisible (InputUnion DataType {typeVisibility})          = typeVisibility
-isVisible (OutputObject DataType {typeVisibility})        = typeVisibility
-
-renderIndent :: Text
-renderIndent = "  "
-
-renderType :: (Text, DataFullType) -> Text
-renderType (name, Leaf (BaseScalar _)) = "scalar " <> name
-renderType (name, Leaf (CustomScalar _)) = "scalar " <> name
-renderType (name, Leaf (LeafEnum DataType {typeData})) =
-  "enum " <> name <> renderObject id typeData
-renderType (name, Union DataType {typeData}) =
-  "union " <> name <> " =\n    " <>
-  intercalate ("\n" <> renderIndent <> "| ") (map fieldType typeData)
-renderType (name, InputObject DataType {typeData}) =
-  "input " <> name <> renderDataObject renderInputField typeData
-renderType (name, InputUnion DataType {typeData}) =
-  "input " <> name <> renderDataObject renderInputField (mapKeys typeData)
-renderType (name, OutputObject DataType {typeData}) =
-  "type " <> name <> renderDataObject renderField typeData
-
-mapKeys :: [DataField a] -> [(Text, DataField a)]
-mapKeys = map (\x -> (fieldName x, x))
-
-renderObject :: (a -> Text) -> [a] -> Text
-renderObject f list =
-  " { \n  " <> intercalate ("\n" <> renderIndent) (map f list) <> "\n}"
-
-renderDataObject ::
-     ((Text, DataField a) -> Text) -> [(Text, DataField a)] -> Text
-renderDataObject f list = renderObject f (ignoreHidden list)
-  where
-    ignoreHidden :: [(Text, DataField a)] -> [(Text, DataField a)]
-    ignoreHidden = filter (not . fieldHidden . snd)
-
-renderInputField :: (Text, DataField ()) -> Text
-renderInputField (key, DataField {fieldTypeWrappers, fieldType}) =
-  key <> ": " <> showWrappedType fieldTypeWrappers fieldType
-
-renderField :: (Text, DataField [(Text, DataArgument)]) -> Text
-renderField (key, DataField {fieldTypeWrappers, fieldType, fieldArgs}) =
-  key <> renderArguments fieldArgs <> ": " <>
-  showWrappedType fieldTypeWrappers fieldType
-  where
-    renderArguments :: [(Text, DataArgument)] -> Text
-    renderArguments [] = ""
-    renderArguments list =
-      "(" <> intercalate ", " (map renderInputField list) <> ")"
diff --git a/src/Data/Morpheus/Rendering/Haskell/RenderHS.hs b/src/Data/Morpheus/Rendering/Haskell/RenderHS.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Morpheus/Rendering/Haskell/RenderHS.hs
@@ -0,0 +1,35 @@
+{-# LANGUAGE DefaultSignatures    #-}
+{-# LANGUAGE NamedFieldPuns       #-}
+{-# LANGUAGE OverloadedStrings    #-}
+{-# LANGUAGE TypeSynonymInstances #-}
+
+module Data.Morpheus.Rendering.Haskell.RenderHS
+  ( RenderHS(..)
+  ) where
+
+import           Data.Semigroup                    ((<>))
+
+-- MORPHEUS
+import           Data.Morpheus.Types.Internal.Data
+
+class RenderHS a where
+  render :: a -> Key
+  renderWrapped :: a -> [WrapperD] -> Key
+  default renderWrapped :: a -> [WrapperD] -> Key
+  renderWrapped x wrappers = showGQLWrapper (toGQLWrapper wrappers)
+    where
+      showGQLWrapper []               = render x
+      showGQLWrapper (ListType:xs)    = "[" <> showGQLWrapper xs <> "]"
+      showGQLWrapper (NonNullType:xs) = showGQLWrapper xs <> "!"
+
+instance RenderHS Key where
+  render = id
+
+instance RenderHS TypeAlias where
+  render TypeAlias {aliasTyCon, aliasWrappers} = renderWrapped aliasTyCon aliasWrappers
+
+instance RenderHS DataKind where
+  render (ScalarKind x) = typeName x
+  render (EnumKind x)   = typeName x
+  render (ObjectKind x) = typeName x
+  render (UnionKind x)  = typeName x
diff --git a/src/Data/Morpheus/Rendering/Haskell/Terms.hs b/src/Data/Morpheus/Rendering/Haskell/Terms.hs
--- a/src/Data/Morpheus/Rendering/Haskell/Terms.hs
+++ b/src/Data/Morpheus/Rendering/Haskell/Terms.hs
@@ -22,7 +22,7 @@
 import           Data.Text                         (Text, intercalate, toUpper)
 
 -- MORPHEUS
-import           Data.Morpheus.Types.Internal.Data (DataTypeWrapper (..))
+import           Data.Morpheus.Types.Internal.Data (WrapperD (..))
 
 indent :: Text
 indent = "  "
@@ -49,8 +49,7 @@
 renderTuple typeName = "(" <> typeName <> ")"
 
 renderSet :: [Text] -> Text
-renderSet fields =
-  bracket "{ " <> intercalate ("\n  ," <> indent) fields <> bracket "}\n"
+renderSet fields = bracket "{ " <> intercalate ("\n  ," <> indent) fields <> bracket "}\n"
   where
     bracket x = "\n    " <> x
 
@@ -60,12 +59,10 @@
 renderExtension :: Text -> Text
 renderExtension name = "{-# LANGUAGE " <> name <> " #-}\n"
 
-renderWrapped :: [DataTypeWrapper] -> Text -> Text
-renderWrapped []                          = renderMaybe . strToText
-renderWrapped [NonNullType]               = strToText
-renderWrapped (NonNullType:(ListType:xs)) = renderList . renderWrapped xs
-renderWrapped (ListType:xs)               = renderMaybe . renderList . renderWrapped xs
-renderWrapped (NonNullType:xs)            = renderWrapped xs
+renderWrapped :: [WrapperD] -> Text -> Text
+renderWrapped (ListD:xs)  = renderList . renderWrapped xs
+renderWrapped (MaybeD:xs) = renderMaybe . renderWrapped xs
+renderWrapped []          = strToText
 
 strToText :: Text -> Text
 strToText "String" = "Text"
@@ -79,11 +76,10 @@
   | Subscription
   | Query
 
-data Context =
-  Context
-    { moduleName :: Text
-    , imports    :: [(Text, [Text])]
-    , extensions :: [Text]
-    , scope      :: Scope
-    , pubSub     :: (Text, Text)
-    }
+data Context = Context
+  { moduleName :: Text
+  , imports    :: [(Text, [Text])]
+  , extensions :: [Text]
+  , scope      :: Scope
+  , pubSub     :: (Text, Text)
+  }
diff --git a/src/Data/Morpheus/Rendering/Haskell/Types.hs b/src/Data/Morpheus/Rendering/Haskell/Types.hs
--- a/src/Data/Morpheus/Rendering/Haskell/Types.hs
+++ b/src/Data/Morpheus/Rendering/Haskell/Types.hs
@@ -15,62 +15,43 @@
                                                         renderData, renderSet, renderTuple, renderUnionCon,
                                                         renderWrapped)
 import           Data.Morpheus.Types.Internal.Data     (DataArgument, DataField (..), DataFullType (..), DataLeaf (..),
-                                                        DataType (..), DataTypeWrapper (..))
+                                                        DataTyCon (..), TypeAlias (..), isNullable)
 
 renderType :: Context -> (Text, DataFullType) -> Text
-renderType context (name, dataType) =
-  typeIntro <> renderData name <> renderT dataType
+renderType context (name, dataType) = typeIntro <> renderData name <> renderT dataType
   where
-    renderT (Leaf (BaseScalar _)) =
-      renderCon name <> "Int Int" <> defineTypeClass "SCALAR" <>
-      renderGQLScalar name
-    renderT (Leaf (CustomScalar _)) =
-      renderCon name <> "Int Int" <> defineTypeClass "SCALAR" <>
-      renderGQLScalar name
-    renderT (Leaf (LeafEnum DataType {typeData})) =
-      unionType typeData <> defineTypeClass "ENUM"
-    renderT (Union DataType {typeData}) =
-      renderUnion name typeData <> defineTypeClass "UNION"
-    renderT (InputObject DataType {typeData}) =
-      renderCon name <> renderObject renderInputField typeData <>
-      defineTypeClass "INPUT_OBJECT"
+    renderT (Leaf (BaseScalar _)) = renderCon name <> "Int Int" <> defineTypeClass "SCALAR" <> renderGQLScalar name
+    renderT (Leaf (CustomScalar _)) = renderCon name <> "Int Int" <> defineTypeClass "SCALAR" <> renderGQLScalar name
+    renderT (Leaf (LeafEnum DataTyCon {typeData})) = unionType typeData <> defineTypeClass "ENUM"
+    renderT (Union DataTyCon {typeData}) = renderUnion name typeData <> defineTypeClass "UNION"
+    renderT (InputObject DataTyCon {typeData}) =
+      renderCon name <> renderObject renderInputField typeData <> defineTypeClass "INPUT_OBJECT"
     renderT (InputUnion _) = "\n -- Error: Input Union Not Supported"
-    renderT (OutputObject DataType {typeData}) =
-      renderCon name <> renderObject (renderField context) typeData <>
-      defineTypeClass "OBJECT"
+    renderT (OutputObject DataTyCon {typeData}) =
+      renderCon name <> renderObject (renderField context) typeData <> defineTypeClass "OBJECT"
     ----------------------------------------------------------------------------------------------------------
     typeIntro = "\n\n---- GQL " <> name <> " ------------------------------- \n"
     ----------------------------------------------------------------------------------------------------------
     defineTypeClass kind =
-      "\n\n" <> renderTypeInstanceHead "GQLType" name <> indent <> "type KIND " <>
-      name <>
-      " = " <>
-      kind <>
-      "\n\n"
+      "\n\n" <> renderTypeInstanceHead "GQLType" name <> indent <> "type KIND " <> name <> " = " <> kind <> "\n\n"
     ----------------------------------------------------------------------------------------------------------
 
 renderTypeInstanceHead :: Text -> Text -> Text
-renderTypeInstanceHead className name =
-  "instance " <> className <> " " <> name <> " where\n"
+renderTypeInstanceHead className name = "instance " <> className <> " " <> name <> " where\n"
 
 renderGQLScalar :: Text -> Text
-renderGQLScalar name =
-  renderTypeInstanceHead "GQLScalar " name <> renderParse <> renderSerialize <>
-  "\n\n"
+renderGQLScalar name = renderTypeInstanceHead "GQLScalar " name <> renderParse <> renderSerialize <> "\n\n"
   where
     renderParse = indent <> "parseValue _ = pure (" <> name <> " 0 0 )" <> "\n"
     renderSerialize = indent <> "serialize (" <> name <> " x y ) = Int (x + y)"
 
-renderUnion :: Text -> [DataField ()] -> Text
+renderUnion :: Text -> [DataField] -> Text
 renderUnion typeName = unionType . map renderElem
   where
-    renderElem DataField {fieldType} =
-      renderUnionCon typeName fieldType <> fieldType
+    renderElem DataField {fieldType = TypeAlias {aliasTyCon}} = renderUnionCon typeName aliasTyCon <> aliasTyCon
 
 unionType :: [Text] -> Text
-unionType ls =
-  "\n" <> indent <> intercalate ("\n" <> indent <> "| ") ls <>
-  " deriving (Generic)"
+unionType ls = "\n" <> indent <> intercalate ("\n" <> indent <> "| ") ls <> " deriving (Generic)"
 
 renderObject :: (a -> (Text, Maybe Text)) -> [a] -> Text
 renderObject f list = intercalate "\n\n" $ renderMainType : catMaybes types
@@ -78,19 +59,17 @@
     renderMainType = renderSet fields <> " deriving (Generic)"
     (fields, types) = unzip (map f list)
 
-renderInputField :: (Text, DataField ()) -> (Text, Maybe Text)
-renderInputField (key, DataField {fieldTypeWrappers, fieldType}) =
-  (key `renderAssignment` renderWrapped fieldTypeWrappers fieldType, Nothing)
+renderInputField :: (Text, DataField) -> (Text, Maybe Text)
+renderInputField (key, DataField {fieldType = TypeAlias {aliasTyCon, aliasWrappers}}) =
+  (key `renderAssignment` renderWrapped aliasWrappers aliasTyCon, Nothing)
 
-renderField ::
-     Context -> (Text, DataField [(Text, DataArgument)]) -> (Text, Maybe Text)
-renderField Context {scope, pubSub = (channel, content)} (key, DataField { fieldTypeWrappers
-                                                                         , fieldType
+renderField :: Context -> (Text, DataField) -> (Text, Maybe Text)
+renderField Context {scope, pubSub = (channel, content)} (key, DataField { fieldType = TypeAlias { aliasWrappers
+                                                                                                 , aliasTyCon
+                                                                                                 }
                                                                          , fieldArgs
                                                                          }) =
-  ( key `renderAssignment` argTypeName <> " -> " <> renderMonad scope <>
-    result fieldTypeWrappers
-  , argTypes)
+  (key `renderAssignment` argTypeName <> " -> " <> renderMonad scope <> result aliasWrappers, argTypes)
   where
     renderMonad Subscription = "IOSubRes " <> channel <> " " <> content <> " "
     renderMonad Mutation =
@@ -99,16 +78,15 @@
         _    -> "IOMutRes " <> channel <> " " <> content <> " "
     renderMonad _ = "IORes "
     -----------------------------------------------------------------
-    result wrappers@(NonNullType:_) = renderWrapped wrappers fieldType
-    result wrappers                 = renderTuple (renderWrapped wrappers fieldType)
+    result wrappers
+      | isNullable wrappers = renderTuple (renderWrapped wrappers aliasTyCon)
+      | otherwise = renderWrapped wrappers aliasTyCon
     (argTypeName, argTypes) = renderArguments fieldArgs
     renderArguments :: [(Text, DataArgument)] -> (Text, Maybe Text)
     renderArguments [] = ("()", Nothing)
     renderArguments list =
       ( fieldArgTypeName
-      , Just
-          (renderData fieldArgTypeName <> renderCon fieldArgTypeName <>
-           renderObject renderInputField list))
+      , Just (renderData fieldArgTypeName <> renderCon fieldArgTypeName <> renderObject renderInputField list))
       where
         fieldArgTypeName = "Arg" <> camelCase key
         camelCase :: Text -> Text
diff --git a/src/Data/Morpheus/Rendering/Haskell/Values.hs b/src/Data/Morpheus/Rendering/Haskell/Values.hs
--- a/src/Data/Morpheus/Rendering/Haskell/Values.hs
+++ b/src/Data/Morpheus/Rendering/Haskell/Values.hs
@@ -13,22 +13,16 @@
 -- MORPHEUS
 import           Data.Morpheus.Rendering.Haskell.Terms (Context (..), Scope (..), renderAssignment, renderCon,
                                                         renderEqual, renderReturn, renderSet, renderUnionCon)
-import           Data.Morpheus.Types.Internal.Data     (DataField (..), DataFullType (..), DataLeaf (..), DataType (..),
-                                                        DataTypeLib (..), DataTypeWrapper (..))
+import           Data.Morpheus.Types.Internal.Data     (DataField (..), DataFullType (..), DataLeaf (..),
+                                                        DataTyCon (..), DataTypeLib (..), TypeAlias (..), WrapperD (..))
 
 renderRootResolver :: Context -> DataTypeLib -> Text
-renderRootResolver _ DataTypeLib {mutation, subscription} =
-  renderSignature <> renderBody <> "\n\n"
+renderRootResolver _ DataTypeLib {mutation, subscription} = renderSignature <> renderBody <> "\n\n"
   where
-    renderSignature =
-      "rootResolver :: " <> renderRootSig (fst <$> subscription) <> "\n"
+    renderSignature = "rootResolver :: " <> renderRootSig (fst <$> subscription) <> "\n"
       where
-        renderRootSig (Just sub) =
-          "GQLRootResolver IO Channel Content Query " <> maybeOperator mutation <>
-          " " <>
-          sub
-        renderRootSig Nothing =
-          "GQLRootResolver IO () () Query " <> maybeOperator mutation <> " ()"
+        renderRootSig (Just sub) = "GQLRootResolver IO Channel Content Query " <> maybeOperator mutation <> " " <> sub
+        renderRootSig Nothing    = "GQLRootResolver IO () () Query " <> maybeOperator mutation <> " ()"
         ----------------------
         maybeOperator (Just (name, _)) = name
         maybeOperator Nothing          = "()"
@@ -44,60 +38,43 @@
         maybeRes Nothing          = "return ()"
 
 renderResolver :: Context -> (Text, DataFullType) -> Text
-renderResolver Context {scope, pubSub = (channel, content)} (name, dataType) =
-  renderSig dataType
+renderResolver Context {scope, pubSub = (channel, content)} (name, dataType) = renderSig dataType
   where
-    renderSig (Leaf BaseScalar {}) =
-      defFunc <> renderReturn <> "$ " <> renderCon name <> "0 0"
-    renderSig (Leaf CustomScalar {}) =
-      defFunc <> renderReturn <> "$ " <> renderCon name <> "0 0"
-    renderSig (Leaf (LeafEnum DataType {typeData})) =
-      defFunc <> renderReturn <> renderCon (head typeData)
-    renderSig (Union DataType {typeData}) =
-      defFunc <> renderUnionCon name typeCon <> " <$> " <> "resolve" <> typeCon
+    renderSig (Leaf BaseScalar {}) = defFunc <> renderReturn <> "$ " <> renderCon name <> "0 0"
+    renderSig (Leaf CustomScalar {}) = defFunc <> renderReturn <> "$ " <> renderCon name <> "0 0"
+    renderSig (Leaf (LeafEnum DataTyCon {typeData})) = defFunc <> renderReturn <> renderCon (head typeData)
+    renderSig (Union DataTyCon {typeData}) = defFunc <> renderUnionCon name typeCon <> " <$> " <> "resolve" <> typeCon
       where
-        typeCon = fieldType $ head typeData
-    renderSig (OutputObject DataType {typeData}) =
-      defFunc <> renderReturn <> renderCon name <> renderObjFields
+        typeCon = aliasTyCon $ fieldType $ head typeData
+    renderSig (OutputObject DataTyCon {typeData}) = defFunc <> renderReturn <> renderCon name <> renderObjFields
       where
         renderObjFields = renderResObject (map renderFieldRes typeData)
-        renderFieldRes (key, DataField {fieldType, fieldTypeWrappers}) =
-          ( key
-          , "const " <>
-            withScope scope (renderValue fieldTypeWrappers fieldType))
+        renderFieldRes (key, DataField {fieldType = TypeAlias {aliasWrappers, aliasTyCon}}) =
+          (key, "const " <> withScope scope (renderValue aliasWrappers aliasTyCon))
           where
-            renderValue [] = const $ "$ " <> renderReturn <> "Nothing"
-            renderValue [NonNullType] = fieldValue
-            renderValue (ListType:_) = const $ "$ " <> renderReturn <> "Just []"
-            renderValue (NonNullType:(ListType:_)) =
-              const $ "$ " <> renderReturn <> "[]"
-            renderValue (NonNullType:(NonNullType:xs)) =
-              renderValue (NonNullType : xs)
+            renderValue (MaybeD:_) = const $ "$ " <> renderReturn <> "Nothing"
+            renderValue (ListD:_)  = const $ "$ " <> renderReturn <> "[]"
+            renderValue []         = fieldValue
             ----------------------------------------------------------------------------
             fieldValue "String" = "$ return \"\""
             fieldValue "Int"    = "$ return 0"
             fieldValue fName    = "resolve" <> fName
             -------------------------------------------
-            withScope Subscription x =
-              "$ Event { channels = [Channel], content = const " <> x <> " }"
+            withScope Subscription x = "$ Event { channels = [Channel], content = const " <> x <> " }"
             withScope Mutation x =
               case (channel, content) of
                 ("()", "()") -> x
-                _ ->
-                  "$ toMutResolver [Event {channels = [Channel], content = Content}] " <>
-                  x
+                _            -> "$ toMutResolver [Event {channels = [Channel], content = Content}] " <> x
             withScope _ x = x
     renderSig _ = "" -- INPUT Types Does not Need Resolvers
     --------------------------------
     defFunc = renderSignature <> renderFunc
     ----------------------------------------------------------------------------------------------------------
-    renderSignature =
-      renderAssignment ("resolve" <> name) (renderMonad name) <> "\n"
+    renderSignature = renderAssignment ("resolve" <> name) (renderMonad name) <> "\n"
     ---------------------------------------------------------------------------------
-    renderMonad "Mutation" =
-      "IOMutRes " <> channel <> " " <> content <> " Mutation"
+    renderMonad "Mutation"     = "IOMutRes " <> channel <> " " <> content <> " Mutation"
     renderMonad "Subscription" = "SubRootRes IO " <> channel <> " Subscription"
-    renderMonad tName = "IORes " <> tName
+    renderMonad tName          = "IORes " <> tName
     ----------------------------------------------------------------------------------------------------------
     renderFunc = "resolve" <> name <> " = "
     ---------------------------------------
diff --git a/src/Data/Morpheus/Rendering/RenderGQL.hs b/src/Data/Morpheus/Rendering/RenderGQL.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Morpheus/Rendering/RenderGQL.hs
@@ -0,0 +1,81 @@
+{-# LANGUAGE DefaultSignatures    #-}
+{-# LANGUAGE FlexibleInstances    #-}
+{-# LANGUAGE NamedFieldPuns       #-}
+{-# LANGUAGE OverloadedStrings    #-}
+{-# LANGUAGE TypeSynonymInstances #-}
+
+module Data.Morpheus.Rendering.RenderGQL
+  ( RenderGQL(..)
+  , renderGraphQLDocument
+  ) where
+
+import           Data.ByteString.Lazy.Char8        (ByteString)
+import           Data.Semigroup                    ((<>))
+import           Data.Text                         (Text, intercalate)
+import qualified Data.Text.Lazy                    as LT (fromStrict)
+import           Data.Text.Lazy.Encoding           (encodeUtf8)
+
+-- MORPHEUS
+import           Data.Morpheus.Types.Internal.Data (DataField (..), DataFullType (..), DataKind (..), DataLeaf (..),
+                                                    DataTyCon (..), DataTypeLib, DataTypeWrapper (..), Key,
+                                                    TypeAlias (..), WrapperD (..), allDataTypes, isVisible,
+                                                    toGQLWrapper)
+
+renderGraphQLDocument :: DataTypeLib -> ByteString
+renderGraphQLDocument lib = encodeUtf8 $ LT.fromStrict $ intercalate "\n\n" $ map render visibleTypes
+  where
+    visibleTypes = filter (isVisible . snd) (allDataTypes lib)
+
+class RenderGQL a where
+  render :: a -> Key
+  renderWrapped :: a -> [WrapperD] -> Key
+  default renderWrapped :: a -> [WrapperD] -> Key
+  renderWrapped x wrappers = showGQLWrapper (toGQLWrapper wrappers)
+    where
+      showGQLWrapper []               = render x
+      showGQLWrapper (ListType:xs)    = "[" <> showGQLWrapper xs <> "]"
+      showGQLWrapper (NonNullType:xs) = showGQLWrapper xs <> "!"
+
+instance RenderGQL Key where
+  render = id
+
+instance RenderGQL TypeAlias where
+  render TypeAlias {aliasTyCon, aliasWrappers} = renderWrapped aliasTyCon aliasWrappers
+
+instance RenderGQL DataKind where
+  render (ScalarKind x) = typeName x
+  render (EnumKind x)   = typeName x
+  render (ObjectKind x) = typeName x
+  render (UnionKind x)  = typeName x
+
+instance RenderGQL (Key, DataFullType) where
+  render (name, Leaf (BaseScalar _)) = "scalar " <> name
+  render (name, Leaf (CustomScalar _)) = "scalar " <> name
+  render (name, Leaf (LeafEnum DataTyCon {typeData})) = "enum " <> name <> renderObject id typeData
+  render (name, Union DataTyCon {typeData}) =
+    "union " <> name <> " =\n    " <> intercalate ("\n" <> renderIndent <> "| ") (map (render . fieldType) typeData)
+  render (name, InputObject DataTyCon {typeData}) = "input " <> name <> render typeData
+  render (name, InputUnion DataTyCon {typeData}) = "input " <> name <> render (mapKeys typeData)
+  render (name, OutputObject DataTyCon {typeData}) = "type " <> name <> render typeData
+
+-- OBJECT
+instance RenderGQL [(Text, DataField)] where
+  render = renderObject renderField . ignoreHidden
+    where
+      renderField :: (Text, DataField) -> Text
+      renderField (key, DataField {fieldType, fieldArgs}) = key <> renderArgs fieldArgs <> ": " <> render fieldType
+        where
+          renderArgs []   = ""
+          renderArgs list = "(" <> intercalate ", " (map renderField list) <> ")"
+      -----------------------------------------------------------
+      ignoreHidden :: [(Text, DataField)] -> [(Text, DataField)]
+      ignoreHidden = filter (not . fieldHidden . snd)
+
+renderIndent :: Text
+renderIndent = "  "
+
+mapKeys :: [DataField] -> [(Text, DataField)]
+mapKeys = map (\x -> (fieldName x, x))
+
+renderObject :: (a -> Text) -> [a] -> Text
+renderObject f list = " { \n  " <> intercalate ("\n" <> renderIndent) (map f list) <> "\n}"
diff --git a/src/Data/Morpheus/Rendering/RenderIntrospection.hs b/src/Data/Morpheus/Rendering/RenderIntrospection.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Morpheus/Rendering/RenderIntrospection.hs
@@ -0,0 +1,209 @@
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE NamedFieldPuns        #-}
+{-# LANGUAGE OverloadedStrings     #-}
+{-# LANGUAGE TypeOperators         #-}
+
+module Data.Morpheus.Rendering.RenderIntrospection
+  ( render
+  , createObjectType
+  ) where
+
+import           Data.Semigroup                     ((<>))
+import           Data.Text                          (Text, unpack)
+
+import           Data.Morpheus.Schema.Schema
+
+-- Morpheus
+import           Data.Morpheus.Schema.TypeKind      (TypeKind (..))
+import           Data.Morpheus.Types.Internal.Data  (DataField (..), DataField, DataFullType (..), DataLeaf (..),
+                                                     DataObject, DataTyCon (..), DataTypeKind (..), DataTypeLib,
+                                                     DataTypeWrapper (..), DataUnion, TypeAlias (..), kindOf,
+                                                     lookupDataType, toGQLWrapper)
+import           Data.Morpheus.Types.Internal.Value (convertToJSONName)
+
+constRes :: Applicative m => a -> b -> m a
+constRes = const . pure
+
+type Result m a = DataTypeLib -> m a
+
+class RenderSchema a b where
+  render :: Monad m => (Text, a) -> DataTypeLib -> m (b m)
+
+instance RenderSchema DataFullType S__Type where
+  render (name, Leaf leaf) = render (name, leaf)
+  render (name, InputObject iObject) = renderInputObject (name, iObject)
+  render (name, OutputObject object') = typeFromObject (name, object')
+    where
+      typeFromObject (key, DataTyCon {typeData, typeDescription}) lib =
+        createObjectType key typeDescription <$>
+        (Just <$> traverse (`render` lib) (filter (not . fieldHidden . snd) typeData))
+  render (name, Union union') = const $ pure $ typeFromUnion (name, union')
+  render (name, InputUnion inpUnion') = renderInputUnion (name, inpUnion')
+
+instance RenderSchema DataLeaf S__Type where
+  render (key, BaseScalar DataTyCon {typeDescription}) _ = pure $ createLeafType SCALAR key typeDescription Nothing
+  render (key, CustomScalar DataTyCon {typeDescription}) _ = pure $ createLeafType SCALAR key typeDescription Nothing
+  render (key, LeafEnum DataTyCon {typeDescription, typeData}) _ =
+    pure $ createLeafType ENUM key typeDescription (Just $ map createEnumValue typeData)
+
+instance RenderSchema DataField S__Field where
+  render (key, field@DataField {fieldType = TypeAlias {aliasTyCon}, fieldArgs}) lib = do
+    kind <- renderTypeKind <$> lookupKind aliasTyCon lib
+    createFieldWith key (wrap field $ createType kind aliasTyCon Nothing $ Just []) <$>
+      traverse (`inputValueFromArg` lib) fieldArgs
+
+renderTypeKind :: DataTypeKind -> TypeKind
+renderTypeKind KindScalar      = SCALAR
+renderTypeKind (KindObject _)  = OBJECT
+renderTypeKind KindUnion       = UNION
+renderTypeKind KindInputUnion  = INPUT_OBJECT
+renderTypeKind KindEnum        = ENUM
+renderTypeKind KindInputObject = INPUT_OBJECT
+renderTypeKind KindList        = LIST
+renderTypeKind KindNonNull     = NON_NULL
+
+wrap :: Monad m => DataField -> S__Type m -> S__Type m
+wrap DataField {fieldType = TypeAlias {aliasWrappers}} typ = foldr wrapByTypeWrapper typ (toGQLWrapper aliasWrappers)
+
+wrapByTypeWrapper :: Monad m => DataTypeWrapper -> S__Type m -> S__Type m
+wrapByTypeWrapper ListType    = wrapAs LIST
+wrapByTypeWrapper NonNullType = wrapAs NON_NULL
+
+lookupKind :: Monad m => Text -> Result m DataTypeKind
+lookupKind name lib =
+  case lookupDataType name lib of
+    Nothing    -> fail $ unpack ("Kind Not Found: " <> name)
+    Just value -> pure (kindOf value)
+
+inputValueFromArg :: Monad m => (Text, DataField) -> Result m (S__InputValue m)
+inputValueFromArg (key, input) = fmap (createInputValueWith key) . createInputObjectType input
+
+createInputObjectType :: Monad m => DataField -> Result m (S__Type m)
+createInputObjectType field@DataField {fieldType = TypeAlias {aliasTyCon}} lib = do
+  kind <- renderTypeKind <$> lookupKind aliasTyCon lib
+  pure $ wrap field $ createType kind aliasTyCon Nothing $ Just []
+
+renderInputObject :: Monad m => (Text, DataObject) -> Result m (S__Type m)
+renderInputObject (key, DataTyCon {typeData, typeDescription}) lib = do
+  fields <- traverse (`inputValueFromArg` lib) typeData
+  pure $ createInputObject key typeDescription fields
+
+renderInputUnion :: Monad m => (Text, DataUnion) -> Result m (S__Type m)
+renderInputUnion (key', DataTyCon {typeData, typeDescription}) lib =
+  createInputObject key' typeDescription <$> traverse createField typeData
+  where
+    createField field = createInputValueWith (fieldName field) <$> createInputObjectType field lib
+
+createLeafType :: Monad m => TypeKind -> Text -> Maybe Text -> Maybe [S__EnumValue m] -> S__Type m
+createLeafType kind name description enums =
+  S__Type
+    { s__TypeKind = constRes kind
+    , s__TypeName = constRes $ Just name
+    , s__TypeDescription = constRes description
+    , s__TypeFields = constRes Nothing
+    , s__TypeOfType = constRes Nothing
+    , s__TypeInterfaces = constRes Nothing
+    , s__TypePossibleTypes = constRes Nothing
+    , s__TypeEnumValues = constRes enums
+    , s__TypeInputFields = constRes Nothing
+    }
+
+typeFromUnion :: Monad m => (Text, DataUnion) -> S__Type m
+typeFromUnion (name, DataTyCon {typeData, typeDescription}) =
+  S__Type
+    { s__TypeKind = constRes UNION
+    , s__TypeName = constRes $ Just name
+    , s__TypeDescription = constRes typeDescription
+    , s__TypeFields = constRes Nothing
+    , s__TypeOfType = constRes Nothing
+    , s__TypeInterfaces = constRes Nothing
+    , s__TypePossibleTypes =
+        constRes $ Just (map (\x -> createObjectType (aliasTyCon $ fieldType x) Nothing $ Just []) typeData)
+    , s__TypeEnumValues = constRes Nothing
+    , s__TypeInputFields = constRes Nothing
+    }
+
+createObjectType :: Monad m => Text -> Maybe Text -> Maybe [S__Field m] -> S__Type m
+createObjectType name description fields =
+  S__Type
+    { s__TypeKind = constRes OBJECT
+    , s__TypeName = constRes $ Just name
+    , s__TypeDescription = constRes description
+    , s__TypeFields = constRes fields
+    , s__TypeOfType = constRes Nothing
+    , s__TypeInterfaces = constRes $ Just []
+    , s__TypePossibleTypes = constRes Nothing
+    , s__TypeEnumValues = constRes Nothing
+    , s__TypeInputFields = constRes Nothing
+    }
+
+createInputObject :: Monad m => Text -> Maybe Text -> [S__InputValue m] -> S__Type m
+createInputObject name description fields =
+  S__Type
+    { s__TypeKind = constRes INPUT_OBJECT
+    , s__TypeName = constRes $ Just name
+    , s__TypeDescription = constRes description
+    , s__TypeFields = constRes Nothing
+    , s__TypeOfType = constRes Nothing
+    , s__TypeInterfaces = constRes Nothing
+    , s__TypePossibleTypes = constRes Nothing
+    , s__TypeEnumValues = constRes Nothing
+    , s__TypeInputFields = constRes $ Just fields
+    }
+
+createType :: Monad m => TypeKind -> Text -> Maybe Text -> Maybe [S__Field m] -> S__Type m
+createType kind name description fields' =
+  S__Type
+    { s__TypeKind = constRes kind
+    , s__TypeName = constRes $ Just name
+    , s__TypeDescription = constRes description
+    , s__TypeFields = constRes fields'
+    , s__TypeOfType = constRes Nothing
+    , s__TypeInterfaces = constRes Nothing
+    , s__TypePossibleTypes = constRes Nothing
+    , s__TypeEnumValues = constRes $ Just []
+    , s__TypeInputFields = constRes Nothing
+    }
+
+wrapAs :: Monad m => TypeKind -> S__Type m -> S__Type m
+wrapAs kind contentType =
+  S__Type
+    { s__TypeKind = constRes kind
+    , s__TypeName = constRes Nothing
+    , s__TypeDescription = constRes Nothing
+    , s__TypeFields = constRes Nothing
+    , s__TypeOfType = constRes $ Just contentType
+    , s__TypeInterfaces = constRes Nothing
+    , s__TypePossibleTypes = constRes Nothing
+    , s__TypeEnumValues = constRes Nothing
+    , s__TypeInputFields = constRes Nothing
+    }
+
+createFieldWith :: Monad m => Text -> S__Type m -> [S__InputValue m] -> S__Field m
+createFieldWith _name fieldType fieldArgs =
+  S__Field
+    { s__FieldName = constRes $ convertToJSONName _name
+    , s__FieldDescription = constRes Nothing
+    , s__FieldArgs = constRes fieldArgs
+    , s__FieldType' = constRes fieldType
+    , s__FieldIsDeprecated = constRes False
+    , s__FieldDeprecationReason = constRes Nothing
+    }
+
+createInputValueWith :: Monad m => Text -> S__Type m -> S__InputValue m
+createInputValueWith name ivType =
+  S__InputValue
+    { s__InputValueName = constRes name
+    , s__InputValueDescription = constRes Nothing
+    , s__InputValueType' = constRes ivType
+    , s__InputValueDefaultValue = constRes Nothing
+    }
+
+createEnumValue :: Monad m => Text -> S__EnumValue m
+createEnumValue name =
+  S__EnumValue
+    { s__EnumValueName = constRes name
+    , s__EnumValueDescription = constRes Nothing
+    , s__EnumValueIsDeprecated = constRes False
+    , s__EnumValueDeprecationReason = constRes Nothing
+    }
diff --git a/src/Data/Morpheus/Schema/Directive.hs b/src/Data/Morpheus/Schema/Directive.hs
deleted file mode 100644
--- a/src/Data/Morpheus/Schema/Directive.hs
+++ /dev/null
@@ -1,30 +0,0 @@
-{-# LANGUAGE DeriveAnyClass    #-}
-{-# LANGUAGE DeriveGeneric     #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE TypeFamilies      #-}
-{-# LANGUAGE TypeOperators     #-}
-
-module Data.Morpheus.Schema.Directive
-  ( Directive(..)
-  ) where
-
-import           Data.Aeson                             (FromJSON (..))
-import           Data.Morpheus.Kind                     (OBJECT)
-import           Data.Morpheus.Schema.DirectiveLocation (DirectiveLocation)
-import           Data.Morpheus.Schema.InputValue        (InputValue)
-import           Data.Morpheus.Types.GQLType            (GQLType (KIND, __typeName, __typeVisibility))
-import           Data.Text                              (Text)
-import           Data.Typeable                          (Typeable)
-import           GHC.Generics                           (Generic)
-
-instance Typeable a => GQLType (Directive a) where
-  type KIND (Directive a) = OBJECT
-  __typeName = const "__Directive"
-  __typeVisibility = const False
-
-data Directive t = Directive
-  { name        :: Text
-  , description :: Maybe Text
-  , locations   :: [DirectiveLocation]
-  , args        :: [InputValue t]
-  } deriving (Show, Generic, FromJSON)
diff --git a/src/Data/Morpheus/Schema/DirectiveLocation.hs b/src/Data/Morpheus/Schema/DirectiveLocation.hs
deleted file mode 100644
--- a/src/Data/Morpheus/Schema/DirectiveLocation.hs
+++ /dev/null
@@ -1,40 +0,0 @@
-{-# LANGUAGE DeriveAnyClass    #-}
-{-# LANGUAGE DeriveGeneric     #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE TypeFamilies      #-}
-
-module Data.Morpheus.Schema.DirectiveLocation
-  ( DirectiveLocation(..)
-  ) where
-
-import           Data.Aeson                  (FromJSON (..))
-import           Data.Morpheus.Kind          (ENUM)
-import           Data.Morpheus.Types.GQLType (GQLType (KIND, __typeName, __typeVisibility))
-import           GHC.Generics
-
-data DirectiveLocation
-  = QUERY
-  | MUTATION
-  | SUBSCRIPTION
-  | FIELD
-  | FRAGMENT_DEFINITION
-  | FRAGMENT_SPREAD
-  | INLINE_FRAGMENT
-  | VARIABLE_DEFINITION
-  | SCHEMA
-  | SCALAR
-  | OBJECT
-  | FIELD_DEFINITION
-  | ARGUMENT_DEFINITION
-  | INTERFACE
-  | UNION
-  | ENUM
-  | ENUM_VALUE
-  | INPUT_OBJECT
-  | INPUT_FIELD_DEFINITION
-  deriving (Show, Generic, FromJSON)
-
-instance GQLType DirectiveLocation where
-  type KIND DirectiveLocation = ENUM
-  __typeName = const "__DirectiveLocation"
-  __typeVisibility = const False
diff --git a/src/Data/Morpheus/Schema/EnumValue.hs b/src/Data/Morpheus/Schema/EnumValue.hs
deleted file mode 100644
--- a/src/Data/Morpheus/Schema/EnumValue.hs
+++ /dev/null
@@ -1,41 +0,0 @@
-{-# LANGUAGE DeriveAnyClass    #-}
-{-# LANGUAGE DeriveGeneric     #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE TypeFamilies      #-}
-
-module Data.Morpheus.Schema.EnumValue
-  ( EnumValue(..)
-  , createEnumValue
-  , isEnumOf
-  ) where
-
-import           Data.Aeson                  (FromJSON (..))
-import           Data.Morpheus.Kind          (OBJECT)
-import           Data.Morpheus.Types.GQLType (GQLType (KIND, __typeName, __typeVisibility))
-import           Data.Text                   (Text)
-import           GHC.Generics
-
-instance GQLType EnumValue where
-  type KIND EnumValue = OBJECT
-  __typeName = const "__EnumValue"
-  __typeVisibility = const False
-
-data EnumValue = EnumValue
-  { name              :: Text
-  , description       :: Maybe Text
-  , isDeprecated      :: Bool
-  , deprecationReason :: Maybe Text
-  } deriving (Show, Generic, FromJSON)
-
-createEnumValue :: Text -> EnumValue
-createEnumValue enumName =
-  EnumValue {name = enumName, description = Nothing, isDeprecated = False, deprecationReason = Nothing}
-
-isEnumValue :: Text -> EnumValue -> Bool
-isEnumValue inpName enum = inpName == name enum
-
-isEnumOf :: Text -> [EnumValue] -> Bool
-isEnumOf enumName enumValues =
-  case filter (isEnumValue enumName) enumValues of
-    [] -> False
-    _  -> True
diff --git a/src/Data/Morpheus/Schema/Field.hs b/src/Data/Morpheus/Schema/Field.hs
deleted file mode 100644
--- a/src/Data/Morpheus/Schema/Field.hs
+++ /dev/null
@@ -1,46 +0,0 @@
-{-# LANGUAGE DeriveGeneric     #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE TypeFamilies      #-}
-
-module Data.Morpheus.Schema.Field where
-
-import           Data.Aeson
-import           Data.Morpheus.Kind                 (OBJECT)
-import           Data.Morpheus.Schema.InputValue    (InputValue)
-import           Data.Morpheus.Types.GQLType        (GQLType (KIND, __typeName, __typeVisibility))
-import           Data.Morpheus.Types.Internal.Value (convertToJSONName)
-import           Data.Text                          (Text)
-import           Data.Typeable                      (Typeable)
-import           GHC.Generics
-
-instance Typeable a => GQLType (Field a) where
-  type KIND (Field a) = OBJECT
-  __typeName = const "__Field"
-  __typeVisibility = const False
-
-data Field t = Field
-  { name              :: Text
-  , description       :: Maybe Text
-  , args              :: [InputValue t]
-  , type'             :: t
-  , isDeprecated      :: Bool
-  , deprecationReason :: Maybe Text
-  } deriving (Show, Generic)
-
-instance FromJSON a => FromJSON (Field a) where
-  parseJSON = withObject "InputValue" objectParser
-    where
-      objectParser o =
-        Field <$> o .: "name" <*> o .:? "description" <*> o .: "args" <*> o .: "type" <*> o .: "isDeprecated" <*>
-        o .:? "deprecationReason"
-
-createFieldWith :: Text -> a -> [InputValue a] -> Field a
-createFieldWith _name fieldType fieldArgs =
-  Field
-    { name = convertToJSONName _name
-    , description = Nothing
-    , args = fieldArgs
-    , type' = fieldType
-    , isDeprecated = False
-    , deprecationReason = Nothing
-    }
diff --git a/src/Data/Morpheus/Schema/InputValue.hs b/src/Data/Morpheus/Schema/InputValue.hs
deleted file mode 100644
--- a/src/Data/Morpheus/Schema/InputValue.hs
+++ /dev/null
@@ -1,37 +0,0 @@
-{-# LANGUAGE DeriveGeneric     #-}
-{-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE TypeFamilies      #-}
-
-module Data.Morpheus.Schema.InputValue
-  ( InputValue(..)
-  , createInputValueWith
-  ) where
-
-import           Data.Aeson
-import           Data.Morpheus.Kind          (OBJECT)
-import           Data.Morpheus.Types.GQLType (GQLType (KIND, __typeName, __typeVisibility))
-import           Data.Text                   (Text)
-import           Data.Typeable               (Typeable)
-import           GHC.Generics
-
-instance Typeable a => GQLType (InputValue a) where
-  type KIND (InputValue a) = OBJECT
-  __typeName = const "__InputValue"
-  __typeVisibility = const False
-
-data InputValue t = InputValue
-  { name         :: Text
-  , description  :: Maybe Text
-  , type'        :: t
-  , defaultValue :: Maybe Text
-  } deriving (Show, Generic)
-
-instance FromJSON a => FromJSON (InputValue a) where
-  parseJSON = withObject "InputValue" objectParser
-    where
-      objectParser o = InputValue <$> o .: "name" <*> o .:? "description" <*> o .: "type" <*> o .:? "defaultValue"
-
-createInputValueWith :: Text -> a -> InputValue a
-createInputValueWith _name ofType =
-  InputValue {name = _name, description = Nothing, type' = ofType, defaultValue = Nothing}
diff --git a/src/Data/Morpheus/Schema/Internal/RenderIntrospection.hs b/src/Data/Morpheus/Schema/Internal/RenderIntrospection.hs
deleted file mode 100644
--- a/src/Data/Morpheus/Schema/Internal/RenderIntrospection.hs
+++ /dev/null
@@ -1,191 +0,0 @@
-{-# LANGUAGE NamedFieldPuns    #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE TypeOperators     #-}
-
-module Data.Morpheus.Schema.Internal.RenderIntrospection
-  ( Type
-  , Field
-  , InputValue
-  , renderType
-  , createObjectType
-  ) where
-
-import           Data.Morpheus.Schema.EnumValue    (EnumValue, createEnumValue)
-import qualified Data.Morpheus.Schema.Field        as F (Field (..), createFieldWith)
-import qualified Data.Morpheus.Schema.InputValue   as IN (InputValue (..), createInputValueWith)
-import           Data.Morpheus.Schema.Type         (Type (..))
-import           Data.Morpheus.Schema.TypeKind     (TypeKind (..))
-import           Data.Morpheus.Types.Internal.Data (DataField (..), DataFullType (..), DataInputField, DataInputObject,
-                                                    DataLeaf (..), DataOutputField, DataType (..), DataTypeKind (..),
-                                                    DataTypeLib, DataTypeWrapper (..), DataUnion, kindOf,
-                                                    lookupDataType)
-import           Data.Text                         (Text)
-
-type InputValue = IN.InputValue Type
-
-type Result a = DataTypeLib -> Either String a
-
-type Field = F.Field Type
-
-renderType :: (Text, DataFullType) -> Result Type
-renderType (name', Leaf leaf') = const $ pure $ typeFromLeaf (name', leaf')
-renderType (name', InputObject iObject') = renderInputObject (name', iObject')
-renderType (name', OutputObject object') = typeFromObject (name', object')
-  where
-    typeFromObject (key, DataType {typeData, typeDescription}) lib =
-      createObjectType key typeDescription <$>
-      (Just <$>
-       traverse
-         (`fieldFromObjectField` lib)
-         (filter (not . fieldHidden . snd) typeData))
-renderType (name', Union union') = const $ pure $ typeFromUnion (name', union')
-renderType (name', InputUnion inpUnion') = renderInputUnion (name', inpUnion')
-
-renderTypeKind :: DataTypeKind -> TypeKind
-renderTypeKind KindScalar      = SCALAR
-renderTypeKind KindObject      = OBJECT
-renderTypeKind KindUnion       = UNION
-renderTypeKind KindInputUnion  = INPUT_OBJECT
-renderTypeKind KindEnum        = ENUM
-renderTypeKind KindInputObject = INPUT_OBJECT
-renderTypeKind KindList        = LIST
-renderTypeKind KindNonNull     = NON_NULL
-
-wrap :: DataField a -> Type -> Type
-wrap field' = wrapRec (fieldTypeWrappers field')
-
-wrapRec :: [DataTypeWrapper] -> Type -> Type
-wrapRec xs type' = foldr wrapByTypeWrapper type' xs
-
-wrapByTypeWrapper :: DataTypeWrapper -> Type -> Type
-wrapByTypeWrapper ListType    = wrapAs LIST
-wrapByTypeWrapper NonNullType = wrapAs NON_NULL
-
-lookupKind :: Text -> Result DataTypeKind
-lookupKind name lib =
-  case lookupDataType name lib of
-    Nothing    -> Left ""
-    Just value -> Right (kindOf value)
-
-fieldFromObjectField :: (Text, DataOutputField) -> Result Field
-fieldFromObjectField (key, field'@DataField {fieldType, fieldArgs}) lib = do
-  kind <- renderTypeKind <$> lookupKind fieldType lib
-  F.createFieldWith key (wrap field' $ createType kind fieldType "" $ Just []) <$>
-    traverse (`inputValueFromArg` lib) fieldArgs
-
-typeFromLeaf :: (Text, DataLeaf) -> Type
-typeFromLeaf (key, BaseScalar DataType {typeDescription}) =
-  createLeafType SCALAR key typeDescription Nothing
-typeFromLeaf (key, CustomScalar DataType {typeDescription}) =
-  createLeafType SCALAR key typeDescription Nothing
-typeFromLeaf (key, LeafEnum DataType {typeDescription, typeData}) =
-  createLeafType ENUM key typeDescription (Just $ map createEnumValue typeData)
-
-createLeafType :: TypeKind -> Text -> Text -> Maybe [EnumValue] -> Type
-createLeafType kind' name' desc' enums' =
-  Type
-    { kind = kind'
-    , name = Just name'
-    , description = Just desc'
-    , fields = const $ return Nothing
-    , ofType = Nothing
-    , interfaces = Nothing
-    , possibleTypes = Nothing
-    , enumValues = const $ return enums'
-    , inputFields = Nothing
-    }
-
-typeFromUnion :: (Text, DataUnion) -> Type
-typeFromUnion (name', DataType { typeData = fields'
-                               , typeDescription = description'
-                               }) =
-  Type
-    { kind = UNION
-    , name = Just name'
-    , description = Just description'
-    , fields = const $ return Nothing
-    , ofType = Nothing
-    , interfaces = Nothing
-    , possibleTypes =
-        Just (map (\x -> createObjectType (fieldType x) "" $ Just []) fields')
-    , enumValues = const $ return Nothing
-    , inputFields = Nothing
-    }
-
-inputValueFromArg :: (Text, DataInputField) -> Result InputValue
-inputValueFromArg (key, input) =
-  fmap (IN.createInputValueWith key) . createInputObjectType input
-
-createInputObjectType :: DataInputField -> Result Type
-createInputObjectType field@DataField {fieldType} lib = do
-  kind <- renderTypeKind <$> lookupKind fieldType lib
-  pure $ wrap field $ createType kind fieldType "" $ Just []
-
-renderInputObject :: (Text, DataInputObject) -> Result Type
-renderInputObject (key, DataType {typeData, typeDescription}) lib = do
-  fields <- traverse (`inputValueFromArg` lib) typeData
-  pure $ createInputObject key typeDescription fields
-
-renderInputUnion :: (Text, DataUnion) -> Result Type
-renderInputUnion (key', DataType {typeData, typeDescription}) lib =
-  createInputObject key' typeDescription <$> traverse createField typeData
-  where
-    createField field =
-      IN.createInputValueWith (fieldName field) <$>
-      createInputObjectType field lib
-
-createObjectType :: Text -> Text -> Maybe [Field] -> Type
-createObjectType name' desc' fields' =
-  Type
-    { kind = OBJECT
-    , name = Just name'
-    , description = Just desc'
-    , fields = const $ return fields'
-    , ofType = Nothing
-    , interfaces = Just []
-    , possibleTypes = Nothing
-    , enumValues = const $ return Nothing
-    , inputFields = Nothing
-    }
-
-createInputObject :: Text -> Text -> [InputValue] -> Type
-createInputObject name' desc' fields' =
-  Type
-    { kind = INPUT_OBJECT
-    , name = Just name'
-    , description = Just desc'
-    , fields = const $ return Nothing
-    , ofType = Nothing
-    , interfaces = Nothing
-    , possibleTypes = Nothing
-    , enumValues = const $ return Nothing
-    , inputFields = Just fields'
-    }
-
-createType :: TypeKind -> Text -> Text -> Maybe [Field] -> Type
-createType kind' name' desc' fields' =
-  Type
-    { kind = kind'
-    , name = Just name'
-    , description = Just desc'
-    , fields = const $ return fields'
-    , ofType = Nothing
-    , interfaces = Nothing
-    , possibleTypes = Nothing
-    , enumValues = const $ return $ Just []
-    , inputFields = Nothing
-    }
-
-wrapAs :: TypeKind -> Type -> Type
-wrapAs kind' contentType =
-  Type
-    { kind = kind'
-    , name = Nothing
-    , description = Nothing
-    , fields = const $ return Nothing
-    , ofType = Just contentType
-    , interfaces = Nothing
-    , possibleTypes = Nothing
-    , enumValues = const $ return Nothing
-    , inputFields = Nothing
-    }
diff --git a/src/Data/Morpheus/Schema/JSONType.hs b/src/Data/Morpheus/Schema/JSONType.hs
deleted file mode 100644
--- a/src/Data/Morpheus/Schema/JSONType.hs
+++ /dev/null
@@ -1,46 +0,0 @@
-{-# LANGUAGE DeriveAnyClass #-}
-{-# LANGUAGE DeriveGeneric  #-}
-{-# LANGUAGE TypeFamilies   #-}
-{-# LANGUAGE TypeOperators  #-}
-
-module Data.Morpheus.Schema.JSONType
-  ( JSONType(..)
-  , JSONSchema(..)
-  , JSONIntro(..)
-  ) where
-
-import           Data.Aeson
-import           Data.Text                       (Text)
-import           GHC.Generics                    (Generic)
-
---
--- MORPHEUS
-import           Data.Morpheus.Schema.Directive  (Directive)
-import           Data.Morpheus.Schema.EnumValue  (EnumValue)
-import qualified Data.Morpheus.Schema.Field      as F (Field (..))
-import qualified Data.Morpheus.Schema.InputValue as I (InputValue (..))
-import           Data.Morpheus.Schema.TypeKind   (TypeKind)
-
-newtype JSONIntro = JSONIntro
-  { __schema :: JSONSchema
-  } deriving (Generic, Show, FromJSON)
-
-data JSONType = JSONType
-  { kind          :: TypeKind
-  , name          :: Maybe Text
-  , description   :: Maybe Text
-  , fields        :: Maybe [F.Field JSONType]
-  , interfaces    :: Maybe [JSONType]
-  , possibleTypes :: Maybe [JSONType]
-  , enumValues    :: Maybe [EnumValue]
-  , inputFields   :: Maybe [I.InputValue JSONType]
-  , ofType        :: Maybe JSONType
-  } deriving (Generic, Show, FromJSON)
-
-data JSONSchema = JSONSchema
-  { types      :: [JSONType]
-   --, queryType        :: JSONType
- -- , mutationType     :: Maybe JSONType
- -- , subscriptionType :: Maybe JSONType
-  , directives :: [Directive JSONType]
-  } deriving (Generic, Show, FromJSON)
diff --git a/src/Data/Morpheus/Schema/Schema.hs b/src/Data/Morpheus/Schema/Schema.hs
--- a/src/Data/Morpheus/Schema/Schema.hs
+++ b/src/Data/Morpheus/Schema/Schema.hs
@@ -1,60 +1,120 @@
-{-# LANGUAGE DeriveGeneric     #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE TupleSections     #-}
-{-# LANGUAGE TypeFamilies      #-}
-{-# LANGUAGE TypeOperators     #-}
+{-# LANGUAGE DeriveGeneric         #-}
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE NamedFieldPuns        #-}
+{-# LANGUAGE OverloadedStrings     #-}
+{-# LANGUAGE QuasiQuotes           #-}
+{-# LANGUAGE ScopedTypeVariables   #-}
+{-# LANGUAGE TemplateHaskell       #-}
+{-# LANGUAGE TypeFamilies          #-}
+{-# LANGUAGE TypeOperators         #-}
+{-# LANGUAGE TypeSynonymInstances  #-}
 
 module Data.Morpheus.Schema.Schema
-  ( initSchema
-  , findType
-  , Schema
-  , Type
+  ( Root(..)
+  , Root__typeArgs(..)
+  , S__Schema(..)
+  , S__Type(..)
+  , S__Field(..)
+  , S__EnumValue(..)
+  , S__InputValue(..)
   ) where
 
-import           Data.Morpheus.Kind                                (OBJECT)
-import           Data.Morpheus.Schema.Directive                    (Directive)
-import           Data.Morpheus.Schema.Internal.RenderIntrospection (Type, createObjectType, renderType)
-import           Data.Morpheus.Types.GQLType                       (GQLType (KIND, __typeName, __typeVisibility))
-import           Data.Morpheus.Types.Internal.Data                 (DataOutputObject, DataTypeLib (..), allDataTypes)
-import           Data.Text                                         (Text)
-import           GHC.Generics                                      (Generic)
+import           Data.Text                                (Text)
 
-instance GQLType Schema where
-  type KIND Schema = OBJECT
-  __typeName = const "__Schema"
-  __typeVisibility = const False
+-- MORPHEUS
+import           Data.Morpheus.Execution.Document.Compile (gqlDocumentNamespace)
+import           Data.Morpheus.Schema.TypeKind            (TypeKind)
 
-data Schema = Schema
-  { types            :: [Type]
-  , queryType        :: Type
-  , mutationType     :: Maybe Type
-  , subscriptionType :: Maybe Type
-  , directives       :: [Directive Type]
-  } deriving (Generic)
+type S__TypeKind = TypeKind
 
-convertTypes :: DataTypeLib -> [Type]
-convertTypes lib =
-  case traverse (`renderType` lib) (allDataTypes lib) of
-    Left _  -> []
-    Right x -> x
+[gqlDocumentNamespace|
+type __Schema {
+  types: [__Type!]!
+  queryType: __Type!
+  mutationType: __Type
+  subscriptionType: __Type
+  directives: [__Directive!]!
+}
 
-buildSchemaLinkType :: (Text, DataOutputObject) -> Type
-buildSchemaLinkType (key', _) = createObjectType key' "" $ Just []
+type __Type {
+  kind: __TypeKind!
+  name: String
+  description: String
 
-findType :: Text -> DataTypeLib -> Maybe Type
-findType name lib = (name, ) <$> lookup name (allDataTypes lib) >>= renderT
-  where
-    renderT i =
-      case renderType i lib of
-        Left _  -> Nothing
-        Right x -> Just x
+  # OBJECT and INTERFACE only
+  fields(includeDeprecated: Boolean ): [__Field!]
 
-initSchema :: DataTypeLib -> Schema
-initSchema types' =
-  Schema
-    { types = convertTypes types'
-    , queryType = buildSchemaLinkType $ query types'
-    , mutationType = buildSchemaLinkType <$> mutation types'
-    , subscriptionType = buildSchemaLinkType <$> subscription types'
-    , directives = []
-    }
+  # OBJECT only
+  interfaces: [__Type!]
+
+  # INTERFACE and UNION only
+  possibleTypes: [__Type!]
+
+  # ENUM only
+  enumValues(includeDeprecated: Boolean): [__EnumValue!]
+
+  # INPUT_OBJECT only
+  inputFields: [__InputValue!]
+
+  # NON_NULL and LIST only
+  ofType: __Type
+}
+
+type __Field {
+  name: String!
+  description: String
+  args: [__InputValue!]!
+  type: __Type!
+  isDeprecated: Boolean!
+  deprecationReason: String
+}
+
+type __InputValue {
+  name: String!
+  description: String
+  type: __Type!
+  defaultValue: String
+}
+
+type __EnumValue {
+  name: String!
+  description: String
+  isDeprecated: Boolean!
+  deprecationReason: String
+}
+
+type __Directive {
+  name: String!
+  description: String
+  locations: [__DirectiveLocation!]!
+  args: [__InputValue!]!
+}
+
+enum __DirectiveLocation {
+  QUERY
+  MUTATION
+  SUBSCRIPTION
+  FIELD
+  FRAGMENT_DEFINITION
+  FRAGMENT_SPREAD
+  INLINE_FRAGMENT
+  VARIABLE_DEFINITION
+  SCHEMA
+  SCALAR
+  OBJECT
+  FIELD_DEFINITION
+  ARGUMENT_DEFINITION
+  INTERFACE
+  UNION
+  ENUM
+  ENUM_VALUE
+  INPUT_OBJECT
+  INPUT_FIELD_DEFINITION
+}
+
+  type Root  {
+    __type(name: String!): __Type
+    __schema : __Schema!
+  }
+|]
diff --git a/src/Data/Morpheus/Schema/SchemaAPI.hs b/src/Data/Morpheus/Schema/SchemaAPI.hs
--- a/src/Data/Morpheus/Schema/SchemaAPI.hs
+++ b/src/Data/Morpheus/Schema/SchemaAPI.hs
@@ -1,5 +1,6 @@
-{-# LANGUAGE DeriveGeneric    #-}
+{-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE NamedFieldPuns   #-}
+{-# LANGUAGE TupleSections    #-}
 {-# LANGUAGE TypeApplications #-}
 {-# LANGUAGE TypeOperators    #-}
 
@@ -10,42 +11,64 @@
   ) where
 
 import           Data.Proxy
-import           Data.Text                                 (Text)
-import           GHC.Generics
+import           Data.Text                                   (Text)
 
 -- MORPHEUS
-import           Data.Morpheus.Execution.Server.Introspect (ObjectRep (..), TypeUpdater, introspectOutputType,
-                                                            resolveTypes)
-import           Data.Morpheus.Schema.Schema               (Schema, Type, findType, initSchema)
-import           Data.Morpheus.Types.ID                    (ID)
-import           Data.Morpheus.Types.Internal.Data         (DataField (..), DataOutputField, DataTypeLib (..))
+import           Data.Morpheus.Execution.Server.Introspect   (ObjectFields (..), TypeUpdater, introspect, resolveTypes)
+import           Data.Morpheus.Rendering.RenderIntrospection (createObjectType, render)
+import           Data.Morpheus.Schema.Schema                 (Root (..), Root__typeArgs (..), S__Schema (..), S__Type)
+import           Data.Morpheus.Types                         (constRes)
+import           Data.Morpheus.Types.GQLType                 (CUSTOM)
+import           Data.Morpheus.Types.ID                      (ID)
+import           Data.Morpheus.Types.Internal.Data           (DataField (..), DataObject, DataTypeLib (..),
+                                                              allDataTypes)
+import           Data.Morpheus.Types.Resolver                (GQLFail (..), ResolveT, Resolver)
 
-newtype TypeArgs = TypeArgs
-  { name :: Text
-  } deriving (Generic)
+convertTypes :: Monad m => DataTypeLib -> (Resolver m) [S__Type (Resolver m)]
+convertTypes lib = traverse (`render` lib) (allDataTypes lib)
 
-data SchemaAPI = SchemaAPI
-  { __type   :: TypeArgs -> Either String (Maybe Type)
-  , __schema :: Schema
-  } deriving (Generic)
+buildSchemaLinkType :: Monad m => (Text, DataObject) -> S__Type (Resolver m)
+buildSchemaLinkType (key', _) = createObjectType key' Nothing $ Just []
 
-hideFields :: (Text, DataField a) -> (Text, DataField a)
+findType :: Monad m => Text -> DataTypeLib -> Resolver m (Maybe (S__Type (Resolver m)))
+findType name lib = getType >>= renderT
+  where
+    getType = pure $ (name, ) <$> lookup name (allDataTypes lib)
+    ------------------------------------------------------------
+    renderT (Just datatype) = toSuccess (const Nothing) Just (render datatype lib)
+    renderT Nothing         = pure Nothing
+
+initSchema :: Monad m => DataTypeLib -> (Resolver m) (S__Schema (Resolver m))
+initSchema lib =
+  pure
+    S__Schema
+      { s__SchemaTypes = const $ convertTypes lib
+      , s__SchemaQueryType = constRes $ buildSchemaLinkType $ query lib
+      , s__SchemaMutationType = constRes $ buildSchemaLinkType <$> mutation lib
+      , s__SchemaSubscriptionType = constRes $ buildSchemaLinkType <$> subscription lib
+      , s__SchemaDirectives = constRes []
+      }
+
+hideFields :: (Text, DataField) -> (Text, DataField)
 hideFields (key', field) = (key', field {fieldHidden = True})
 
-hiddenRootFields :: [(Text, DataOutputField)]
-hiddenRootFields = map (hideFields . fst) $ objectFieldTypes $ Proxy @(Rep SchemaAPI)
+hiddenRootFields :: [(Text, DataField)]
+hiddenRootFields = map hideFields $ fst $ objectFields (Proxy :: Proxy (CUSTOM (Root Maybe))) (Proxy @(Root Maybe))
 
 defaultTypes :: TypeUpdater
 defaultTypes =
   flip
     resolveTypes
-    [ introspectOutputType (Proxy @Bool)
-    , introspectOutputType (Proxy @Int)
-    , introspectOutputType (Proxy @Float)
-    , introspectOutputType (Proxy @Text)
-    , introspectOutputType (Proxy @ID)
-    , introspectOutputType (Proxy @Schema)
+    [ introspect (Proxy @Bool)
+    , introspect (Proxy @Int)
+    , introspect (Proxy @Float)
+    , introspect (Proxy @Text)
+    , introspect (Proxy @ID)
+    , introspect (Proxy @(S__Schema Maybe))
     ]
 
-schemaAPI :: DataTypeLib -> SchemaAPI
-schemaAPI lib = SchemaAPI {__type = \TypeArgs {name} -> return $ findType name lib, __schema = initSchema lib}
+schemaAPI :: Monad m => DataTypeLib -> ResolveT m (Root (Resolver m))
+schemaAPI lib = pure $ Root {root__type, root__schema}
+  where
+    root__type (Root__typeArgs name) = findType name lib
+    root__schema _ = initSchema lib
diff --git a/src/Data/Morpheus/Schema/Type.hs b/src/Data/Morpheus/Schema/Type.hs
deleted file mode 100644
--- a/src/Data/Morpheus/Schema/Type.hs
+++ /dev/null
@@ -1,43 +0,0 @@
-{-# LANGUAGE DeriveGeneric     #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE TypeFamilies      #-}
-{-# LANGUAGE TypeOperators     #-}
-
-module Data.Morpheus.Schema.Type
-  ( Type(..)
-  , DeprecationArgs(..)
-  ) where
-
-import           Data.Morpheus.Kind              (OBJECT)
-import           Data.Morpheus.Schema.EnumValue  (EnumValue)
-import qualified Data.Morpheus.Schema.Field      as F (Field (..))
-import qualified Data.Morpheus.Schema.InputValue as I (InputValue (..))
-import           Data.Morpheus.Schema.TypeKind   (TypeKind)
-import           Data.Morpheus.Types.GQLType     (GQLType (KIND, __typeName, __typeVisibility))
-import           Data.Text                       (Text)
-import           GHC.Generics                    (Generic)
-
-instance GQLType Type where
-  type KIND Type = OBJECT
-  __typeName = const "__Type"
-  __typeVisibility = const False
-
-data Type =
-  Type
-    { kind          :: TypeKind
-    , name          :: Maybe Text
-    , description   :: Maybe Text
-    , fields        :: DeprecationArgs -> Either String (Maybe [F.Field Type])
-    , interfaces    :: Maybe [Type]
-    , possibleTypes :: Maybe [Type]
-    , enumValues    :: DeprecationArgs -> Either String (Maybe [EnumValue])
-    , inputFields   :: Maybe [I.InputValue Type]
-    , ofType        :: Maybe Type
-    }
-  deriving (Generic)
-
-newtype DeprecationArgs =
-  DeprecationArgs
-    { includeDeprecated :: Maybe Bool
-    }
-  deriving (Generic)
diff --git a/src/Data/Morpheus/Types.hs b/src/Data/Morpheus/Types.hs
--- a/src/Data/Morpheus/Types.hs
+++ b/src/Data/Morpheus/Types.hs
@@ -9,6 +9,7 @@
   , IOSubRes
   , Resolver
   , SubRootRes
+  , SubResolver(..)
   , Event(..)
   -- Type Classes
   , GQLType(KIND, description)
@@ -19,6 +20,7 @@
   , ID(..)
   , ScalarValue(..)
   , GQLRootResolver(..)
+  , constRes
   ) where
 
 import           Data.Morpheus.Types.GQLScalar      (GQLScalar (parseValue, serialize))
@@ -27,10 +29,14 @@
 import           Data.Morpheus.Types.Internal.Value (ScalarValue (..))
 import           Data.Morpheus.Types.IO             (GQLRequest (..), GQLResponse (..))
 import           Data.Morpheus.Types.Resolver       (Event (..), GQLRootResolver (..), MutResolver, Resolver,
-                                                     SubResolver, SubRootRes, mutResolver, resolver, toMutResolver)
+                                                     SubResolver (..), SubRootRes, mutResolver, resolver, toMutResolver)
 
+-- resolves constant value on any argument
+constRes :: Monad m => b -> a -> m b
+constRes = const . return
+
 type IORes = Resolver IO
 
 type IOMutRes e c = MutResolver IO e c
 
-type IOSubRes e c a = SubResolver IO e c a
+type IOSubRes e c = SubResolver IO e c
diff --git a/src/Data/Morpheus/Types/GQLType.hs b/src/Data/Morpheus/Types/GQLType.hs
--- a/src/Data/Morpheus/Types/GQLType.hs
+++ b/src/Data/Morpheus/Types/GQLType.hs
@@ -12,6 +12,8 @@
 
 module Data.Morpheus.Types.GQLType
   ( GQLType(..)
+  , TRUE
+  , FALSE
   ) where
 
 import           Data.Map                          (Map)
@@ -19,32 +21,38 @@
 import           Data.Set                          (Set)
 import           Data.Text                         (Text, intercalate, pack)
 import           Data.Typeable                     (TyCon, TypeRep, Typeable, splitTyConApp, tyConFingerprint,
-                                                    tyConName, typeRep)
+                                                    tyConName, typeRep, typeRepTyCon)
 
 -- MORPHEUS
 import           Data.Morpheus.Kind
 import           Data.Morpheus.Types.Custom        (MapKind, Pair)
 import           Data.Morpheus.Types.Internal.Data (DataFingerprint (..))
-import           Data.Morpheus.Types.Resolver      (Resolver)
+import           Data.Morpheus.Types.Resolver      (Resolver, SubResolver)
 
+type TRUE = 'True
+
+type FALSE = 'False
+
 resolverCon :: TyCon
-resolverCon = fst $ splitTyConApp $ typeRep $ Proxy @(Resolver Maybe)
+resolverCon = typeRepTyCon $ typeRep $ Proxy @(Resolver Maybe)
 
+subResCon :: TyCon
+subResCon = typeRepTyCon $ typeRep $ Proxy @(SubResolver Maybe)
+
 -- | replaces typeName (A,B) with Pair_A_B
 replacePairCon :: TyCon -> TyCon
 replacePairCon x
   | hsPair == x = gqlPair
   where
-    hsPair = fst $ splitTyConApp $ typeRep $ Proxy @(Int, Int)
-    gqlPair = fst $ splitTyConApp $ typeRep $ Proxy @(Pair Int Int)
+    hsPair = typeRepTyCon $ typeRep $ Proxy @(Int, Int)
+    gqlPair = typeRepTyCon $ typeRep $ Proxy @(Pair Int Int)
 replacePairCon x = x
 
 -- Ignores Resolver name  from typeName
 ignoreResolver :: (TyCon, [TypeRep]) -> [TyCon]
 ignoreResolver (con, _)
-  | con == resolverCon = []
-ignoreResolver (con, args) =
-  con : concatMap (ignoreResolver . splitTyConApp) args
+  | con `elem` [resolverCon, subResCon] = []
+ignoreResolver (con, args) = con : concatMap (ignoreResolver . splitTyConApp) args
 
 -- | GraphQL type, every graphQL type should have an instance of 'GHC.Generics.Generic' and 'GQLType'.
 --
@@ -62,8 +70,11 @@
 --  @
 class GQLType a where
   type KIND a :: GQL_KIND
-  description :: Proxy a -> Text
-  description _ = ""
+  type KIND a = OBJECT
+  type CUSTOM a :: Bool
+  type CUSTOM a = FALSE
+  description :: Proxy a -> Maybe Text
+  description _ = Nothing
   __typeVisibility :: Proxy a -> Bool
   __typeVisibility = const True
   __typeName :: Proxy a -> Text
@@ -71,18 +82,18 @@
     Proxy a -> Text
   __typeName _ = intercalate "_" (getName $ Proxy @a)
     where
-      getName =
-        fmap
-          (map (pack . tyConName))
-          (map replacePairCon . ignoreResolver . splitTyConApp . typeRep)
+      getName = fmap (map (pack . tyConName)) (map replacePairCon . ignoreResolver . splitTyConApp . typeRep)
   __typeFingerprint :: Proxy a -> DataFingerprint
   default __typeFingerprint :: (Typeable a) =>
     Proxy a -> DataFingerprint
   __typeFingerprint _ = TypeableFingerprint $ conFingerprints (Proxy @a)
     where
-      conFingerprints =
-        fmap (map tyConFingerprint) (ignoreResolver . splitTyConApp . typeRep)
+      conFingerprints = fmap (map tyConFingerprint) (ignoreResolver . splitTyConApp . typeRep)
 
+instance GQLType () where
+  type KIND () = WRAPPER
+  type CUSTOM () = 'False
+
 instance GQLType Int where
   type KIND Int = SCALAR
   __typeVisibility = const False
@@ -120,19 +131,29 @@
   __typeName _ = __typeName (Proxy @a)
   __typeFingerprint _ = __typeFingerprint (Proxy @a)
 
-instance (Typeable a, Typeable b, GQLType a, GQLType b) =>
-         GQLType (Pair a b) where
+instance (Typeable a, Typeable b, GQLType a, GQLType b) => GQLType (Pair a b) where
   type KIND (Pair a b) = OBJECT
 
-instance (Typeable a, Typeable b, Typeable m, GQLType a, GQLType b) =>
-         GQLType (MapKind a b m) where
+instance (Typeable a, Typeable b, GQLType a, GQLType b) => GQLType (MapKind a b m) where
   type KIND (MapKind a b m) = OBJECT
+  __typeName _ = __typeName (Proxy @(Map a b))
+  __typeFingerprint _ = __typeFingerprint (Proxy @(Map a b))
 
 instance (Typeable k, Typeable v) => GQLType (Map k v) where
   type KIND (Map k v) = WRAPPER
 
+instance GQLType a => GQLType (Either s a) where
+  type KIND (Either s a) = WRAPPER
+  __typeName _ = __typeName (Proxy @a)
+  __typeFingerprint _ = __typeFingerprint (Proxy @a)
+
 instance GQLType a => GQLType (Resolver m a) where
   type KIND (Resolver m a) = WRAPPER
+  __typeName _ = __typeName (Proxy @a)
+  __typeFingerprint _ = __typeFingerprint (Proxy @a)
+
+instance GQLType a => GQLType (SubResolver m e c a) where
+  type KIND (SubResolver m e c a) = WRAPPER
   __typeName _ = __typeName (Proxy @a)
   __typeFingerprint _ = __typeFingerprint (Proxy @a)
 
diff --git a/src/Data/Morpheus/Types/ID.hs b/src/Data/Morpheus/Types/ID.hs
--- a/src/Data/Morpheus/Types/ID.hs
+++ b/src/Data/Morpheus/Types/ID.hs
@@ -16,11 +16,9 @@
 -- | default GraphQL type,
 -- parses only 'String' and 'Int' values,
 -- serialized always as 'String'
-newtype ID =
-  ID
-    { unpackID :: Text
-    }
-  deriving (Generic)
+newtype ID = ID
+  { unpackID :: Text
+  } deriving (Show, Generic)
 
 instance GQLType ID where
   type KIND ID = SCALAR
diff --git a/src/Data/Morpheus/Types/Internal/AST/Operation.hs b/src/Data/Morpheus/Types/Internal/AST/Operation.hs
--- a/src/Data/Morpheus/Types/Internal/AST/Operation.hs
+++ b/src/Data/Morpheus/Types/Internal/AST/Operation.hs
@@ -5,7 +5,6 @@
 module Data.Morpheus.Types.Internal.AST.Operation
   ( Operation(..)
   , Variable(..)
-  , OperationKind(..)
   , ValidOperation
   , RawOperation
   , VariableDefinitions
@@ -15,7 +14,7 @@
 import           Data.Morpheus.Types.Internal.AST.RawSelection (RawSelectionSet)
 import           Data.Morpheus.Types.Internal.AST.Selection    (Arguments, SelectionSet)
 import           Data.Morpheus.Types.Internal.Base             (Collection, Key, Position)
-import           Data.Morpheus.Types.Internal.Data             (DataTypeWrapper)
+import           Data.Morpheus.Types.Internal.Data             (OperationKind, WrapperD)
 import           Data.Morpheus.Types.Internal.TH               (apply, liftText, liftTextMap)
 import           Data.Morpheus.Types.Internal.Value            (Value)
 import           Language.Haskell.TH.Syntax                    (Lift (..))
@@ -28,12 +27,6 @@
 
 type RawOperation = Operation VariableDefinitions RawSelectionSet
 
-data OperationKind
-  = QUERY
-  | MUTATION
-  | SUBSCRIPTION
-  deriving (Show, Lift)
-
 data Operation args sel = Operation
   { operationName      :: Key
   , operationKind      :: OperationKind
@@ -49,7 +42,7 @@
 data Variable a = Variable
   { variableType         :: Key
   , isVariableRequired   :: Bool
-  , variableTypeWrappers :: [DataTypeWrapper]
+  , variableTypeWrappers :: [WrapperD]
   , variablePosition     :: Position
   , variableValue        :: a
   } deriving (Show)
diff --git a/src/Data/Morpheus/Types/Internal/Base.hs b/src/Data/Morpheus/Types/Internal/Base.hs
--- a/src/Data/Morpheus/Types/Internal/Base.hs
+++ b/src/Data/Morpheus/Types/Internal/Base.hs
@@ -8,6 +8,7 @@
   , Position
   , EnhancedKey(..)
   , Location(..)
+  , Message
   , enhanceKeyWithNull
   ) where
 
@@ -24,6 +25,7 @@
   } deriving (Show, Generic, FromJSON, ToJSON, Lift)
 
 type Key = Text
+type Message = Text
 
 type Collection a = [(Key, a)]
 
diff --git a/src/Data/Morpheus/Types/Internal/Data.hs b/src/Data/Morpheus/Types/Internal/Data.hs
--- a/src/Data/Morpheus/Types/Internal/Data.hs
+++ b/src/Data/Morpheus/Types/Internal/Data.hs
@@ -1,22 +1,26 @@
-{-# LANGUAGE DeriveLift        #-}
-{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE DataKinds             #-}
+{-# LANGUAGE DefaultSignatures     #-}
+{-# LANGUAGE DeriveLift            #-}
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE GADTs                 #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE NamedFieldPuns        #-}
+{-# LANGUAGE OverloadedStrings     #-}
+{-# LANGUAGE PolyKinds             #-}
+{-# LANGUAGE RankNTypes            #-}
+{-# LANGUAGE TemplateHaskell       #-}
+{-# LANGUAGE TypeSynonymInstances  #-}
 
 module Data.Morpheus.Types.Internal.Data
   ( Key
   , DataScalar
   , DataEnum
   , DataObject
-  , DataInputField
   , DataArgument
-  , DataOutputField
-  , DataInputObject
-  , DataOutputObject
   , DataUnion
-  , DataOutputType
-  , DataInputType
   , DataArguments
   , DataField(..)
-  , DataType(..)
+  , DataTyCon(..)
   , DataLeaf(..)
   , DataKind(..)
   , DataFullType(..)
@@ -26,28 +30,67 @@
   , DataTypeKind(..)
   , DataFingerprint(..)
   , RawDataType(..)
+  , ResolverKind(..)
+  , WrapperD(..)
+  , TypeAlias(..)
+  , ArgsType(..)
   , isTypeDefined
   , initTypeLib
   , defineType
-  , showWrappedType
-  , showFullAstType
   , isFieldNullable
   , allDataTypes
   , lookupDataType
   , kindOf
+  , toNullableField
+  , toListField
+  , isObject
+  , isInput
+  , toHSWrappers
+  , isNullable
+  , toGQLWrapper
+  , isWeaker
+  , isVisible
+  , isSubscription
+  , isOutputObject
+  , OperationKind(..)
   ) where
 
-import           Data.Morpheus.Types.Internal.Value (Value (..))
-import           Data.Text                          (Text)
-import qualified Data.Text                          as T (concat)
+import           Data.Semigroup                     ((<>))
+import qualified Data.Text                          as T (pack, unpack)
 import           GHC.Fingerprint.Type               (Fingerprint)
-import           Language.Haskell.TH.Syntax         (Lift)
+import           Language.Haskell.TH.Syntax         (Lift (..))
 
-type Key = Text
+-- MORPHEUS
+import           Data.Morpheus.Types.Internal.Base  (Key)
+import           Data.Morpheus.Types.Internal.TH    (apply, liftText, liftTextMap)
+import           Data.Morpheus.Types.Internal.Value (Value (..))
 
+data OperationKind
+  = Query
+  | Subscription
+  | Mutation
+  deriving (Show, Eq, Lift)
+
+isSubscription :: DataTypeKind -> Bool
+isSubscription (KindObject (Just Subscription)) = True
+isSubscription _                                = False
+
+isOutputObject :: DataTypeKind -> Bool
+isOutputObject (KindObject _) = True
+isOutputObject _              = False
+
+isObject :: DataTypeKind -> Bool
+isObject (KindObject _)  = True
+isObject KindInputObject = True
+isObject _               = False
+
+isInput :: DataTypeKind -> Bool
+isInput KindInputObject = True
+isInput _               = False
+
 data DataTypeKind
   = KindScalar
-  | KindObject
+  | KindObject (Maybe OperationKind)
   | KindUnion
   | KindEnum
   | KindInputObject
@@ -56,39 +99,65 @@
   | KindInputUnion
   deriving (Eq, Show, Lift)
 
+data ResolverKind
+  = PlainResolver
+  | TypeVarResolver
+  | ExternalResolver
+  deriving (Show, Eq, Lift)
+
+data WrapperD
+  = ListD
+  | MaybeD
+  deriving (Show, Lift)
+
+isFieldNullable :: DataField -> Bool
+isFieldNullable = isNullable . aliasWrappers . fieldType
+
+isNullable :: [WrapperD] -> Bool
+isNullable (MaybeD:_) = True
+isNullable _          = False
+
+isWeaker :: [WrapperD] -> [WrapperD] -> Bool
+isWeaker (MaybeD:xs1) (MaybeD:xs2) = isWeaker xs1 xs2
+isWeaker (MaybeD:_) _              = True
+isWeaker (_:xs1) (_:xs2)           = isWeaker xs1 xs2
+isWeaker _ _                       = False
+
+toGQLWrapper :: [WrapperD] -> [DataTypeWrapper]
+toGQLWrapper (MaybeD:(MaybeD:tw)) = toGQLWrapper (MaybeD : tw)
+toGQLWrapper (MaybeD:(ListD:tw))  = ListType : toGQLWrapper tw
+toGQLWrapper (ListD:tw)           = [NonNullType, ListType] <> toGQLWrapper tw
+toGQLWrapper [MaybeD]             = []
+toGQLWrapper []                   = [NonNullType]
+
+toHSWrappers :: [DataTypeWrapper] -> [WrapperD]
+toHSWrappers (NonNullType:(NonNullType:xs)) = toHSWrappers (NonNullType : xs)
+toHSWrappers (NonNullType:(ListType:xs))    = ListD : toHSWrappers xs
+toHSWrappers (ListType:xs)                  = [MaybeD, ListD] <> toHSWrappers xs
+toHSWrappers []                             = [MaybeD]
+toHSWrappers [NonNullType]                  = []
+
 data DataFingerprint
-  = SystemFingerprint Text
+  = SystemFingerprint Key
   | TypeableFingerprint [Fingerprint]
   deriving (Show, Eq, Ord)
 
 newtype DataValidator = DataValidator
-  { validateValue :: Value -> Either Text Value
+  { validateValue :: Value -> Either Key Value
   }
 
 instance Show DataValidator where
   show _ = "DataValidator"
 
-type DataScalar = DataType DataValidator
-
-type DataEnum = DataType [Key]
-
-type DataObject a = DataType [(Key, a)]
-
-type DataInputField = DataField ()
-
-type DataArgument = DataInputField
-
-type DataOutputField = DataField [(Key, DataArgument)]
-
-type DataInputObject = DataObject DataInputField
+type DataScalar = DataTyCon DataValidator
 
-type DataOutputObject = DataObject DataOutputField
+type DataEnum = DataTyCon [Key]
 
-type DataUnion = DataType [DataField ()]
+type DataObject = DataTyCon [(Key, DataField)]
 
-type DataOutputType = DataKind DataOutputField
+type DataArgument = DataField
 
-type DataInputType = DataKind DataInputField
+type DataUnion = DataTyCon [DataField]
 
 type DataArguments = [(Key, DataArgument)]
 
@@ -97,22 +166,43 @@
   | NonNullType
   deriving (Show, Lift)
 
-data DataField a = DataField
-  { fieldArgs         :: a
-  , fieldName         :: Text
-  , fieldType         :: Text
-  , fieldTypeWrappers :: [DataTypeWrapper]
-  , fieldHidden       :: Bool
+data TypeAlias = TypeAlias
+  { aliasTyCon    :: Key
+  , aliasArgs     :: Maybe Key
+  , aliasWrappers :: [WrapperD]
   } deriving (Show)
 
-isFieldNullable :: DataField a -> Bool
-isFieldNullable DataField {fieldTypeWrappers = NonNullType:_} = False
-isFieldNullable _                                             = True
+instance Lift TypeAlias where
+  lift TypeAlias {aliasTyCon = x, aliasArgs, aliasWrappers} =
+    [|TypeAlias {aliasTyCon = name, aliasArgs = T.pack <$> args, aliasWrappers}|]
+    where
+      name = T.unpack x
+      args = T.unpack <$> aliasArgs
 
-data DataType a = DataType
-  { typeName        :: Text
+data ArgsType = ArgsType
+  { argsTypeName :: Key
+  , resKind      :: ResolverKind
+  } deriving (Show)
+
+instance Lift ArgsType where
+  lift (ArgsType argT kind) = apply 'ArgsType [liftText argT, lift kind]
+
+data DataField = DataField
+  { fieldName     :: Key
+  , fieldArgs     :: [(Key, DataArgument)]
+  , fieldArgsType :: Maybe ArgsType
+  , fieldType     :: TypeAlias
+  , fieldHidden   :: Bool
+  } deriving (Show)
+
+instance Lift DataField where
+  lift (DataField name args argsT ft hid) =
+    apply 'DataField [liftText name, liftTextMap args, lift argsT, lift ft, lift hid]
+
+data DataTyCon a = DataTyCon
+  { typeName        :: Key
   , typeFingerprint :: DataFingerprint
-  , typeDescription :: Text
+  , typeDescription :: Maybe Key
   , typeVisibility  :: Bool
   , typeData        :: a
   } deriving (Show)
@@ -123,56 +213,46 @@
   | LeafEnum DataEnum
   deriving (Show)
 
-data DataKind a
+-- DATA KIND
+data DataKind
   = ScalarKind DataScalar
   | EnumKind DataEnum
-  | ObjectKind (DataObject a)
+  | ObjectKind DataObject
   | UnionKind DataUnion
   deriving (Show)
 
 data RawDataType
   = FinalDataType DataFullType
-  | Interface DataOutputObject
+  | Interface DataObject
   | Implements { implementsInterfaces :: [Key]
-               , unImplements         :: DataOutputObject }
+               , unImplements         :: DataObject }
   deriving (Show)
 
 data DataFullType
   = Leaf DataLeaf
-  | InputObject DataInputObject
-  | OutputObject DataOutputObject
+  | InputObject DataObject
+  | OutputObject DataObject
   | Union DataUnion
   | InputUnion DataUnion
   deriving (Show)
 
 data DataTypeLib = DataTypeLib
-  { leaf         :: [(Text, DataLeaf)]
-  , inputObject  :: [(Text, DataInputObject)]
-  , object       :: [(Text, DataOutputObject)]
-  , union        :: [(Text, DataUnion)]
-  , inputUnion   :: [(Text, DataUnion)]
-  , query        :: (Text, DataOutputObject)
-  , mutation     :: Maybe (Text, DataOutputObject)
-  , subscription :: Maybe (Text, DataOutputObject)
+  { leaf         :: [(Key, DataLeaf)]
+  , inputObject  :: [(Key, DataObject)]
+  , object       :: [(Key, DataObject)]
+  , union        :: [(Key, DataUnion)]
+  , inputUnion   :: [(Key, DataUnion)]
+  , query        :: (Key, DataObject)
+  , mutation     :: Maybe (Key, DataObject)
+  , subscription :: Maybe (Key, DataObject)
   } deriving (Show)
 
-showWrappedType :: [DataTypeWrapper] -> Text -> Text
-showWrappedType [] type'               = type'
-showWrappedType (ListType:xs) type'    = T.concat ["[", showWrappedType xs type', "]"]
-showWrappedType (NonNullType:xs) type' = T.concat [showWrappedType xs type', "!"]
-
-showFullAstType :: [DataTypeWrapper] -> DataKind a -> Text
-showFullAstType wrappers' (ScalarKind x) = showWrappedType wrappers' (typeName x)
-showFullAstType wrappers' (EnumKind x)   = showWrappedType wrappers' (typeName x)
-showFullAstType wrappers' (ObjectKind x) = showWrappedType wrappers' (typeName x)
-showFullAstType wrappers' (UnionKind x)  = showWrappedType wrappers' (typeName x)
-
-initTypeLib :: (Text, DataOutputObject) -> DataTypeLib
-initTypeLib query' =
+initTypeLib :: (Key, DataObject) -> DataTypeLib
+initTypeLib query =
   DataTypeLib
     { leaf = []
     , inputObject = []
-    , query = query'
+    , query = query
     , object = []
     , union = []
     , inputUnion = []
@@ -180,7 +260,7 @@
     , subscription = Nothing
     }
 
-allDataTypes :: DataTypeLib -> [(Text, DataFullType)]
+allDataTypes :: DataTypeLib -> [(Key, DataFullType)]
 allDataTypes (DataTypeLib leaf' inputObject' object' union' inputUnion' query' mutation' subscription') =
   packType OutputObject query' :
   fromMaybeType mutation' ++
@@ -190,11 +270,11 @@
   map (packType InputUnion) inputUnion' ++ map (packType OutputObject) object' ++ map (packType Union) union'
   where
     packType f (x, y) = (x, f y)
-    fromMaybeType :: Maybe (Text, DataOutputObject) -> [(Text, DataFullType)]
+    fromMaybeType :: Maybe (Key, DataObject) -> [(Key, DataFullType)]
     fromMaybeType (Just (key', dataType')) = [(key', OutputObject dataType')]
     fromMaybeType Nothing                  = []
 
-lookupDataType :: Text -> DataTypeLib -> Maybe DataFullType
+lookupDataType :: Key -> DataTypeLib -> Maybe DataFullType
 lookupDataType name lib = name `lookup` allDataTypes lib
 
 kindOf :: DataFullType -> DataTypeKind
@@ -202,25 +282,40 @@
 kindOf (Leaf (CustomScalar _)) = KindScalar
 kindOf (Leaf (LeafEnum _))     = KindEnum
 kindOf (InputObject _)         = KindInputObject
-kindOf (OutputObject _)        = KindObject
+kindOf (OutputObject _)        = KindObject Nothing
 kindOf (Union _)               = KindUnion
 kindOf (InputUnion _)          = KindInputUnion
 
-isTypeDefined :: Text -> DataTypeLib -> Maybe DataFingerprint
-isTypeDefined name lib = getTypeFingerprint <$> lookupDataType name lib
-  where
-    getTypeFingerprint :: DataFullType -> DataFingerprint
-    getTypeFingerprint (Leaf (BaseScalar dataType'))   = typeFingerprint dataType'
-    getTypeFingerprint (Leaf (CustomScalar dataType')) = typeFingerprint dataType'
-    getTypeFingerprint (Leaf (LeafEnum dataType'))     = typeFingerprint dataType'
-    getTypeFingerprint (InputObject dataType')         = typeFingerprint dataType'
-    getTypeFingerprint (OutputObject dataType')        = typeFingerprint dataType'
-    getTypeFingerprint (Union dataType')               = typeFingerprint dataType'
-    getTypeFingerprint (InputUnion dataType')          = typeFingerprint dataType'
+fromDataType :: (DataTyCon () -> v) -> DataFullType -> v
+fromDataType f (Leaf (BaseScalar dt))   = f dt {typeData = ()}
+fromDataType f (Leaf (CustomScalar dt)) = f dt {typeData = ()}
+fromDataType f (Leaf (LeafEnum dt))     = f dt {typeData = ()}
+fromDataType f (Union dt)               = f dt {typeData = ()}
+fromDataType f (InputObject dt)         = f dt {typeData = ()}
+fromDataType f (InputUnion dt)          = f dt {typeData = ()}
+fromDataType f (OutputObject dt)        = f dt {typeData = ()}
 
-defineType :: (Text, DataFullType) -> DataTypeLib -> DataTypeLib
+isVisible :: DataFullType -> Bool
+isVisible = fromDataType typeVisibility
+
+isTypeDefined :: Key -> DataTypeLib -> Maybe DataFingerprint
+isTypeDefined name lib = fromDataType typeFingerprint <$> lookupDataType name lib
+
+defineType :: (Key, DataFullType) -> DataTypeLib -> DataTypeLib
 defineType (key', Leaf type') lib         = lib {leaf = (key', type') : leaf lib}
 defineType (key', InputObject type') lib  = lib {inputObject = (key', type') : inputObject lib}
 defineType (key', OutputObject type') lib = lib {object = (key', type') : object lib}
 defineType (key', Union type') lib        = lib {union = (key', type') : union lib}
 defineType (key', InputUnion type') lib   = lib {inputUnion = (key', type') : inputUnion lib}
+
+toNullableField :: DataField -> DataField
+toNullableField dataField
+  | isNullable (aliasWrappers $ fieldType dataField) = dataField
+  | otherwise = dataField {fieldType = nullable (fieldType dataField)}
+  where
+    nullable alias@TypeAlias {aliasWrappers} = alias {aliasWrappers = MaybeD : aliasWrappers}
+
+toListField :: DataField -> DataField
+toListField dataField = dataField {fieldType = listW (fieldType dataField)}
+  where
+    listW alias@TypeAlias {aliasWrappers} = alias {aliasWrappers = ListD : aliasWrappers}
diff --git a/src/Data/Morpheus/Types/Internal/DataD.hs b/src/Data/Morpheus/Types/Internal/DataD.hs
--- a/src/Data/Morpheus/Types/Internal/DataD.hs
+++ b/src/Data/Morpheus/Types/Internal/DataD.hs
@@ -1,38 +1,23 @@
 {-# LANGUAGE DeriveLift #-}
 
 module Data.Morpheus.Types.Internal.DataD
-  ( FieldD(..)
-  , TypeD(..)
+  ( TypeD(..)
   , ConsD(..)
   , QueryD(..)
-  , AppD(..)
-  , GQLTypeD
-  , gqlToHSWrappers
+  , GQLTypeD(..)
   ) where
 
 import           Language.Haskell.TH.Syntax        (Lift (..))
 
 --
 -- MORPHEUS
-import           Data.Morpheus.Types.Internal.Data (DataTypeKind, DataTypeWrapper (..))
-
-data AppD a
-  = ListD (AppD a)
-  | MaybeD (AppD a)
-  | ResD String
-         String
-         (AppD a)
-  | BaseD a
-  deriving (Show, Lift)
-
-gqlToHSWrappers :: [DataTypeWrapper] -> a -> AppD a
-gqlToHSWrappers []                             = MaybeD . BaseD
-gqlToHSWrappers [NonNullType]                  = BaseD
-gqlToHSWrappers (NonNullType:(ListType:xs))    = ListD . gqlToHSWrappers xs
-gqlToHSWrappers (NonNullType:(NonNullType:xs)) = gqlToHSWrappers xs
-gqlToHSWrappers (ListType:xs)                  = MaybeD . ListD . gqlToHSWrappers xs
+import           Data.Morpheus.Types.Internal.Data (DataField, DataTypeKind)
 
-type GQLTypeD = (TypeD, DataTypeKind, [TypeD])
+data GQLTypeD = GQLTypeD
+  { typeD     :: TypeD
+  , typeKindD :: DataTypeKind
+  , typeArgD  :: [TypeD]
+  } deriving (Show, Lift)
 
 data QueryD = QueryD
   { queryText     :: String
@@ -40,11 +25,6 @@
   , queryArgTypes :: [TypeD]
   } deriving (Show, Lift)
 
-data FieldD = FieldD
-  { fieldNameD :: String
-  , fieldTypeD :: AppD String
-  } deriving (Show, Lift)
-
 data TypeD = TypeD
   { tName :: String
   , tCons :: [ConsD]
@@ -52,5 +32,5 @@
 
 data ConsD = ConsD
   { cName   :: String
-  , cFields :: [FieldD]
+  , cFields :: [DataField]
   } deriving (Show, Lift)
diff --git a/src/Data/Morpheus/Types/Internal/Stream.hs b/src/Data/Morpheus/Types/Internal/Stream.hs
--- a/src/Data/Morpheus/Types/Internal/Stream.hs
+++ b/src/Data/Morpheus/Types/Internal/Stream.hs
@@ -1,6 +1,8 @@
-{-# LANGUAGE DeriveFunctor  #-}
-{-# LANGUAGE NamedFieldPuns #-}
-{-# LANGUAGE TypeFamilies   #-}
+{-# LANGUAGE DataKinds         #-}
+{-# LANGUAGE DeriveFunctor     #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE NamedFieldPuns    #-}
+{-# LANGUAGE TypeFamilies      #-}
 
 module Data.Morpheus.Types.Internal.Stream
   ( StreamState(..)
@@ -15,29 +17,55 @@
   , ResponseStream
   , closeStream
   , mapS
+  , injectEvents
+  , initExceptStream
+  , GQLStream(..)
   ) where
 
-import           Data.Morpheus.Types.IO (GQLResponse)
+import           Control.Monad.Trans.Except        (ExceptT (..), runExceptT)
+import           Data.Morpheus.Types.Internal.Data (OperationKind (..))
+import           Data.Morpheus.Types.IO            (GQLResponse)
 
-data Event e c =
-  Event
-    { channels :: [e]
-    , content  :: c
-    }
+newtype GQLStream (o :: OperationKind) (m :: * -> *) event a = GQLStream
+  { unGQLStream :: StreamT m (CHANNEL o m event a) (RESOLVER o m event a)
+  }
 
-data StreamState c v =
-  StreamState
-    { streamEvents :: [c]
-    , streamValue  :: v
-    }
-  deriving (Functor)
+instance Functor m => Functor (GQLStream 'Query m event) where
+  fmap f (GQLStream x) = GQLStream (f <$> x)
 
+instance Functor m => Functor (GQLStream 'Mutation m event) where
+  fmap f (GQLStream x) = GQLStream (f <$> x)
+
+class STREAM (o :: OperationKind) where
+  type RESOLVER o (m :: * -> *) event a :: *
+  type CHANNEL o (m :: * -> *) event a :: *
+
+instance STREAM 'Query where
+  type CHANNEL 'Query m event a = ()
+  type RESOLVER 'Query m event a = a
+
+instance STREAM 'Mutation where
+  type CHANNEL 'Mutation m event a = event
+  type RESOLVER 'Mutation m event a = a
+
+instance STREAM 'Subscription where
+  type CHANNEL 'Subscription m (Event channel content) a = channel
+  type RESOLVER 'Subscription m event a = event -> m a
+
+data Event e c = Event
+  { channels :: [e]
+  , content  :: c
+  }
+
+data StreamState c v = StreamState
+  { streamEvents :: [c]
+  , streamValue  :: v
+  } deriving (Functor)
+
 -- | Monad Transformer that sums all effect Together
-newtype StreamT m s a =
-  StreamT
-    { runStreamT :: m (StreamState s a)
-    }
-  deriving (Functor)
+newtype StreamT m s a = StreamT
+  { runStreamT :: m (StreamState s a)
+  } deriving (Functor)
 
 instance Monad m => Applicative (StreamT m c) where
   pure = StreamT . return . StreamState []
@@ -69,7 +97,7 @@
 
 type PublishStream m e c = StreamT m (PubEvent e c)
 
-type ResponseStream m event con a = StreamT m (ResponseEvent m event con) a
+type ResponseStream m event con = StreamT m (ResponseEvent m event con)
 
 -- Helper Functions
 toTuple :: StreamState s a -> ([s], a)
@@ -83,3 +111,9 @@
   StreamT $ do
     state <- ma
     return $ state {streamEvents = map func (streamEvents state)}
+
+injectEvents :: Functor m => [event] -> ExceptT e m a -> ExceptT e (StreamT m event) a
+injectEvents states = ExceptT . StreamT . fmap (StreamState states) . runExceptT
+
+initExceptStream :: Applicative m => [event] -> a -> ExceptT e (StreamT m event) a
+initExceptStream events = ExceptT . StreamT . pure . StreamState events . Right
diff --git a/src/Data/Morpheus/Types/Internal/TH.hs b/src/Data/Morpheus/Types/Internal/TH.hs
--- a/src/Data/Morpheus/Types/Internal/TH.hs
+++ b/src/Data/Morpheus/Types/Internal/TH.hs
@@ -1,12 +1,11 @@
-{-# LANGUAGE TemplateHaskell   #-}
+{-# LANGUAGE TemplateHaskell #-}
 
 module Data.Morpheus.Types.Internal.TH where
 
+import           Data.Text                  (Text, pack, unpack)
 import           Language.Haskell.TH
 import           Language.Haskell.TH.Syntax
-import           Data.Text                  (Text, pack, unpack)
 
-
 liftText :: Text -> ExpQ
 liftText x = appE (varE 'pack) (lift (unpack x))
 
@@ -18,3 +17,18 @@
 
 apply :: Name -> [Q Exp] -> Q Exp
 apply n = foldl appE (conE n)
+
+applyT :: Name -> [Q Type] -> Q Type
+applyT name = foldl appT (conT name)
+
+typeT :: Name -> [String] -> Q Type
+typeT name li = applyT name (map (varT . mkName) li)
+
+instanceHeadT :: Name -> String -> [String] -> Q Type
+instanceHeadT cName iType tArgs = applyT cName [applyT (mkName iType) (map (varT . mkName) tArgs)]
+
+instanceFunD :: Name -> [String] -> Q Exp -> Q Dec
+instanceFunD name args body = funD name [clause (map (varP . mkName) args) (normalB body) []]
+
+instanceHeadMultiT :: Name -> Q Type -> [Q Type] -> Q Type
+instanceHeadMultiT className iType li = applyT className (iType : li)
diff --git a/src/Data/Morpheus/Types/Internal/Validation.hs b/src/Data/Morpheus/Types/Internal/Validation.hs
--- a/src/Data/Morpheus/Types/Internal/Validation.hs
+++ b/src/Data/Morpheus/Types/Internal/Validation.hs
@@ -32,9 +32,9 @@
   , locations :: [Location]
   } deriving (Show, Generic, FromJSON, ToJSON)
 
-type Validation a = Either GQLErrors a
+type Validation = Either GQLErrors
 
-type SchemaValidation a = Validation a
+type SchemaValidation = Validation
 
 type ResolveT = ExceptT GQLErrors
 
diff --git a/src/Data/Morpheus/Types/Internal/Value.hs b/src/Data/Morpheus/Types/Internal/Value.hs
--- a/src/Data/Morpheus/Types/Internal/Value.hs
+++ b/src/Data/Morpheus/Types/Internal/Value.hs
@@ -1,11 +1,16 @@
-{-# LANGUAGE DeriveGeneric     #-}
-{-# LANGUAGE DeriveLift        #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE TemplateHaskell   #-}
+{-# LANGUAGE DeriveGeneric       #-}
+{-# LANGUAGE DeriveLift          #-}
+{-# LANGUAGE FlexibleInstances   #-}
+{-# LANGUAGE OverloadedStrings   #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE TupleSections       #-}
 
 module Data.Morpheus.Types.Internal.Value
   ( Value(..)
   , ScalarValue(..)
+  , Object
+  , GQLValue(..)
   , replaceValue
   , decodeScientific
   , convertToJSONName
@@ -13,8 +18,8 @@
   ) where
 
 import qualified Data.Aeson                      as A (FromJSON (..), ToJSON (..), Value (..), object, pairs, (.=))
+import           Data.Function                   ((&))
 import qualified Data.HashMap.Strict             as M (toList)
-import           Data.Morpheus.Types.Internal.TH (apply, liftText, liftTextMap)
 import           Data.Scientific                 (Scientific, floatingOrInteger)
 import           Data.Semigroup                  ((<>))
 import           Data.Text                       (Text)
@@ -24,6 +29,9 @@
 import           Language.Haskell.TH
 import           Language.Haskell.TH.Syntax
 
+-- MORPHEUS
+import           Data.Morpheus.Types.Internal.TH (apply, liftText, liftTextMap)
+
 isReserved :: Text -> Bool
 isReserved "case"     = True
 isReserved "class"    = True
@@ -97,8 +105,10 @@
   lift (Scalar n)  = apply 'Scalar [lift n]
   lift Null        = varE 'Null
 
+type Object = [(Text, Value)]
+
 data Value
-  = Object [(Text, Value)]
+  = Object Object
   | List [Value]
   | Enum Text
   | Scalar ScalarValue
@@ -115,9 +125,6 @@
     where
       encodeField (key, value) = convertToJSONName key A..= value
 
-replace :: (a, A.Value) -> (a, Value)
-replace (key, val) = (key, replaceValue val)
-
 decodeScientific :: Scientific -> ScalarValue
 decodeScientific v =
   case floatingOrInteger v of
@@ -125,12 +132,64 @@
     Right int  -> Int int
 
 replaceValue :: A.Value -> Value
-replaceValue (A.Bool v)   = Scalar $ Boolean v
+replaceValue (A.Bool v) = gqlBoolean v
 replaceValue (A.Number v) = Scalar $ decodeScientific v
-replaceValue (A.String v) = Scalar $ String v
-replaceValue (A.Object v) = Object $ map replace (M.toList v)
-replaceValue (A.Array li) = List (map replaceValue (V.toList li))
-replaceValue A.Null       = Null
+replaceValue (A.String v) = gqlString v
+replaceValue (A.Object v) = gqlObject $ map replace (M.toList v)
+  where
+    replace :: (a, A.Value) -> (a, Value)
+    replace (key, val) = (key, replaceValue val)
+replaceValue (A.Array li) = gqlList (map replaceValue (V.toList li))
+replaceValue A.Null = gqlNull
 
 instance A.FromJSON Value where
   parseJSON = pure . replaceValue
+
+-- DEFAULT VALUES
+class GQLValue a where
+  gqlNull :: a
+  gqlScalar :: ScalarValue -> a
+  gqlBoolean :: Bool -> a
+  gqlString :: Text -> a
+  gqlList :: [a] -> a
+  gqlObject :: [(Text, a)] -> a
+
+-- build GQL Values for Subscription Resolver
+instance GQLValue Value where
+  gqlNull = Null
+  gqlScalar = Scalar
+  gqlBoolean = Scalar . Boolean
+  gqlString = Scalar . String
+  gqlList = List
+  gqlObject = Object
+
+instance Monad m => GQLValue (m Value) where
+  gqlNull = pure gqlNull
+  gqlScalar = pure . gqlScalar
+  gqlBoolean = pure . gqlBoolean
+  gqlString = pure . gqlString
+  -----------------------------------------
+  -- listValue :: [m Value] -> m Value
+  gqlList = fmap gqlList . sequence
+  -----------------------------------------
+  -- objectValue :: [(Text, m Value )] -> m Value
+  gqlObject = fmap gqlObject . traverse keyVal
+    where
+      keyVal :: Monad m => (Text, m Value) -> m (Text, Value)
+      keyVal (key, valFunc) = (key, ) <$> valFunc
+
+-- build GQL Values for Subscription Resolver
+instance Monad m => GQLValue (args -> m Value) where
+  gqlNull = const gqlNull
+  gqlScalar = const . gqlScalar
+  gqlBoolean = pure . gqlBoolean
+  gqlString = const . gqlString
+  ----------------------------------------
+   -- listValue :: [args -> m Value] -> ( args -> m Value )
+  gqlList res args = gqlList <$> traverse (args &) res
+  ----------------------------------------
+  -- objectValue :: [(Text, args -> m Value )] -> ( args -> m Value )
+  gqlObject res args = gqlObject <$> traverse keyVal res
+    where
+      keyVal :: Monad m => (Text, args -> m Value) -> m (Text, Value)
+      keyVal (key, valFunc) = (key, ) <$> valFunc args
diff --git a/src/Data/Morpheus/Types/Resolver.hs b/src/Data/Morpheus/Types/Resolver.hs
--- a/src/Data/Morpheus/Types/Resolver.hs
+++ b/src/Data/Morpheus/Types/Resolver.hs
@@ -12,40 +12,74 @@
   ( Pure
   , Resolver
   , MutResolver
-  , SubResolver
+  , SubResolver(..)
   , ResolveT
   , SubResolveT
   , MutResolveT
   , SubRootRes
   , Event(..)
   , GQLRootResolver(..)
+  , UnSubResolver
   , resolver
   , mutResolver
   , toMutResolver
+  , GQLFail(..)
+  , ResponseT
   ) where
 
 import           Control.Monad.Trans.Except              (ExceptT (..), runExceptT)
+import           Data.Text                               (pack, unpack)
 
 -- MORPHEUS
 --
-import           Data.Morpheus.Types.Internal.Stream     (Event (..), PublishStream, StreamState (..), StreamT (..),
-                                                          SubscribeStream)
+import           Data.Morpheus.Types.Internal.Base       (Message)
+import           Data.Morpheus.Types.Internal.Stream     (Event (..), PublishStream, ResponseStream, StreamState (..),
+                                                          StreamT (..), SubscribeStream)
 import           Data.Morpheus.Types.Internal.Validation (ResolveT)
 
--- SubResolver m (Event [c1, c2] d) a
+class Monad m =>
+      GQLFail (t :: (* -> *) -> * -> *) m
+  where
+  gqlFail :: Monad m => Message -> t m a
+  toSuccess :: Monad m => (Message -> b) -> (a -> b) -> t m a -> t m b
+
+instance Monad m => GQLFail Resolver m where
+  gqlFail = ExceptT . pure . Left . unpack
+  toSuccess fFail fSuc (ExceptT value) = ExceptT $ pure . mapCases <$> value
+    where
+      mapCases (Right x) = fSuc x
+      mapCases (Left x)  = fFail $ pack $ show x
+
 ----------------------------------------------------------------------------------------
-type MutResolveT m e c a = ResolveT (PublishStream m e c) a
+{--
+newtype SubResolveT m e c a = SubResolveT
+  { unSubResolveT :: ResolveT (SubscribeStream m e) (Event e c -> ResolveT m a)
+  }
 
+newtype MutResolveT m e c a = MutResolveT
+  { unMutResolveT :: ResolveT (PublishStream m e c) a
+  }
+-}
+data SubResolver m e c a = SubResolver
+  { subChannels :: [e]
+  , subResolver :: Event e c -> Resolver m a
+  }
+
+type family UnSubResolver (a :: * -> *) :: (* -> *)
+
+type instance UnSubResolver (SubResolver m e c) = Resolver m
+
 -------------------------------------------------------------------
 type Resolver = ExceptT String
 
-type MutResolver m e c = Resolver (PublishStream m e c)
+type ResponseT m e c = ResolveT (ResponseStream m e c)
 
-type SubResolver m e c a = Event e (Event e c -> Resolver m a)
+type MutResolveT m e c = ResolveT (PublishStream m e c)
 
-type SubResolveT m e c a
-   = ResolveT (SubscribeStream m e) (Event e c -> ResolveT m a)
+type SubResolveT m e c a = ResolveT (SubscribeStream m e) (Event e c -> ResolveT m a)
 
+type MutResolver m e c = Resolver (PublishStream m e c)
+
 type SubRootRes m e sub = Resolver (SubscribeStream m e) sub
 
 -------------------------------------------------------------------
@@ -57,15 +91,10 @@
 resolver = ExceptT
 
 toMutResolver :: Monad m => [Event e c] -> Resolver m a -> MutResolver m e c a
-toMutResolver channels =
-  ExceptT . StreamT . fmap (StreamState channels) . runExceptT
+toMutResolver channels = ExceptT . StreamT . fmap (StreamState channels) . runExceptT
 
 -- | GraphQL Resolver for mutation or subscription resolver , adds effect to normal resolver
-mutResolver ::
-     Monad m
-  => [Event e c]
-  -> (StreamT m (Event e c)) (Either String a)
-  -> MutResolver m e c a
+mutResolver :: Monad m => [Event e c] -> (StreamT m (Event e c)) (Either String a) -> MutResolver m e c a
 mutResolver channels = ExceptT . StreamT . fmap effectPlus . runStreamT
   where
     effectPlus state = state {streamEvents = channels ++ streamEvents state}
@@ -74,9 +103,8 @@
 --
 --  'queryResolver' is required, 'mutationResolver' and 'subscriptionResolver' are optional,
 --  if your schema does not supports __mutation__ or __subscription__ , you acn use __()__ for it.
-data GQLRootResolver m e c query mut sub =
-  GQLRootResolver
-    { queryResolver        :: Resolver m query
-    , mutationResolver     :: Resolver (PublishStream m e c) mut
-    , subscriptionResolver :: SubRootRes m e sub
-    }
+data GQLRootResolver m e c query mut sub = GQLRootResolver
+  { queryResolver        :: Resolver m query
+  , mutationResolver     :: Resolver (PublishStream m e c) mut
+  , subscriptionResolver :: SubRootRes m e sub
+  }
diff --git a/src/Data/Morpheus/Validation/Document/Validation.hs b/src/Data/Morpheus/Validation/Document/Validation.hs
--- a/src/Data/Morpheus/Validation/Document/Validation.hs
+++ b/src/Data/Morpheus/Validation/Document/Validation.hs
@@ -9,12 +9,10 @@
 --
 -- Morpheus
 import           Data.Morpheus.Error.Document.Interface  (ImplementsError (..), partialImplements, unknownInterface)
-import           Data.Morpheus.Types.Internal.Base       (Location (..))
-import           Data.Morpheus.Types.Internal.Data       (DataField (..), DataFullType (..), DataOutputField,
-                                                          DataOutputObject, DataType (..), Key, RawDataType (..),
-                                                          showWrappedType)
+import           Data.Morpheus.Rendering.RenderGQL       (RenderGQL (..))
+import           Data.Morpheus.Types.Internal.Data       (DataField (..), DataFullType (..), DataObject, DataTyCon (..),
+                                                          Key, RawDataType (..), TypeAlias (..), isWeaker, isWeaker)
 import           Data.Morpheus.Types.Internal.Validation (Validation)
-import           Data.Morpheus.Validation.Internal.Utils (isEqOrStricter)
 
 validatePartialDocument :: [(Key, RawDataType)] -> Validation [(Key, DataFullType)]
 validatePartialDocument lib = catMaybes <$> traverse validateType lib
@@ -26,28 +24,29 @@
     -----------------------------------
     asTuple name x = Just (name, x)
     -----------------------------------
-    mustImplement :: DataOutputObject -> [Key] -> Validation DataFullType
+    mustImplement :: DataObject -> [Key] -> Validation DataFullType
     mustImplement object interfaceKey = do
       interface <- traverse getInterfaceByKey interfaceKey
       case concatMap (mustBeSubset object) interface of
         []     -> pure $ OutputObject object
-        errors -> Left $ partialImplements (typeName object)  errors
+        errors -> Left $ partialImplements (typeName object) errors
     -------------------------------
-    mustBeSubset :: DataOutputObject -> DataOutputObject -> [(Key, Key, ImplementsError)]
-    mustBeSubset DataType {typeData = objFields} DataType {typeName, typeData = interfaceFields} =
+    mustBeSubset :: DataObject -> DataObject -> [(Key, Key, ImplementsError)]
+    mustBeSubset DataTyCon {typeData = objFields} DataTyCon {typeName, typeData = interfaceFields} =
       concatMap checkField interfaceFields
       where
-        checkField :: (Key, DataOutputField) -> [(Key, Key, ImplementsError)]
-        checkField (key, DataField {fieldType = interfaceTypeName, fieldTypeWrappers = interfaceWrappers}) =
+        checkField :: (Key, DataField) -> [(Key, Key, ImplementsError)]
+        checkField (key, DataField {fieldType = interfaceT@TypeAlias { aliasTyCon = interfaceTypeName
+                                                                     , aliasWrappers = interfaceWrappers
+                                                                     }}) =
           case lookup key objFields of
-            Just DataField {fieldType, fieldTypeWrappers}
-              | fieldType == interfaceTypeName && isEqOrStricter fieldTypeWrappers interfaceWrappers -> []
-              | otherwise -> [(typeName, key, UnexpectedType {expectedType, foundType})]
-              where expectedType = showWrappedType interfaceWrappers interfaceTypeName
-                    foundType = showWrappedType fieldTypeWrappers fieldType
+            Just DataField {fieldType = objT@TypeAlias {aliasTyCon, aliasWrappers}}
+              | aliasTyCon == interfaceTypeName && not (isWeaker aliasWrappers interfaceWrappers) -> []
+              | otherwise ->
+                [(typeName, key, UnexpectedType {expectedType = render interfaceT, foundType = render objT})]
             Nothing -> [(typeName, key, UndefinedField)]
     -------------------------------
-    getInterfaceByKey :: Key -> Validation DataOutputObject
+    getInterfaceByKey :: Key -> Validation DataObject
     getInterfaceByKey key =
       case lookup key lib of
         Just (Interface x) -> pure x
diff --git a/src/Data/Morpheus/Validation/Internal/Utils.hs b/src/Data/Morpheus/Validation/Internal/Utils.hs
--- a/src/Data/Morpheus/Validation/Internal/Utils.hs
+++ b/src/Data/Morpheus/Validation/Internal/Utils.hs
@@ -6,15 +6,13 @@
   , lookupField
   , checkNameCollision
   , checkForUnknownKeys
-  , isEqOrStricter
   , VALIDATION_MODE(..)
   ) where
 
 import           Data.List                               ((\\))
 import           Data.Morpheus.Error.Variable            (unknownType)
 import           Data.Morpheus.Types.Internal.Base       (EnhancedKey (..), Key, Position, enhanceKeyWithNull)
-import           Data.Morpheus.Types.Internal.Data       (DataInputType, DataKind (..), DataLeaf (..), DataOutputObject,
-                                                          DataTypeLib (..), DataTypeWrapper (..))
+import           Data.Morpheus.Types.Internal.Data       (DataKind (..), DataLeaf (..), DataObject, DataTypeLib (..))
 import           Data.Morpheus.Types.Internal.Validation (Validation)
 import qualified Data.Set                                as S
 import           Data.Text                               (Text)
@@ -38,7 +36,7 @@
     Nothing    -> Left error'
     Just field -> pure field
 
-getInputType :: Text -> DataTypeLib -> GenError error DataInputType
+getInputType :: Text -> DataTypeLib -> GenError error DataKind
 getInputType typeName' lib error' =
   case lookup typeName' (inputObject lib) of
     Just x -> pure (ObjectKind x)
@@ -52,7 +50,7 @@
             Just (CustomScalar x) -> pure (ScalarKind x)
             Just (LeafEnum x)     -> pure (EnumKind x)
 
-existsObjectType :: Position -> Text -> DataTypeLib -> Validation DataOutputObject
+existsObjectType :: Position -> Text -> DataTypeLib -> Validation DataObject
 existsObjectType position' typeName' lib = lookupType error' (object lib) typeName'
   where
     error' = unknownType typeName' position'
@@ -77,10 +75,3 @@
   case filter (not . elementOfKeys keys') enhancedKeys' of
     []           -> pure enhancedKeys'
     unknownKeys' -> Left $ errorGenerator' unknownKeys'
-
-isEqOrStricter :: [DataTypeWrapper] -> [DataTypeWrapper] -> Bool
-isEqOrStricter [] []                               = True
-isEqOrStricter (NonNullType:xs1) (NonNullType:xs2) = isEqOrStricter xs1 xs2
-isEqOrStricter (NonNullType:xs1) xs2               = isEqOrStricter xs1 xs2
-isEqOrStricter (ListType:xs1) (ListType:xs2)       = isEqOrStricter xs1 xs2
-isEqOrStricter _ _                                 = False
diff --git a/src/Data/Morpheus/Validation/Query/Arguments.hs b/src/Data/Morpheus/Validation/Query/Arguments.hs
--- a/src/Data/Morpheus/Validation/Query/Arguments.hs
+++ b/src/Data/Morpheus/Validation/Query/Arguments.hs
@@ -10,21 +10,20 @@
 import           Data.Morpheus.Error.Input                     (InputValidation, inputErrorMessage)
 import           Data.Morpheus.Error.Internal                  (internalUnknownTypeMessage)
 import           Data.Morpheus.Error.Variable                  (incompatibleVariableType, undefinedVariable)
+import           Data.Morpheus.Rendering.RenderGQL             (RenderGQL (..))
 import           Data.Morpheus.Types.Internal.AST.Operation    (ValidVariables, Variable (..))
 import           Data.Morpheus.Types.Internal.AST.RawSelection (RawArgument (..), RawArguments, Reference (..))
 import           Data.Morpheus.Types.Internal.AST.Selection    (Argument (..), ArgumentOrigin (..), Arguments)
 import           Data.Morpheus.Types.Internal.Base             (EnhancedKey (..), Position)
-import           Data.Morpheus.Types.Internal.Data             (DataArgument, DataField (..), DataInputField,
-                                                                DataOutputField, DataTypeLib, isFieldNullable,
-                                                                showWrappedType)
+import           Data.Morpheus.Types.Internal.Data             (DataArgument, DataField (..), DataField, DataTypeLib,
+                                                                TypeAlias (..), isFieldNullable, isWeaker)
 import           Data.Morpheus.Types.Internal.Validation       (Validation)
 import           Data.Morpheus.Types.Internal.Value            (Value (Null))
-import           Data.Morpheus.Validation.Internal.Utils       (checkForUnknownKeys, checkNameCollision, getInputType,
-                                                                isEqOrStricter)
+import           Data.Morpheus.Validation.Internal.Utils       (checkForUnknownKeys, checkNameCollision, getInputType)
 import           Data.Morpheus.Validation.Query.Input.Object   (validateInputValue)
 import           Data.Text                                     (Text)
 
-resolveArgumentVariables :: Text -> ValidVariables -> DataOutputField -> RawArguments -> Validation Arguments
+resolveArgumentVariables :: Text -> ValidVariables -> DataField -> RawArguments -> Validation Arguments
 resolveArgumentVariables operatorName variables DataField {fieldName, fieldArgs} = mapM resolveVariable
   where
     resolveVariable :: (Text, RawArgument) -> Validation (Text, Argument)
@@ -40,55 +39,51 @@
             Just Variable {variableValue, variableType, variableTypeWrappers} ->
               case lookup key fieldArgs of
                 Nothing -> Left $ unknownArguments fieldName [EnhancedKey key referencePosition]
-                Just DataField {fieldType, fieldTypeWrappers} ->
-                  if variableType == fieldType && isEqOrStricter variableTypeWrappers fieldTypeWrappers
+                Just DataField {fieldType = fieldT@TypeAlias {aliasTyCon, aliasWrappers}} ->
+                  if variableType == aliasTyCon && not (isWeaker variableTypeWrappers aliasWrappers)
                     then return variableValue
                     else Left $ incompatibleVariableType referenceName varSignature fieldSignature referencePosition
-                  where varSignature = showWrappedType variableTypeWrappers variableType
-                        fieldSignature = showWrappedType fieldTypeWrappers fieldType
-
-handleInputError :: Text -> Position -> InputValidation a -> Validation ()
-handleInputError key position' (Left error') = Left $ argumentGotInvalidValue key (inputErrorMessage error') position'
-handleInputError _ _ _                       = pure ()
-
-validateArgumentValue :: DataTypeLib -> DataField a -> (Text, Argument) -> Validation (Text, Argument)
-validateArgumentValue lib DataField {fieldType, fieldTypeWrappers} arg@(key, Argument {argumentValue, argumentPosition}) =
-  getInputType fieldType lib (internalUnknownTypeMessage fieldType) >>= checkType >> pure arg
-  where
-    checkType type' =
-      handleInputError key argumentPosition (validateInputValue lib [] fieldTypeWrappers type' (key, argumentValue))
+                  where varSignature = renderWrapped variableType variableTypeWrappers
+                        fieldSignature = render fieldT
 
 validateArgument :: DataTypeLib -> Position -> Arguments -> (Text, DataArgument) -> Validation (Text, Argument)
-validateArgument types argumentPosition requestArgs (key, arg) =
+validateArgument lib fieldPosition requestArgs (key, argType@DataField {fieldType = TypeAlias { aliasTyCon
+                                                                                              , aliasWrappers
+                                                                                              }}) =
   case lookup key requestArgs of
     Nothing                                            -> handleNullable
     Just argument@Argument {argumentOrigin = VARIABLE} -> pure (key, argument) -- Variables are already checked in Variable Validation
     Just Argument {argumentValue = Null}               -> handleNullable
-    Just argument                                      -> validateArgumentValue types arg (key, argument)
+    Just argument                                      -> validateArgumentValue argument
   where
     handleNullable
-      | isFieldNullable arg = pure (key, Argument {argumentValue = Null, argumentOrigin = INLINE, argumentPosition})
-      | otherwise = Left $ undefinedArgument (EnhancedKey key argumentPosition)
-
-checkForUnknownArguments :: (Text, DataOutputField) -> Arguments -> Validation [(Text, DataInputField)]
-checkForUnknownArguments (key, DataField {fieldArgs}) args =
-  checkForUnknownKeys enhancedKeys fieldKeys argError >> checkNameCollision enhancedKeys argumentNameCollision >>
-  pure fieldArgs
-  where
-    argError = unknownArguments key
-    enhancedKeys = map argToKey args
-    argToKey (key', Argument {argumentPosition}) = EnhancedKey key' argumentPosition
-    fieldKeys = map fst fieldArgs
+      | isFieldNullable argType =
+        pure (key, Argument {argumentValue = Null, argumentOrigin = INLINE, argumentPosition = fieldPosition})
+      | otherwise = Left $ undefinedArgument (EnhancedKey key fieldPosition)
+    -------------------------------------------------------------------------
+    validateArgumentValue :: Argument -> Validation (Text, Argument)
+    validateArgumentValue arg@Argument {argumentValue, argumentPosition} =
+      getInputType aliasTyCon lib (internalUnknownTypeMessage aliasTyCon) >>= checkType >> pure (key, arg)
+      where
+        checkType type' = handleInputError (validateInputValue lib [] aliasWrappers type' (key, argumentValue))
+        ---------
+        handleInputError :: InputValidation a -> Validation ()
+        handleInputError (Left err) = Left $ argumentGotInvalidValue key (inputErrorMessage err) argumentPosition
+        handleInputError _          = pure ()
 
 validateArguments ::
-     DataTypeLib
-  -> Text
-  -> ValidVariables
-  -> (Text, DataOutputField)
-  -> Position
-  -> RawArguments
-  -> Validation Arguments
-validateArguments typeLib operatorName variables inputs pos rawArgs = do
-  args <- resolveArgumentVariables operatorName variables (snd inputs) rawArgs
-  dataArgs <- checkForUnknownArguments inputs args
+     DataTypeLib -> Text -> ValidVariables -> (Text, DataField) -> Position -> RawArguments -> Validation Arguments
+validateArguments typeLib operatorName variables (key, field@DataField {fieldArgs}) pos rawArgs = do
+  args <- resolveArgumentVariables operatorName variables field rawArgs
+  dataArgs <- checkForUnknownArguments args
   mapM (validateArgument typeLib pos args) dataArgs
+  where
+    checkForUnknownArguments :: Arguments -> Validation [(Text, DataField)]
+    checkForUnknownArguments args =
+      checkForUnknownKeys enhancedKeys fieldKeys argError >> checkNameCollision enhancedKeys argumentNameCollision >>
+      pure fieldArgs
+      where
+        argError = unknownArguments key
+        enhancedKeys = map argToKey args
+        argToKey (key', Argument {argumentPosition}) = EnhancedKey key' argumentPosition
+        fieldKeys = map fst fieldArgs
diff --git a/src/Data/Morpheus/Validation/Query/Input/Object.hs b/src/Data/Morpheus/Validation/Query/Input/Object.hs
--- a/src/Data/Morpheus/Validation/Query/Input/Object.hs
+++ b/src/Data/Morpheus/Validation/Query/Input/Object.hs
@@ -5,63 +5,61 @@
   ( validateInputValue
   ) where
 
-import           Data.Morpheus.Error.Input                  (InputError (..), InputValidation, Prop (..))
-import           Data.Morpheus.Types.Internal.Data          (DataField (..), DataInputType, DataKind (..),
-                                                             DataType (..), DataTypeLib (..), DataTypeWrapper (..),
-                                                             DataValidator (..), showFullAstType)
-import           Data.Morpheus.Types.Internal.Value         (Value (..))
-import           Data.Morpheus.Validation.Query.Input.Enum  (validateEnum)
-import           Data.Morpheus.Validation.Internal.Utils (getInputType, lookupField)
-import           Data.Text                                  (Text)
+import           Data.Morpheus.Error.Input                 (InputError (..), InputValidation, Prop (..))
+import           Data.Morpheus.Rendering.RenderGQL         (renderWrapped)
+import           Data.Morpheus.Types.Internal.Data         (DataField (..), DataKind (..), DataTyCon (..),
+                                                            DataTypeLib (..), DataValidator (..), TypeAlias (..),
+                                                            WrapperD (..), isNullable)
+import           Data.Morpheus.Types.Internal.Value        (Value (..))
+import           Data.Morpheus.Validation.Internal.Utils   (getInputType, lookupField)
+import           Data.Morpheus.Validation.Query.Input.Enum (validateEnum)
+import           Data.Text                                 (Text)
 
 typeMismatch :: Value -> Text -> [Prop] -> InputError
 typeMismatch jsType expected' path' = UnexpectedType path' expected' jsType Nothing
 
 -- Validate Variable Argument or all Possible input Values
-validateInputValue ::
-     DataTypeLib -> [Prop] -> [DataTypeWrapper] -> DataInputType -> (Text, Value) -> InputValidation Value
-validateInputValue lib' prop' = validate
+validateInputValue :: DataTypeLib -> [Prop] -> [WrapperD] -> DataKind -> (Text, Value) -> InputValidation Value
+validateInputValue lib prop' = validate
   where
-    throwError :: [DataTypeWrapper] -> DataInputType -> Value -> InputValidation Value
-    throwError wrappers' type' value' = Left $ UnexpectedType prop' (showFullAstType wrappers' type') value' Nothing
-    {-- VALIDATION --}
-    {-- 1. VALIDATE WRAPPERS -}
-    validate :: [DataTypeWrapper] -> DataInputType -> (Text, Value) -> InputValidation Value
-    -- throw error on not nullable type if value = null
-    validate (NonNullType:wrappers') type' (_, Null) = throwError wrappers' type' Null
-    -- resolves nullable value as null
-    validate _ _ (_, Null) = return Null
-    -- ignores NonNUllTypes if value /= null
-    validate (NonNullType:wrappers') type' value' = validateInputValue lib' prop' wrappers' type' value'
-    {-- VALIDATE LIST -}
-    validate (ListType:wrappers') type' (key', List list') = List <$> mapM validateElement list'
+    throwError :: [WrapperD] -> DataKind -> Value -> InputValidation Value
+    throwError wrappers type' value' = Left $ UnexpectedType prop' (renderWrapped type' wrappers) value' Nothing
+    -- VALIDATION
+    validate :: [WrapperD] -> DataKind -> (Text, Value) -> InputValidation Value
+    -- Validate Null. value = null ?
+    validate wrappers tName (_, Null)
+      | isNullable wrappers = return Null
+      | otherwise = throwError wrappers tName Null
+    -- Validate LIST
+    validate (MaybeD:wrappers) type' value' = validateInputValue lib prop' wrappers type' value'
+    validate (ListD:wrappers) type' (key', List list') = List <$> mapM validateElement list'
       where
-        validateElement element' = validateInputValue lib' prop' wrappers' type' (key', element')
+        validateElement element' = validateInputValue lib prop' wrappers type' (key', element')
     {-- 2. VALIDATE TYPES, all wrappers are already Processed --}
     {-- VALIDATE OBJECT--}
-    validate [] (ObjectKind DataType {typeData = parentFields'}) (_, Object fields) =
+    validate [] (ObjectKind DataTyCon {typeData = parentFields'}) (_, Object fields) =
       Object <$> mapM validateField fields
       where
-        validateField (_name, value') = do
-          (type', currentProp') <- validationData value'
-          wrappers' <- fieldTypeWrappers <$> getField
-          value'' <- validateInputValue lib' currentProp' wrappers' type' (_name, value')
+        validateField (_name, value) = do
+          (type', currentProp') <- validationData value
+          wrappers' <- aliasWrappers . fieldType <$> getField
+          value'' <- validateInputValue lib currentProp' wrappers' type' (_name, value)
           return (_name, value'')
           where
             validationData x = do
-              fieldTypeName' <- fieldType <$> getField
+              fieldTypeName' <- aliasTyCon . fieldType <$> getField
               let currentProp = prop' ++ [Prop _name fieldTypeName']
-              type' <- getInputType fieldTypeName' lib' (typeMismatch x fieldTypeName' currentProp)
+              type' <- getInputType fieldTypeName' lib (typeMismatch x fieldTypeName' currentProp)
               return (type', currentProp)
             getField = lookupField _name parentFields' (UnknownField prop' _name)
     -- VALIDATE INPUT UNION
     -- TODO: Validate Union
-    validate [] (UnionKind DataType {typeData}) (_, Object fields) = return (Object fields)
+    validate [] (UnionKind DataTyCon {typeData}) (_, Object fields) = return (Object fields)
     {-- VALIDATE SCALAR --}
-    validate [] (EnumKind DataType {typeData = tags', typeName = name'}) (_, value') =
+    validate [] (EnumKind DataTyCon {typeData = tags', typeName = name'}) (_, value') =
       validateEnum (UnexpectedType prop' name' value' Nothing) tags' value'
     {-- VALIDATE ENUM --}
-    validate [] (ScalarKind DataType {typeName = name', typeData = DataValidator {validateValue = validator'}}) (_, value') =
+    validate [] (ScalarKind DataTyCon {typeName = name', typeData = DataValidator {validateValue = validator'}}) (_, value') =
       case validator' value' of
         Right _           -> return value'
         Left ""           -> Left $ UnexpectedType prop' name' value' Nothing
diff --git a/src/Data/Morpheus/Validation/Query/Selection.hs b/src/Data/Morpheus/Validation/Query/Selection.hs
--- a/src/Data/Morpheus/Validation/Query/Selection.hs
+++ b/src/Data/Morpheus/Validation/Query/Selection.hs
@@ -16,8 +16,9 @@
                                                                  RawSelection' (..), RawSelectionSet)
 import           Data.Morpheus.Types.Internal.AST.Selection     (Selection (..), SelectionRec (..), SelectionSet)
 import           Data.Morpheus.Types.Internal.Base              (EnhancedKey (..))
-import           Data.Morpheus.Types.Internal.Data              (DataField (..), DataFullType (..), DataOutputObject,
-                                                                 DataType (..), DataTypeLib (..), allDataTypes)
+import           Data.Morpheus.Types.Internal.Data              (DataField (..), DataFullType (..), DataObject,
+                                                                 DataTyCon (..), DataTypeLib (..), TypeAlias (..),
+                                                                 allDataTypes)
 import           Data.Morpheus.Types.Internal.Validation        (Validation)
 import           Data.Morpheus.Validation.Internal.Utils        (checkNameCollision, lookupType)
 import           Data.Morpheus.Validation.Query.Arguments       (validateArguments)
@@ -26,15 +27,15 @@
                                                                  lookupUnionTypes)
 import           Data.Text                                      (Text)
 
-checkDuplicatesOn :: DataOutputObject -> SelectionSet -> Validation SelectionSet
-checkDuplicatesOn DataType {typeName = name'} keys = checkNameCollision enhancedKeys selError >> pure keys
+checkDuplicatesOn :: DataObject -> SelectionSet -> Validation SelectionSet
+checkDuplicatesOn DataTyCon {typeName = name'} keys = checkNameCollision enhancedKeys selError >> pure keys
   where
     selError = duplicateQuerySelections name'
     enhancedKeys = map selToKey keys
     selToKey (key', Selection {selectionPosition = position'}) = EnhancedKey key' position'
 
 clusterUnionSelection ::
-     FragmentLib -> Text -> [DataOutputObject] -> (Text, RawSelection) -> Validation ([Fragment], SelectionSet)
+     FragmentLib -> Text -> [DataObject] -> (Text, RawSelection) -> Validation ([Fragment], SelectionSet)
 clusterUnionSelection fragments type' possibleTypes' = splitFrag
   where
     packFragment fragment = return ([fragment], [])
@@ -55,11 +56,11 @@
     splitFrag (_, InlineFragment fragment') =
       castFragmentType Nothing (fragmentPosition fragment') typeNames fragment' >>= packFragment
 
-categorizeTypes :: [DataOutputObject] -> [Fragment] -> [(DataOutputObject, [Fragment])]
+categorizeTypes :: [DataObject] -> [Fragment] -> [(DataObject, [Fragment])]
 categorizeTypes types fragments = filter notEmpty $ map categorizeType types
   where
     notEmpty = (0 /=) . length . snd
-    categorizeType :: DataOutputObject -> (DataOutputObject, [Fragment])
+    categorizeType :: DataObject -> (DataObject, [Fragment])
     categorizeType datatype = (datatype, filter matches fragments)
       where
         matches fragment = fragmentType fragment == typeName datatype
@@ -79,16 +80,10 @@
  -}
 
 validateSelectionSet ::
-     DataTypeLib
-  -> FragmentLib
-  -> Text
-  -> ValidVariables
-  -> DataOutputObject
-  -> RawSelectionSet
-  -> Validation SelectionSet
+     DataTypeLib -> FragmentLib -> Text -> ValidVariables -> DataObject -> RawSelectionSet -> Validation SelectionSet
 validateSelectionSet lib fragments' operatorName variables = __validate
   where
-    __validate dataType'@DataType {typeName = typeName'} selectionSet' =
+    __validate dataType'@DataTyCon {typeName = typeName'} selectionSet' =
       concat <$> mapM validateSelection selectionSet' >>= checkDuplicatesOn dataType'
       where
         validateFragment Fragment {fragmentSelection = selection'} = __validate dataType' selection'
@@ -109,9 +104,9 @@
           -- check field Type existence  -----
           fieldDataType <-
             lookupType
-              (unknownType (fieldType selectionField) rawSelectionPosition)
+              (unknownType (aliasTyCon $fieldType selectionField) rawSelectionPosition)
               (allDataTypes lib)
-              (fieldType selectionField)
+              (aliasTyCon $ fieldType selectionField)
           return (selectionField, fieldDataType, arguments)
         -- validate single selection: InlineFragments and Spreads will Be resolved and included in SelectionSet
         --
@@ -128,30 +123,30 @@
         validateSelection (key', RawSelectionSet fullRawSelection'@RawSelection' { rawSelectionRec = rawSelectors
                                                                                  , rawSelectionPosition = position'
                                                                                  }) = do
-          (dataField', dataType, arguments) <- getValidationData key' fullRawSelection'
+          (dataField, dataType, arguments) <- getValidationData key' fullRawSelection'
           case dataType of
             Union _ -> do
               (categories, __typename) <- clusterTypes
               mapM (validateCluster __typename) categories >>= returnSelection arguments . UnionSelection
               where clusterTypes = do
-                      unionTypes <- lookupUnionTypes position' key' lib dataField'
+                      unionTypes <- lookupUnionTypes position' key' lib dataField
                       (spreads, __typename) <-
                         flatTuple <$> mapM (clusterUnionSelection fragments' typeName' unionTypes) rawSelectors
                       return (categorizeTypes unionTypes spreads, __typename)
                     --
                     --    second arguments will be added to every selection cluster
-                    validateCluster :: SelectionSet -> (DataOutputObject, [Fragment]) -> Validation (Text, SelectionSet)
+                    validateCluster :: SelectionSet -> (DataObject, [Fragment]) -> Validation (Text, SelectionSet)
                     validateCluster sysSelection' (type', frags') = do
                       selection' <- __validate type' (concatMap fragmentSelection frags')
                       return (typeName type', sysSelection' ++ selection')
             OutputObject _ -> do
-              fieldType' <- lookupFieldAsSelectionSet position' key' lib dataField'
+              fieldType' <- lookupFieldAsSelectionSet position' key' lib dataField
               __validate fieldType' rawSelectors >>= returnSelection arguments . SelectionSet
                  -- DataFullType
                        --   = Leaf DataLeaf
                        --   | InputObject DataInputObject
                        --   | InputUnion DataUnion
-            _ -> Left $ hasNoSubfields key' (fieldType dataField') position'
+            _ -> Left $ hasNoSubfields key' (aliasTyCon $fieldType dataField) position'
           where
             returnSelection arguments' selection' =
               pure
@@ -159,20 +154,21 @@
                   , Selection
                       {selectionArguments = arguments', selectionRec = selection', selectionPosition = position'})
                 ]
-        validateSelection (key', RawSelectionField fullRawSelection'@RawSelection' {rawSelectionPosition}) = do
-          (dataField, datatype, arguments') <- getValidationData key' fullRawSelection'
+        validateSelection (key, RawSelectionField fullRawSelection'@RawSelection' {rawSelectionPosition}) = do
+          (dataField, datatype, arguments) <- getValidationData key fullRawSelection'
           isLeaf datatype dataField
           pure
-            [ ( key'
+            [ ( key
               , Selection
-                  { selectionArguments = arguments'
+                  { selectionArguments = arguments
                   , selectionRec = SelectionField
                   , selectionPosition = rawSelectionPosition
                   })
             ]
           where
-            isLeaf (Leaf _) _              = Right ()
-            isLeaf _ DataField {fieldType} = Left $ subfieldsNotSelected key' fieldType rawSelectionPosition
+            isLeaf (Leaf _) _ = Right ()
+            isLeaf _ DataField {fieldType = TypeAlias {aliasTyCon}} =
+              Left $ subfieldsNotSelected key aliasTyCon rawSelectionPosition
         validateSelection (_, Spread reference') = resolveSpread fragments' [typeName'] reference' >>= validateFragment
         validateSelection (_, InlineFragment fragment') =
           castFragmentType Nothing (fragmentPosition fragment') [typeName'] fragment' >>= validateFragment
diff --git a/src/Data/Morpheus/Validation/Query/Utils/Selection.hs b/src/Data/Morpheus/Validation/Query/Utils/Selection.hs
--- a/src/Data/Morpheus/Validation/Query/Utils/Selection.hs
+++ b/src/Data/Morpheus/Validation/Query/Utils/Selection.hs
@@ -1,3 +1,5 @@
+{-# LANGUAGE NamedFieldPuns #-}
+
 module Data.Morpheus.Validation.Query.Utils.Selection
   ( lookupFieldAsSelectionSet
   , lookupSelectionField
@@ -6,24 +8,25 @@
 
 import           Data.Morpheus.Error.Selection           (cannotQueryField, hasNoSubfields)
 import           Data.Morpheus.Types.Internal.Base       (Position)
-import           Data.Morpheus.Types.Internal.Data       (DataField (..), DataOutputField, DataOutputObject,
-                                                          DataType (..), DataTypeLib (..))
+import           Data.Morpheus.Types.Internal.Data       (DataField (..), DataObject, DataTyCon (..), DataTypeLib (..),
+                                                          TypeAlias (..))
 import           Data.Morpheus.Types.Internal.Validation (Validation)
 import           Data.Morpheus.Validation.Internal.Utils (lookupField, lookupType)
 import           Data.Text                               (Text)
 
-lookupUnionTypes :: Position -> Text -> DataTypeLib -> DataOutputField -> Validation [DataOutputObject]
-lookupUnionTypes position' key' lib' DataField {fieldType = type'} =
-  lookupType error' (union lib') type' >>= mapM (lookupType error' (object lib') . fieldType) . typeData
+lookupUnionTypes :: Position -> Text -> DataTypeLib -> DataField -> Validation [DataObject]
+lookupUnionTypes position' key' lib DataField {fieldType = TypeAlias {aliasTyCon = type'}} =
+  lookupType error' (union lib) type' >>= mapM (lookupType error' (object lib) . aliasTyCon . fieldType) . typeData
   where
     error' = hasNoSubfields key' type' position'
 
-lookupFieldAsSelectionSet :: Position -> Text -> DataTypeLib -> DataOutputField -> Validation DataOutputObject
-lookupFieldAsSelectionSet position' key' lib' DataField {fieldType = type'} = lookupType error' (object lib') type'
+lookupFieldAsSelectionSet :: Position -> Text -> DataTypeLib -> DataField -> Validation DataObject
+lookupFieldAsSelectionSet position key' lib DataField {fieldType = TypeAlias {aliasTyCon = type'}} =
+  lookupType error' (object lib) type'
   where
-    error' = hasNoSubfields key' type' position'
+    error' = hasNoSubfields key' type' position
 
-lookupSelectionField :: Position -> Text -> DataOutputObject -> Validation DataOutputField
-lookupSelectionField position' key' DataType {typeData = fields', typeName = name'} = lookupField key' fields' error'
+lookupSelectionField :: Position -> Text -> DataObject -> Validation DataField
+lookupSelectionField position' key' DataTyCon {typeData = fields', typeName = name'} = lookupField key' fields' error'
   where
     error' = cannotQueryField key' name' position'
diff --git a/src/Data/Morpheus/Validation/Query/Validation.hs b/src/Data/Morpheus/Validation/Query/Validation.hs
--- a/src/Data/Morpheus/Validation/Query/Validation.hs
+++ b/src/Data/Morpheus/Validation/Query/Validation.hs
@@ -10,9 +10,8 @@
 import           Data.Map                                   (fromList)
 import           Data.Morpheus.Error.Mutation               (mutationIsNotDefined)
 import           Data.Morpheus.Error.Subscription           (subscriptionIsNotDefined)
-import           Data.Morpheus.Types.Internal.AST.Operation (Operation (..), OperationKind (..), RawOperation,
-                                                             ValidOperation)
-import           Data.Morpheus.Types.Internal.Data          (DataOutputObject, DataTypeLib (..))
+import           Data.Morpheus.Types.Internal.AST.Operation (Operation (..), RawOperation, ValidOperation)
+import           Data.Morpheus.Types.Internal.Data          (DataObject, DataTypeLib (..), OperationKind (..))
 import           Data.Morpheus.Types.Internal.Validation    (Validation)
 import           Data.Morpheus.Types.Types                  (GQLQueryRoot (..))
 import           Data.Morpheus.Validation.Internal.Utils    (VALIDATION_MODE)
@@ -20,13 +19,13 @@
 import           Data.Morpheus.Validation.Query.Selection   (validateSelectionSet)
 import           Data.Morpheus.Validation.Query.Variable    (resolveOperationVariables)
 
-getOperationDataType :: RawOperation -> DataTypeLib -> Validation DataOutputObject
-getOperationDataType Operation {operationKind = QUERY} lib = pure $ snd $ query lib
-getOperationDataType Operation {operationKind = MUTATION, operationPosition} lib =
+getOperationDataType :: RawOperation -> DataTypeLib -> Validation DataObject
+getOperationDataType Operation {operationKind = Query} lib = pure $ snd $ query lib
+getOperationDataType Operation {operationKind = Mutation, operationPosition} lib =
   case mutation lib of
     Just (_, mutation') -> pure mutation'
     Nothing             -> Left $ mutationIsNotDefined operationPosition
-getOperationDataType Operation {operationKind = SUBSCRIPTION, operationPosition} lib =
+getOperationDataType Operation {operationKind = Subscription, operationPosition} lib =
   case subscription lib of
     Just (_, subscription') -> pure subscription'
     Nothing                 -> Left $ subscriptionIsNotDefined operationPosition
diff --git a/src/Data/Morpheus/Validation/Query/Variable.hs b/src/Data/Morpheus/Validation/Query/Variable.hs
--- a/src/Data/Morpheus/Validation/Query/Variable.hs
+++ b/src/Data/Morpheus/Validation/Query/Variable.hs
@@ -16,7 +16,7 @@
                                                                 RawSelection (..), RawSelection' (..), RawSelectionSet,
                                                                 Reference (..))
 import           Data.Morpheus.Types.Internal.Base             (EnhancedKey (..), Position)
-import           Data.Morpheus.Types.Internal.Data             (DataInputType, DataTypeLib)
+import           Data.Morpheus.Types.Internal.Data             (DataKind, DataTypeLib)
 import           Data.Morpheus.Types.Internal.Validation       (Validation)
 import           Data.Morpheus.Types.Internal.Value            (Value (..))
 import           Data.Morpheus.Types.Types                     (Variables)
@@ -26,7 +26,7 @@
 import           Data.Semigroup                                ((<>))
 import           Data.Text                                     (Text)
 
-getVariableType :: Text -> Position -> DataTypeLib -> Validation DataInputType
+getVariableType :: Text -> Position -> DataTypeLib -> Validation DataKind
 getVariableType type' position' lib' = getInputType type' lib' error'
   where
     error' = unknownType type' position'
diff --git a/test/Feature/Holistic/API.gql b/test/Feature/Holistic/API.gql
--- a/test/Feature/Holistic/API.gql
+++ b/test/Feature/Holistic/API.gql
@@ -1,5 +1,3 @@
-scalar TestScalar
-
 enum TestEnum {
   EnumA
   EnumB
@@ -15,6 +13,11 @@
   fieldNestedInputObject: [NestedInputObject]!
 }
 
+input Coordinates {
+  latitude: TestScalar!
+  longitude: Int!
+}
+
 type Address {
   city: String!
   street(
@@ -24,21 +27,25 @@
   houseNumber: Int!
 }
 
+union TestUnion = User | Address
+
 type User {
-  name(id: ID!): String!
+  name: String!
   email: String!
-  address: Address
-  testEnum: TestEnum
+  address(coordinates: Coordinates!, comment: String): Address!
+  office(zipCode: [Int!], cityID: TestEnum!): Address!
+  friend: User
 }
 
-union TestUnion = User | Address
-
 type Query {
   user: User!
-  myUnion: TestUnion!
-  fieldID: ID!
+  testUnion: TestUnion
 }
 
 type Mutation {
-  createUser: User!
+  createUser(userID: String!, userName: String!): User!
+}
+
+type Subscription {
+  newUser: User!
 }
diff --git a/test/Feature/Holistic/API.hs b/test/Feature/Holistic/API.hs
--- a/test/Feature/Holistic/API.hs
+++ b/test/Feature/Holistic/API.hs
@@ -1,32 +1,30 @@
-{-# LANGUAGE DeriveGeneric     #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE TypeFamilies      #-}
-{-# LANGUAGE TypeOperators     #-}
+{-# LANGUAGE DeriveGeneric         #-}
+{-# LANGUAGE DerivingStrategies    #-}
+{-# LANGUAGE FlexibleContexts      #-}
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE NamedFieldPuns        #-}
+{-# LANGUAGE OverloadedStrings     #-}
+{-# LANGUAGE ScopedTypeVariables   #-}
+{-# LANGUAGE TemplateHaskell       #-}
+{-# LANGUAGE TypeFamilies          #-}
 
 module Feature.Holistic.API
   ( api
   ) where
 
-import           Data.Morpheus       (interpreter)
-import           Data.Morpheus.Kind  (ENUM, INPUT_OBJECT, OBJECT, SCALAR, UNION)
-import           Data.Morpheus.Types (Event (..), GQLRequest, GQLResponse, GQLRootResolver (..), GQLScalar (..),
-                                      GQLType (..), ID (..), IORes, IOSubRes, ScalarValue (..))
-import           Data.Text           (Text)
-import           GHC.Generics        (Generic)
-
-data TestEnum
-  = EnumA
-  | EnumB
-  | EnumC
-  deriving (Generic)
-
-instance GQLType TestEnum where
-  type KIND TestEnum = ENUM
+import           Data.Morpheus          (interpreter)
+import           Data.Morpheus.Document (importGQLDocument)
+import           Data.Morpheus.Kind     (SCALAR)
+import           Data.Morpheus.Types    (GQLRequest, GQLResponse, GQLRootResolver (..), GQLScalar (..), GQLType (..),
+                                         ID (..), IOMutRes, IORes, IOSubRes, ScalarValue (..), SubResolver (..))
+import           Data.Text              (Text)
+import           GHC.Generics           (Generic)
 
 data TestScalar =
   TestScalar Int
              Int
-  deriving (Generic)
+  deriving (Show, Generic)
 
 instance GQLType TestScalar where
   type KIND TestScalar = SCALAR
@@ -35,106 +33,37 @@
   parseValue _ = pure (TestScalar 1 0)
   serialize (TestScalar x y) = Int (x * 100 + y)
 
-newtype NestedInputObject = NestedInputObject
-  { fieldTestID :: ID
-  } deriving (Generic)
-
-instance GQLType NestedInputObject where
-  type KIND NestedInputObject = INPUT_OBJECT
-
-data TestInputObject = TestInputObject
-  { fieldTestScalar        :: TestScalar
-  , fieldNestedInputObject :: [Maybe NestedInputObject]
-  } deriving (Generic)
-
-instance GQLType TestInputObject where
-  type KIND TestInputObject = INPUT_OBJECT
-
-data StreetArgs = StreetArgs
-  { argInputObject :: TestInputObject
-  , argMaybeString :: Maybe Text
-  } deriving (Generic)
-
-data Address = Address
-  { city        :: Text
-  , street      :: StreetArgs -> IORes (Maybe [Maybe [[[Text]]]])
-  , houseNumber :: Int
-  } deriving (Generic)
-
-instance GQLType Address where
-  type KIND Address = OBJECT
-
-data TestUnion
-  = UnionA User
-  | UnionB Address
-  deriving (Generic)
-
-instance GQLType TestUnion where
-  type KIND TestUnion = UNION
-
-data Coordinates = Coordinates
-  { latitude  :: TestScalar
-  , longitude :: Int
-  } deriving (Generic)
-
-instance GQLType Coordinates where
-  type KIND Coordinates = INPUT_OBJECT
-
-data AddressArgs = AddressArgs
-  { coordinates :: Coordinates
-  , comment     :: Maybe Text
-  } deriving (Generic)
-
-data OfficeArgs = OfficeArgs
-  { zipCode :: Maybe [Int]
-  , cityID  :: TestEnum
-  } deriving (Generic)
-
-data User = User
-  { name    :: Text
-  , email   :: Text
-  , address :: AddressArgs -> IORes Address
-  , office  :: OfficeArgs -> IORes Address
-  , friend  :: () -> IORes (Maybe User)
-  } deriving (Generic)
-
-instance GQLType User where
-  type KIND User = OBJECT
-  description = const "Custom Description for Client Defined User Type"
-
-data Query = Query
-  { user      :: () -> IORes User
-  , testUnion :: Maybe TestUnion
-  } deriving (Generic)
-
-newtype Mutation = Mutation
-  { createUser :: AddressArgs -> IORes User
-  } deriving (Generic)
-
 data EVENT =
   EVENT
   deriving (Show, Eq)
 
-newtype Subscription = Subscription
-  { newUser :: AddressArgs -> IOSubRes EVENT () User
-  } deriving (Generic)
-
-resolveAddress :: a -> IORes Address
-resolveAddress _ = return Address {city = "", houseNumber = 0, street = const $ return Nothing}
+importGQLDocument "test/Feature/Holistic/API.gql"
 
-resolveUser :: a -> IORes User
-resolveUser _ =
-  return $
-  User
-    {name = "testName", email = "", address = resolveAddress, office = resolveAddress, friend = const $ return Nothing}
+resolveValue :: Monad m => b -> a -> m b
+resolveValue = const . return
 
-rootResolver :: GQLRootResolver IO EVENT () Query Mutation Subscription
+rootResolver ::
+     GQLRootResolver IO EVENT () (Query IORes) (Mutation (IOMutRes EVENT ())) (Subscription (IOSubRes EVENT ()))
 rootResolver =
   GQLRootResolver
-    { queryResolver = return Query {user = resolveUser, testUnion = Nothing}
-    , mutationResolver = return Mutation {createUser = resolveUser}
-    , subscriptionResolver = return Subscription {newUser = const $ Event [EVENT] resolveUser}
+    { queryResolver = return Query {user, testUnion = const $ return Nothing}
+    , mutationResolver = return Mutation {createUser = user}
+    , subscriptionResolver =
+        return Subscription {newUser = const SubResolver {subChannels = [EVENT], subResolver = user}}
     }
+  where
+    user _ =
+      return $
+      User
+        { name = resolveValue "testName"
+        , email = resolveValue ""
+        , address = resolveAddress
+        , office = resolveAddress
+        , friend = resolveValue Nothing
+        }
+      where
+        resolveAddress _ =
+          return Address {city = resolveValue "", houseNumber = resolveValue 0, street = resolveValue Nothing}
 
 api :: GQLRequest -> IO GQLResponse
 api = interpreter rootResolver
diff --git a/test/Feature/Input/Enum/API.hs b/test/Feature/Input/Enum/API.hs
--- a/test/Feature/Input/Enum/API.hs
+++ b/test/Feature/Input/Enum/API.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE DeriveAnyClass #-}
 {-# LANGUAGE DeriveGeneric  #-}
 {-# LANGUAGE NamedFieldPuns #-}
 {-# LANGUAGE TypeFamilies   #-}
@@ -56,7 +57,7 @@
   { test  :: TestArgs Level -> IORes Level
   , test2 :: TestArgs TwoCon -> IORes TwoCon
   , test3 :: TestArgs ThreeCon -> IORes ThreeCon
-  } deriving (Generic)
+  } deriving (Generic, GQLType)
 
 rootResolver :: GQLRootResolver IO () () Query () ()
 rootResolver =
diff --git a/test/Feature/InputType/API.hs b/test/Feature/InputType/API.hs
--- a/test/Feature/InputType/API.hs
+++ b/test/Feature/InputType/API.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE DeriveAnyClass    #-}
 {-# LANGUAGE DeriveGeneric     #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE TypeFamilies      #-}
@@ -33,7 +34,7 @@
 
 newtype Query = Query
   { q1 :: A
-  } deriving (Generic)
+  } deriving (Generic, GQLType)
 
 rootResolver :: GQLRootResolver IO () () Query () ()
 rootResolver =
diff --git a/test/Feature/InputType/variables/invalidValue/invalidListVariable/response.json b/test/Feature/InputType/variables/invalidValue/invalidListVariable/response.json
--- a/test/Feature/InputType/variables/invalidValue/invalidListVariable/response.json
+++ b/test/Feature/InputType/variables/invalidValue/invalidListVariable/response.json
@@ -1,7 +1,7 @@
 {
   "errors": [
     {
-      "message": "Variable \"$v1\" got invalid value;  Expected type \"String\" found null.",
+      "message": "Variable \"$v1\" got invalid value;  Expected type \"String!\" found null.",
       "locations": [
         {
           "line": 1,
diff --git a/test/Feature/InputType/variables/invalidValue/nestedListNonNullListReceivedNull/response.json b/test/Feature/InputType/variables/invalidValue/nestedListNonNullListReceivedNull/response.json
--- a/test/Feature/InputType/variables/invalidValue/nestedListNonNullListReceivedNull/response.json
+++ b/test/Feature/InputType/variables/invalidValue/nestedListNonNullListReceivedNull/response.json
@@ -1,7 +1,7 @@
 {
   "errors": [
     {
-      "message": "Variable \"$v1\" got invalid value;  Expected type \"[Int!]\" found null.",
+      "message": "Variable \"$v1\" got invalid value;  Expected type \"[Int!]!\" found null.",
       "locations": [
         {
           "line": 1,
diff --git a/test/Feature/Schema/API.hs b/test/Feature/Schema/API.hs
--- a/test/Feature/Schema/API.hs
+++ b/test/Feature/Schema/API.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE DeriveAnyClass    #-}
 {-# LANGUAGE DeriveGeneric     #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE TypeFamilies      #-}
@@ -25,7 +26,7 @@
 data Query = Query
   { a1 :: A
   , a2 :: A2.A
-  } deriving (Generic)
+  } deriving (Generic, GQLType)
 
 rootResolver :: GQLRootResolver IO () () Query () ()
 rootResolver =
diff --git a/test/Feature/UnionType/API.hs b/test/Feature/UnionType/API.hs
--- a/test/Feature/UnionType/API.hs
+++ b/test/Feature/UnionType/API.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE DeriveAnyClass    #-}
 {-# LANGUAGE DeriveGeneric     #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE TypeFamilies      #-}
@@ -48,7 +49,7 @@
 data Query = Query
   { union :: () -> IORes [AOrB]
   , fc    :: C
-  } deriving (Generic)
+  } deriving (Generic, GQLType)
 
 resolveUnion :: () -> IORes [AOrB]
 resolveUnion _ = return [A' A {aText = "at", aInt = 1}, B' B {bText = "bt", bInt = 2}]
diff --git a/test/Feature/WrappedTypeName/API.hs b/test/Feature/WrappedTypeName/API.hs
--- a/test/Feature/WrappedTypeName/API.hs
+++ b/test/Feature/WrappedTypeName/API.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE DeriveAnyClass    #-}
 {-# LANGUAGE DeriveGeneric     #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE TypeFamilies      #-}
@@ -9,8 +10,8 @@
 
 import           Data.Morpheus       (interpreter)
 import           Data.Morpheus.Kind  (OBJECT)
-import           Data.Morpheus.Types (Event (..), GQLRequest, GQLResponse, GQLRootResolver (..), GQLType (..), IOMutRes,
-                                      IORes, IOSubRes)
+import           Data.Morpheus.Types (GQLRequest, GQLResponse, GQLRootResolver (..), GQLType (..), IOMutRes, IORes,
+                                      IOSubRes, SubResolver (..))
 import           Data.Text           (Text)
 import           Data.Typeable       (Typeable)
 import           GHC.Generics        (Generic)
@@ -35,13 +36,13 @@
   { a1 :: WA IORes
   , a2 :: Maybe (Wrapped Int Int)
   , a3 :: Maybe (Wrapped (Wrapped Text Int) Text)
-  } deriving (Generic)
+  } deriving (Generic, GQLType)
 
 data Mutation = Mutation
   { mut1 :: Maybe (WA (IOMutRes EVENT ()))
   , mut2 :: Maybe (Wrapped Int Int)
   , mut3 :: Maybe (Wrapped (Wrapped Text Int) Text)
-  } deriving (Generic)
+  } deriving (Generic, GQLType)
 
 data EVENT =
   EVENT
@@ -51,7 +52,7 @@
   { sub1 :: () -> IOSubRes EVENT () (Maybe (WA IORes))
   , sub2 :: () -> IOSubRes EVENT () (Maybe (Wrapped Int Int))
   , sub3 :: () -> IOSubRes EVENT () (Maybe (Wrapped (Wrapped Text Int) Text))
-  } deriving (Generic)
+  } deriving (Generic, GQLType)
 
 rootResolver :: GQLRootResolver IO EVENT () Query Mutation Subscription
 rootResolver =
@@ -61,9 +62,9 @@
     , subscriptionResolver =
         return
           Subscription
-            { sub1 = const $ Event [EVENT] (const $ return Nothing)
-            , sub2 = const $ Event [EVENT] (const $ return Nothing)
-            , sub3 = const $ Event [EVENT] (const $ return Nothing)
+            { sub1 = const SubResolver {subChannels = [EVENT], subResolver = const $ return Nothing}
+            , sub2 = const SubResolver {subChannels = [EVENT], subResolver = const $ return Nothing}
+            , sub3 = const SubResolver {subChannels = [EVENT], subResolver = const $ return Nothing}
             }
     }
 
diff --git a/test/Lib.hs b/test/Lib.hs
--- a/test/Lib.hs
+++ b/test/Lib.hs
@@ -12,7 +12,6 @@
 import qualified Data.ByteString.Lazy       as L (readFile)
 import           Data.ByteString.Lazy.Char8 (ByteString)
 import           Data.Maybe                 (fromMaybe)
-import           Data.Morpheus.Types        (GQLResponse (..))
 import           Data.Text                  (Text, unpack)
 
 path :: Text -> String
