diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -29,7 +29,7 @@
 resolver: lts-14.8
 
 extra-deps:
-  - morpheus-graphql-0.6.2
+  - morpheus-graphql-0.7.0
 ```
 
 As Morpheus is quite new, make sure stack can find morpheus-graphql by running `stack upgrade` and `stack update`
@@ -45,9 +45,15 @@
   deity(name: String!): Deity!
 }
 
+"""
+Description for Deity
+"""
 type Deity {
+  """
+  Description for name
+  """
   name: String!
-  power: String
+  power: String String! @deprecated(reason: "some reason for")
 }
 ```
 
@@ -95,6 +101,8 @@
 
 Template Haskell Generates types: `Query` , `Deity`, `DeityArgs`, that can be used by `rootResolver`
 
+`descriptions` and `deprecations` will be displayed in intropsection.
+
 `importGQLDocumentWithNamespace` will generate Types with namespaced fields. if you don't need napespacing use `importGQLDocument`
 
 ### with Native Haskell Types
@@ -138,7 +146,7 @@
 
 ```haskell
 resolveDeity :: DeityArgs -> IORes e Deity
-resolveDeity DeityArgs { name, mythology } = liftEitherM $ dbDeity name mythology
+resolveDeity DeityArgs { name, mythology } = liftEither $ dbDeity name mythology
 
 askDB :: Text -> Maybe Text -> IO (Either String Deity)
 askDB = ...
@@ -281,25 +289,23 @@
 ### Mutations
 
 In addition to queries, Morpheus also supports mutations. The behave just like regular queries and are defined similarly:
-Just exchange deriving `GQLQuery` for `GQLMutation` and declare them separately at the `GQLRootResolver` definition
 
 ```haskell
 newtype Mutation m = Mutation
-  { createDeity :: Form -> m Deity
+  { createDeity :: MutArgs -> m Deity
   } deriving (Generic, GQLType)
 
-createDeityMutation :: Form -> m (Deity m)
-createDeityMutation = ...
-
-rootResolver :: GQLRootResolver IO Query Mutation Undefined
+rootResolver :: GQLRootResolver IO  () Query Mutation Undefined
 rootResolver =
   GQLRootResolver
     { queryResolver = Query {...}
-    , mutationResolver = Mutation {
-       createDeity = createDeityMutation
-    }
+    , mutationResolver = Mutation { createDeity }
     , subscriptionResolver = Undefined
     }
+    where
+      -- Mutation Without Event Triggering
+      createDeity :: MutArgs -> ResolveM () IO Deity
+      createDeity_args = lift setDBAddress
 
 gqlApi :: ByteString -> IO ByteString
 gqlApi = interpreter rootResolver
@@ -321,6 +327,8 @@
   = ContentA Int
   | ContentB Text
 
+type MyEvent = Event Channel Content
+
 newtype Query m = Query
   { deity :: () -> m Deity
   } deriving (Generic)
@@ -329,29 +337,33 @@
   { createDeity :: () -> m Deity
   } deriving (Generic)
 
-newtype Subscription m = Subscription
+newtype Subscription (m ::  * -> * ) = Subscription
   { newDeity :: () -> m  Deity
   } deriving (Generic)
 
 type APIEvent = Event Channel Content
 
 rootResolver :: GQLRootResolver IO APIEvent Query Mutation Subscription
-rootResolver =
-  GQLRootResolver
-    { queryResolver = Query {deity = const fetchDeity}
-    , mutationResolver = Mutation {createDeity}
-    , subscriptionResolver = Subscription {newDeity}
-    }
-  where
-    createDeity _args = MutResolver events updateDeity
-        where
-        events = [Event {channels = [ChannelA], content = ContentA 1}]
-        updateDeity = updateDBDeity
-    newDeity _args = SubResolver [ChannelA] subResolver
-      where
-        subResolver (Event [ChannelA] (ContentA _value)) = fetchDeity  -- resolve New State
-        subResolver (Event [ChannelA] (ContentB _value)) = fetchDeity   -- resolve New State
-        subResolver _                                    = fetchDeity -- Resolve Old State
+rootResolver = GQLRootResolver
+  { queryResolver        = Query { deity }
+  , mutationResolver     = Mutation { createDeity }
+  , subscriptionResolver = Subscription { newDeity }
+  }
+ where
+  deity _args = fetchDeity
+  -- Mutation Without Event Triggering
+  createDeity :: () -> ResolveM EVENT IO Address
+  createDeity _args = MutResolver \$ do
+      value <- lift dbCreateDeity
+      pure (
+        [Event { channels = [ChannelA], content = ContentA 1 }],
+        value
+      )
+  newDeity _args = SubResolver [ChannelA] subResolver
+   where
+    subResolver (Event [ChannelA] (ContentA _value)) = fetchDeity  -- resolve New State
+    subResolver (Event [ChannelA] (ContentB _value)) = fetchDeity   -- resolve New State
+    subResolver _ = fetchDeity -- Resolve Old State
 ```
 
 ## Morpheus `GraphQL Client` with Template haskell QuasiQuotes
diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,3 +1,136 @@
+## [0.7.0] - 24.11.2019
+
+## Removed
+
+- `toMorpheusHaskellAPi` from `Data.Morpheus.Document` functionality will be migrated in `morpheus-graphql-cli`
+
+## Changed
+
+- `liftM` to `MonadTrans` instance method `lift`
+
+- `liftEitherM` to `liftEither`
+
+- `Resolver operation m event value` -> `Resolver operation event m value` , monad trans needs that last 2 type arguments are monad and value that why it was necessary
+
+- exposed `Data.Morpheus.Types.Internal.AST`
+
+- Mutation Resolver was changed from
+
+```
+resolver :: () -> ResolveM EVENT IO Address
+resolver = MutResolver  {
+  mutEvents = [someEventForSubscription],
+  mutResolver = lift setDBAddress
+}
+```
+
+```haskell
+-- Mutation Wit Event Triggering : sends events to subscription
+resolver :: () -> ResolveM EVENT IO Address
+resolver = MutResolver \$ do
+  value <- lift setDBAddress
+  pure ([someEventForSubscription], value)
+-- or
+-- Mutation Without Event Triggering
+resolver :: () -> ResolveM EVENT IO Address
+resolver _args = lift setDBAddress
+```
+
+### Added
+
+- added `parseDSL` to `Data.Morpheus.Document`
+
+- GraphQL SDL support fully supports descriptions: onTypes, fields , args ...
+  with (enums, inputObjects , union, object)
+  for example :
+
+  ```gql
+  """
+  Description for Type Address
+  """
+  type Address {
+    """
+    Description for Field city
+    """
+    city: String!
+    street(
+      """
+      Description argument id
+      """
+      id: ID!
+    ): Int!
+  }
+  ```
+
+  ###### GraphQL SDL
+
+  ```gql
+  type User {
+    name: String! @deprecated(reason: "some reason")
+  }
+  ```
+
+  will displayed in introspection
+
+  ###### introspection.json
+
+  ```json
+  {
+    "data": {
+      "__type": {
+        "fields": [
+          {
+            "name": "city",
+            "isDeprecated": true,
+            "deprecationReason": "test deprecation field with reason"
+          }
+        ]
+      }
+    }
+  }
+  ```
+
+- basic support of directive `@deprecated` on `enumValue` and object `field`, only on introspection
+
+- GraphQL Client deprecation warnings
+
+  on type
+
+  ```gql
+  type Human {
+    humanName: String!
+    lifetime: Lifetime! @deprecated(reason: "some reason")
+    profession: Profession
+  }
+  ```
+
+  compiler output:
+
+  ```
+  warning:
+    Morpheus Client Warning:
+    {
+      "message":"the field \"Human.lifetime\" is deprecated. some reason",
+      "locations":[{"line":24,"column":15}]
+    }
+  ```
+
+- new helper resolver types aliases:
+
+  - ResolveQ : for Query
+  - ResolveM : for Mutation
+  - ResolveS : for Subscription
+
+  `ResolveM EVENT IO Address` is same as `MutRes EVENT IO (Address (MutRes EVENT IO))`
+
+  is helpfull wenn you want to resolve GraphQL object
+
+### Fixed
+
+- added missing Monad instance for Mutation resolver
+- `defineByIntrospectionFile` does not breaks if schema contains interfaces
+- Morpheus Client supports `Subscription` and `Mutation`operations
+
 ## [0.6.2] - 2.11.2019
 
 ## Added
diff --git a/morpheus-graphql.cabal b/morpheus-graphql.cabal
--- a/morpheus-graphql.cabal
+++ b/morpheus-graphql.cabal
@@ -4,10 +4,10 @@
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: 6d77e1db039ce6a4a5ef7761d0b18beb9ea7067fbb99372bd3a97510e4da4a43
+-- hash: a97de9ffea5713a01a84ffef6bd7ee41104d3d898f2d6a90ae0ef0be27ba7568
 
 name:           morpheus-graphql
-version:        0.6.2
+version:        0.7.0
 synopsis:       Morpheus GraphQL
 description:    Build GraphQL APIs with your favourite functional language!
 category:       web, graphql
@@ -23,7 +23,6 @@
     changelog.md
     README.md
 data-files:
-    test/Feature/Holistic/API.gql
     test/Feature/Holistic/arguments/nameConflict/query.gql
     test/Feature/Holistic/arguments/undefinedArgument/query.gql
     test/Feature/Holistic/arguments/unknownArguments/query.gql
@@ -39,6 +38,12 @@
     test/Feature/Holistic/introspection/defaultTypes/ID/query.gql
     test/Feature/Holistic/introspection/defaultTypes/Int/query.gql
     test/Feature/Holistic/introspection/defaultTypes/String/query.gql
+    test/Feature/Holistic/introspection/deprecated/enumValue/query.gql
+    test/Feature/Holistic/introspection/deprecated/field/query.gql
+    test/Feature/Holistic/introspection/description/enum/query.gql
+    test/Feature/Holistic/introspection/description/inputObject/query.gql
+    test/Feature/Holistic/introspection/description/object/query.gql
+    test/Feature/Holistic/introspection/description/union/query.gql
     test/Feature/Holistic/introspection/kinds/ENUM/query.gql
     test/Feature/Holistic/introspection/kinds/INPUT_OBJECT/query.gql
     test/Feature/Holistic/introspection/kinds/OBJECT/query.gql
@@ -68,6 +73,7 @@
     test/Feature/Holistic/parsing/missingCloseBrace/query.gql
     test/Feature/Holistic/parsing/notNullSpacing/query.gql
     test/Feature/Holistic/parsing/singleLineComments/query.gql
+    test/Feature/Holistic/schema.gql
     test/Feature/Holistic/selection/AliasNameConflict/query.gql
     test/Feature/Holistic/selection/AliasResolve/query.gql
     test/Feature/Holistic/selection/AliasUnknownField/query.gql
@@ -133,6 +139,12 @@
     test/Feature/Holistic/introspection/defaultTypes/ID/response.json
     test/Feature/Holistic/introspection/defaultTypes/Int/response.json
     test/Feature/Holistic/introspection/defaultTypes/String/response.json
+    test/Feature/Holistic/introspection/deprecated/enumValue/response.json
+    test/Feature/Holistic/introspection/deprecated/field/response.json
+    test/Feature/Holistic/introspection/description/enum/response.json
+    test/Feature/Holistic/introspection/description/inputObject/response.json
+    test/Feature/Holistic/introspection/description/object/response.json
+    test/Feature/Holistic/introspection/description/union/response.json
     test/Feature/Holistic/introspection/kinds/ENUM/response.json
     test/Feature/Holistic/introspection/kinds/INPUT_OBJECT/response.json
     test/Feature/Holistic/introspection/kinds/OBJECT/response.json
@@ -242,6 +254,7 @@
       Data.Morpheus.Server
       Data.Morpheus.Document
       Data.Morpheus.Client
+      Data.Morpheus.Types.Internal.AST
   other-modules:
       Data.Morpheus.Error.Arguments
       Data.Morpheus.Error.Client.Client
@@ -269,7 +282,6 @@
       Data.Morpheus.Execution.Document.Introspect
       Data.Morpheus.Execution.Internal.Declare
       Data.Morpheus.Execution.Internal.Decode
-      Data.Morpheus.Execution.Internal.GraphScanner
       Data.Morpheus.Execution.Internal.Utils
       Data.Morpheus.Execution.Server.Decode
       Data.Morpheus.Execution.Server.Encode
@@ -281,7 +293,6 @@
       Data.Morpheus.Execution.Subscription.ClientRegister
       Data.Morpheus.Parsing.Document.Parser
       Data.Morpheus.Parsing.Document.TypeSystem
-      Data.Morpheus.Parsing.Internal.Create
       Data.Morpheus.Parsing.Internal.Internal
       Data.Morpheus.Parsing.Internal.Pattern
       Data.Morpheus.Parsing.Internal.Terms
@@ -292,30 +303,23 @@
       Data.Morpheus.Parsing.Request.Operation
       Data.Morpheus.Parsing.Request.Parser
       Data.Morpheus.Parsing.Request.Selection
-      Data.Morpheus.Rendering.Haskell.Render
-      Data.Morpheus.Rendering.Haskell.Terms
-      Data.Morpheus.Rendering.Haskell.Types
-      Data.Morpheus.Rendering.Haskell.Values
       Data.Morpheus.Rendering.RenderGQL
       Data.Morpheus.Rendering.RenderIntrospection
       Data.Morpheus.Schema.Schema
       Data.Morpheus.Schema.SchemaAPI
       Data.Morpheus.Schema.TypeKind
-      Data.Morpheus.Types.Custom
       Data.Morpheus.Types.GQLScalar
       Data.Morpheus.Types.GQLType
       Data.Morpheus.Types.ID
+      Data.Morpheus.Types.Internal.AST.Base
+      Data.Morpheus.Types.Internal.AST.Data
       Data.Morpheus.Types.Internal.AST.Operation
-      Data.Morpheus.Types.Internal.AST.RawSelection
       Data.Morpheus.Types.Internal.AST.Selection
-      Data.Morpheus.Types.Internal.Base
-      Data.Morpheus.Types.Internal.Data
-      Data.Morpheus.Types.Internal.DataD
-      Data.Morpheus.Types.Internal.Resolver
-      Data.Morpheus.Types.Internal.Stream
+      Data.Morpheus.Types.Internal.AST.Value
+      Data.Morpheus.Types.Internal.Resolving
+      Data.Morpheus.Types.Internal.Resolving.Core
+      Data.Morpheus.Types.Internal.Resolving.Resolver
       Data.Morpheus.Types.Internal.TH
-      Data.Morpheus.Types.Internal.Validation
-      Data.Morpheus.Types.Internal.Value
       Data.Morpheus.Types.Internal.WebSocket
       Data.Morpheus.Types.IO
       Data.Morpheus.Types.Types
@@ -325,7 +329,6 @@
       Data.Morpheus.Validation.Query.Arguments
       Data.Morpheus.Validation.Query.Fragment
       Data.Morpheus.Validation.Query.Selection
-      Data.Morpheus.Validation.Query.Utils.Selection
       Data.Morpheus.Validation.Query.Validation
       Data.Morpheus.Validation.Query.Variable
       Paths_morpheus_graphql
@@ -342,6 +345,7 @@
     , scientific >=0.3.6.2 && <0.4
     , template-haskell >=2.0 && <=2.16
     , text >=1.2.3.0 && <1.3
+    , th-lift-instances >=0.1.1 && <=0.2.0
     , transformers >=0.3.0.0 && <0.6
     , unordered-containers >=0.2.8.0 && <0.3
     , uuid >=1.0 && <=1.4
@@ -381,6 +385,7 @@
     , tasty-hunit
     , template-haskell >=2.0 && <=2.16
     , text >=1.2.3.0 && <1.3
+    , th-lift-instances >=0.1.1 && <=0.2.0
     , transformers >=0.3.0.0 && <0.6
     , unordered-containers >=0.2.8.0 && <0.3
     , uuid >=1.0 && <=1.4
diff --git a/src/Data/Morpheus.hs b/src/Data/Morpheus.hs
--- a/src/Data/Morpheus.hs
+++ b/src/Data/Morpheus.hs
@@ -1,6 +1,8 @@
 -- | Build GraphQL APIs with your favourite functional language!
 module Data.Morpheus
   ( Interpreter(..)
-  ) where
+  )
+where
 
-import           Data.Morpheus.Execution.Server.Interpreter (Interpreter (..))
+import           Data.Morpheus.Execution.Server.Interpreter
+                                                ( Interpreter(..) )
diff --git a/src/Data/Morpheus/Client.hs b/src/Data/Morpheus/Client.hs
--- a/src/Data/Morpheus/Client.hs
+++ b/src/Data/Morpheus/Client.hs
@@ -1,5 +1,4 @@
 {-# LANGUAGE FlexibleContexts  #-}
-{-# LANGUAGE NamedFieldPuns    #-}
 {-# LANGUAGE OverloadedStrings #-}
 
 module Data.Morpheus.Client
@@ -10,38 +9,46 @@
   , defineByDocumentFile
   , defineByIntrospection
   , defineByIntrospectionFile
-  ) where
+  )
+where
 
-import           Data.ByteString.Lazy                    (ByteString)
-import qualified Data.ByteString.Lazy                    as L (readFile)
+import           Data.ByteString.Lazy           ( ByteString )
+import qualified Data.ByteString.Lazy          as L
+                                                ( readFile )
 import           Language.Haskell.TH
 import           Language.Haskell.TH.Quote
 
-import           Data.Morpheus.Document                  (parseFullGQLDocument)
+import           Data.Morpheus.Document         ( parseFullGQLDocument )
 -- MORPHEUS
-import           Data.Morpheus.Execution.Client.Build    (defineQuery)
-import           Data.Morpheus.Execution.Client.Compile  (compileSyntax)
-import           Data.Morpheus.Execution.Client.Fetch    (Fetch (..))
-import           Data.Morpheus.Parsing.JSONSchema.Parse  (decodeIntrospection)
-import           Data.Morpheus.Types.Internal.Data       (DataTypeLib)
-import           Data.Morpheus.Types.Internal.Validation (Validation)
-import           Data.Morpheus.Types.Types               (GQLQueryRoot)
+import           Data.Morpheus.Execution.Client.Build
+                                                ( defineQuery )
+import           Data.Morpheus.Execution.Client.Compile
+                                                ( compileSyntax )
+import           Data.Morpheus.Execution.Client.Fetch
+                                                ( Fetch(..) )
+import           Data.Morpheus.Parsing.JSONSchema.Parse
+                                                ( decodeIntrospection )
+import           Data.Morpheus.Types.Internal.Resolving
+                                                ( Validation )
+import           Data.Morpheus.Types.Internal.AST
+                                                ( GQLQuery
+                                                , DataTypeLib
+                                                )
 
 gql :: QuasiQuoter
-gql =
-  QuasiQuoter
-    { quoteExp = compileSyntax
-    , quotePat = notHandled "Patterns"
-    , quoteType = notHandled "Types"
-    , quoteDec = notHandled "Declarations"
-    }
-  where
-    notHandled things = error $ things ++ " are not supported by the GraphQL QuasiQuoter"
+gql = QuasiQuoter { quoteExp  = compileSyntax
+                  , quotePat  = notHandled "Patterns"
+                  , quoteType = notHandled "Types"
+                  , quoteDec  = notHandled "Declarations"
+                  }
+ where
+  notHandled things =
+    error $ things ++ " are not supported by the GraphQL QuasiQuoter"
 
-defineByDocumentFile :: String -> (GQLQueryRoot, String) -> Q [Dec]
+defineByDocumentFile :: String -> (GQLQuery, String) -> Q [Dec]
 defineByDocumentFile = defineByDocument . L.readFile
 
-defineByIntrospectionFile :: String -> (GQLQueryRoot, String) -> Q [Dec]
+defineByIntrospectionFile :: String -> (GQLQuery, String) -> Q [Dec]
 defineByIntrospectionFile = defineByIntrospection . L.readFile
 
 --
@@ -49,11 +56,11 @@
 -- TODO: Define By API
 -- Validates By Server API
 --
-defineByDocument :: IO ByteString -> (GQLQueryRoot, String) -> Q [Dec]
+defineByDocument :: IO ByteString -> (GQLQuery, String) -> Q [Dec]
 defineByDocument doc = defineQuery (schemaByDocument doc)
 
 schemaByDocument :: IO ByteString -> IO (Validation DataTypeLib)
 schemaByDocument documentGQL = parseFullGQLDocument <$> documentGQL
 
-defineByIntrospection :: IO ByteString -> (GQLQueryRoot, String) -> Q [Dec]
+defineByIntrospection :: IO ByteString -> (GQLQuery, String) -> Q [Dec]
 defineByIntrospection json = defineQuery (decodeIntrospection <$> json)
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
@@ -1,39 +1,64 @@
+{-# LANGUAGE NamedFieldPuns #-}
 {-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE NamedFieldPuns   #-}
 
 module Data.Morpheus.Document
   ( toGraphQLDocument
-  , toMorpheusHaskellAPi
   , gqlDocument
   , parseFullGQLDocument
   , importGQLDocument
   , importGQLDocumentWithNamespace
-  ) where
+  , parseDSL
+  )
+where
 
-import           Control.Monad                                ((>=>))
-import           Data.ByteString.Lazy.Char8                   (ByteString, pack)
-import           Data.Text                                    (Text)
-import qualified Data.Text.Lazy                               as LT (toStrict)
-import           Data.Text.Lazy.Encoding                      (decodeUtf8)
+import           Control.Monad                  ( (>=>) )
+import           Data.ByteString.Lazy.Char8     ( ByteString
+                                                , pack
+                                                )
+import           Data.Text                      ( Text )
+import qualified Data.Text.Lazy                as LT
+                                                ( toStrict )
+import           Data.Text.Lazy.Encoding        ( decodeUtf8 )
 import           Language.Haskell.TH
 
 --
 -- MORPHEUS
-import           Data.Morpheus.Execution.Document.Compile     (compileDocument, gqlDocument)
-import           Data.Morpheus.Execution.Server.Resolve       (RootResCon, fullSchema)
-import           Data.Morpheus.Rendering.Haskell.Render       (renderHaskellDocument)
-import           Data.Morpheus.Rendering.RenderGQL            (renderGraphQLDocument)
-import           Data.Morpheus.Types                          (GQLRootResolver)
+import           Data.Morpheus.Execution.Document.Compile
+                                                ( compileDocument
+                                                , gqlDocument
+                                                )
+import           Data.Morpheus.Execution.Server.Resolve
+                                                ( RootResCon
+                                                , fullSchema
+                                                )
+import           Data.Morpheus.Parsing.Document.Parser
+                                                ( parseTypes )
 
-import           Data.Morpheus.Parsing.Document.Parser        (parseTypes)
-import           Data.Morpheus.Parsing.Internal.Create        (createDataTypeLib)
-import           Data.Morpheus.Schema.SchemaAPI               (defaultTypes)
-import           Data.Morpheus.Types.Internal.Data            (DataTypeLib)
-import           Data.Morpheus.Types.Internal.Validation      (Validation)
-import           Data.Morpheus.Validation.Document.Validation (validatePartialDocument)
+import           Data.Morpheus.Rendering.RenderGQL
+                                                ( renderGraphQLDocument )
+import           Data.Morpheus.Schema.SchemaAPI ( defaultTypes )
+import           Data.Morpheus.Types            ( GQLRootResolver )
+import           Data.Morpheus.Types.Internal.AST
+                                                ( DataTypeLib
+                                                , createDataTypeLib
+                                                )
+import           Data.Morpheus.Types.Internal.Resolving
+                                                ( Validation
+                                                , Result(..)
+                                                )
+import           Data.Morpheus.Validation.Document.Validation
+                                                ( validatePartialDocument )
 
+                                              
+parseDSL :: ByteString -> Either String DataTypeLib
+parseDSL doc = case parseGraphQLDocument doc of
+  Failure errors     -> Left (show errors)
+  Success { result } -> Right result
+
+
 parseDocument :: Text -> Validation DataTypeLib
-parseDocument doc = parseTypes doc >>= validatePartialDocument >>= createDataTypeLib
+parseDocument doc =
+  parseTypes doc >>= validatePartialDocument >>= createDataTypeLib
 
 parseGraphQLDocument :: ByteString -> Validation DataTypeLib
 parseGraphQLDocument x = parseDocument (LT.toStrict $ decodeUtf8 x)
@@ -42,20 +67,19 @@
 parseFullGQLDocument = parseGraphQLDocument >=> defaultTypes
 
 -- | Generates schema.gql file from 'GQLRootResolver'
-toGraphQLDocument :: RootResCon m event query mut sub => proxy (GQLRootResolver m event query mut sub) -> ByteString
-toGraphQLDocument x =
-  case fullSchema x of
-    Left errors -> pack (show errors)
-    Right lib   -> renderGraphQLDocument lib
+toGraphQLDocument
+  :: RootResCon m event query mut sub
+  => proxy (GQLRootResolver m event query mut sub)
+  -> ByteString
+toGraphQLDocument x = case fullSchema x of
+  Failure errors           -> pack (show errors)
+  Success { result = lib } -> renderGraphQLDocument lib
 
-toMorpheusHaskellAPi :: String -> ByteString -> Either ByteString ByteString
-toMorpheusHaskellAPi moduleName doc =
-  case parseGraphQLDocument doc of
-    Left errors -> Left $ pack (show errors)
-    Right lib   -> Right $ renderHaskellDocument moduleName lib
 
+
 importGQLDocument :: String -> Q [Dec]
 importGQLDocument src = runIO (readFile src) >>= compileDocument False
 
 importGQLDocumentWithNamespace :: String -> Q [Dec]
-importGQLDocumentWithNamespace src = runIO (readFile src) >>= compileDocument True
+importGQLDocumentWithNamespace src =
+  runIO (readFile src) >>= compileDocument True
diff --git a/src/Data/Morpheus/Error/Arguments.hs b/src/Data/Morpheus/Error/Arguments.hs
--- a/src/Data/Morpheus/Error/Arguments.hs
+++ b/src/Data/Morpheus/Error/Arguments.hs
@@ -5,13 +5,21 @@
   , unknownArguments
   , argumentGotInvalidValue
   , argumentNameCollision
-  ) where
+  )
+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 qualified Data.Text                               as T (concat)
+import           Data.Morpheus.Error.Utils      ( errorMessage )
+import           Data.Morpheus.Types.Internal.AST.Base
+                                                ( Ref(..)
+                                                , Position
+                                                )
+import           Data.Morpheus.Types.Internal.Resolving.Core
+                                                ( GQLError(..)
+                                                , GQLErrors
+                                                )
+import           Data.Text                      ( Text )
+import qualified Data.Text                     as T
+                                                ( concat )
 
 {-
   ARGUMENTS:
@@ -28,29 +36,27 @@
   - date(name: "name") -> "Unknown argument \"name\" on field \"date\" of type \"Experience\"."
 -}
 argumentGotInvalidValue :: Text -> Text -> Position -> GQLErrors
-argumentGotInvalidValue key' inputMessage' position' =
-  errorMessage position' text
-  where
-    text = T.concat ["Argument ", key', " got invalid value ;", inputMessage']
+argumentGotInvalidValue key' inputMessage' position' = errorMessage position'
+                                                                    text
+ where
+  text = T.concat ["Argument ", key', " got invalid value ;", inputMessage']
 
-unknownArguments :: Text -> [EnhancedKey] -> GQLErrors
+unknownArguments :: Text -> [Ref] -> GQLErrors
 unknownArguments fieldName = map keyToError
-  where
-    keyToError (EnhancedKey argName pos) =
-      GQLError {desc = toMessage argName, positions = [pos]}
-    toMessage argName =
-      T.concat
-        ["Unknown Argument \"", argName, "\" on Field \"", fieldName, "\"."]
+ where
+  keyToError (Ref argName pos) =
+    GQLError { message = toMessage argName, locations = [pos] }
+  toMessage argName = T.concat
+    ["Unknown Argument \"", argName, "\" on Field \"", fieldName, "\"."]
 
-argumentNameCollision :: [EnhancedKey] -> GQLErrors
+argumentNameCollision :: [Ref] -> GQLErrors
 argumentNameCollision = map keyToError
-  where
-    keyToError (EnhancedKey argName pos) =
-      GQLError {desc = toMessage argName, positions = [pos]}
-    toMessage argName =
-      T.concat ["There can Be only One Argument Named \"", argName, "\""]
+ where
+  keyToError (Ref argName pos) =
+    GQLError { message = toMessage argName, locations = [pos] }
+  toMessage argName =
+    T.concat ["There can Be only One Argument Named \"", argName, "\""]
 
-undefinedArgument :: EnhancedKey -> GQLErrors
-undefinedArgument (EnhancedKey key' position') = errorMessage position' text
-  where
-    text = T.concat ["Required Argument: \"", key', "\" was not Defined"]
+undefinedArgument :: Ref -> GQLErrors
+undefinedArgument (Ref key' position') = errorMessage position' text
+  where text = T.concat ["Required Argument: \"", key', "\" was not Defined"]
diff --git a/src/Data/Morpheus/Error/Client/Client.hs b/src/Data/Morpheus/Error/Client/Client.hs
--- a/src/Data/Morpheus/Error/Client/Client.hs
+++ b/src/Data/Morpheus/Error/Client/Client.hs
@@ -1,11 +1,55 @@
+{-# LANGUAGE NamedFieldPuns #-}
+{-# LANGUAGE OverloadedStrings #-}
+
 module Data.Morpheus.Error.Client.Client
   ( renderGQLErrors
-  ) where
+  , deprecatedEnum
+  , deprecatedField
+  , gqlWarnings
+  )
+where
 
-import           Data.Aeson                              (encode)
-import           Data.ByteString.Lazy.Char8              (unpack)
-import           Data.Morpheus.Error.Utils               (renderErrors)
-import           Data.Morpheus.Types.Internal.Validation (GQLErrors)
+import           Data.Aeson                     ( encode )
+import           Data.ByteString.Lazy.Char8     ( unpack )
+import           Data.Morpheus.Error.Utils      ( errorMessage )
+import           Data.Morpheus.Types.Internal.Resolving.Core
+                                                ( GQLErrors )
+import           Data.Morpheus.Types.Internal.AST.Base
+                                                ( Ref(..)
+                                                , Description
+                                                , Name
+                                                )
+import           Language.Haskell.TH            ( Q
+                                                , reportWarning
+                                                )
+import           Data.Semigroup                 ( (<>) )
 
 renderGQLErrors :: GQLErrors -> String
-renderGQLErrors = unpack . encode . renderErrors
+renderGQLErrors = unpack . encode
+
+deprecatedEnum :: Name -> Ref -> Maybe Description -> GQLErrors
+deprecatedEnum typeName Ref { refPosition, refName } reason =
+  errorMessage refPosition
+    $  "the enum value "
+    <> typeName
+    <> "."
+    <> refName
+    <> "\" is deprecated."
+    <> maybe "" (" " <>) reason
+
+deprecatedField :: Name -> Ref -> Maybe Description -> GQLErrors
+deprecatedField typeName Ref { refPosition, refName } reason =
+  errorMessage refPosition
+    $  "the field \""
+    <> typeName
+    <> "."
+    <> refName
+    <> "\" is deprecated."
+    <> maybe "" (" " <>) reason
+
+gqlWarnings :: GQLErrors -> Q ()
+gqlWarnings []       = pure ()
+gqlWarnings warnings = mapM_ handleWarning warnings
+ where
+  handleWarning warning =
+    reportWarning ("Morpheus GraphQL Warning: " <> (unpack . encode) warning)
diff --git a/src/Data/Morpheus/Error/Document/Interface.hs b/src/Data/Morpheus/Error/Document/Interface.hs
--- a/src/Data/Morpheus/Error/Document/Interface.hs
+++ b/src/Data/Morpheus/Error/Document/Interface.hs
@@ -5,17 +5,21 @@
   ( unknownInterface
   , partialImplements
   , ImplementsError(..)
-  ) where
+  )
+where
 
-import           Data.Morpheus.Error.Utils               (globalErrorMessage)
-import           Data.Morpheus.Types.Internal.Base       (Key)
-import           Data.Morpheus.Types.Internal.Validation (GQLError (..), GQLErrors)
-import           Data.Semigroup                          ((<>))
+import           Data.Morpheus.Error.Utils      ( globalErrorMessage )
+import           Data.Morpheus.Types.Internal.AST.Base
+                                                ( Key )
+import           Data.Morpheus.Types.Internal.Resolving.Core
+                                                ( GQLError(..)
+                                                , GQLErrors
+                                                )
+import           Data.Semigroup                 ( (<>) )
 
 unknownInterface :: Key -> GQLErrors
 unknownInterface name = globalErrorMessage message
-  where
-    message = "Unknown Interface \"" <> name <> "\"."
+  where message = "Unknown Interface \"" <> name <> "\"."
 
 data ImplementsError
   = UnexpectedType { expectedType :: Key
@@ -24,12 +28,24 @@
 
 partialImplements :: Key -> [(Key, Key, ImplementsError)] -> GQLErrors
 partialImplements name = map impError
-  where
-    impError (interfaceName, key, errorType) = GQLError {desc = message, positions = []}
-      where
-        message =
-          "type \"" <> name <> "\" implements Interface \"" <> interfaceName <> "\" Partially," <>
-          detailedMessage errorType
-        detailedMessage UnexpectedType {expectedType, foundType} =
-          " on key \"" <> key <> "\" expected type \"" <> expectedType <> "\" found \"" <> foundType <> "\"."
-        detailedMessage UndefinedField = " key \"" <> key <> "\" not found ."
+ where
+  impError (interfaceName, key, errorType) = GQLError { message   = message
+                                                      , locations = []
+                                                      }
+   where
+    message =
+      "type \""
+        <> name
+        <> "\" implements Interface \""
+        <> interfaceName
+        <> "\" Partially,"
+        <> detailedMessage errorType
+    detailedMessage UnexpectedType { expectedType, foundType } =
+      " on key \""
+        <> key
+        <> "\" expected type \""
+        <> expectedType
+        <> "\" found \""
+        <> foundType
+        <> "\"."
+    detailedMessage UndefinedField = " key \"" <> key <> "\" not found ."
diff --git a/src/Data/Morpheus/Error/Fragment.hs b/src/Data/Morpheus/Error/Fragment.hs
--- a/src/Data/Morpheus/Error/Fragment.hs
+++ b/src/Data/Morpheus/Error/Fragment.hs
@@ -7,16 +7,23 @@
   , unknownFragment
   , cannotBeSpreadOnType
   , fragmentNameCollision
-  ) where
+  )
+where
 
-import           Data.Semigroup                          ((<>))
-import           Data.Text                               (Text)
-import qualified Data.Text                               as T
+import           Data.Semigroup                 ( (<>) )
+import           Data.Text                      ( Text )
+import qualified Data.Text                     as T
 
 -- MORPHEUS
-import           Data.Morpheus.Error.Utils               (errorMessage)
-import           Data.Morpheus.Types.Internal.Base       (EnhancedKey (..), Position)
-import           Data.Morpheus.Types.Internal.Validation (GQLError (..), GQLErrors)
+import           Data.Morpheus.Error.Utils      ( errorMessage )
+import           Data.Morpheus.Types.Internal.AST.Base
+                                                ( Ref(..)
+                                                , Position
+                                                )
+import           Data.Morpheus.Types.Internal.Resolving.Core
+                                                ( GQLError(..)
+                                                , GQLErrors
+                                                )
 
 {-
   FRAGMENT:
@@ -29,57 +36,53 @@
     fragment H on D {...}  ->  "Unknown type \"D\"."
     {...H} -> "Unknown fragment \"H\"."
 -}
-fragmentNameCollision :: [EnhancedKey] -> GQLErrors
+fragmentNameCollision :: [Ref] -> GQLErrors
 fragmentNameCollision = map toError
-  where
-    toError EnhancedKey {uid, location} =
-      GQLError
-        { desc = "There can be only one fragment named \"" <> uid <> "\"."
-        , positions = [location]
-        }
+ where
+  toError Ref { refName, refPosition } = GQLError
+    { message      = "There can be only one fragment named \"" <> refName <> "\"."
+    , locations = [refPosition]
+    }
 
-unusedFragment :: [EnhancedKey] -> GQLErrors
+unusedFragment :: [Ref] -> GQLErrors
 unusedFragment = map toError
-  where
-    toError EnhancedKey {uid, location} =
-      GQLError
-        { desc = "Fragment \"" <> uid <> "\" is never used."
-        , positions = [location]
-        }
+ where
+  toError Ref { refName, refPosition } = GQLError
+    { message      = "Fragment \"" <> refName <> "\" is never used."
+    , locations = [refPosition]
+    }
 
-cannotSpreadWithinItself :: [EnhancedKey] -> GQLErrors
+cannotSpreadWithinItself :: [Ref] -> GQLErrors
 cannotSpreadWithinItself fragments =
-  [GQLError {desc = text, positions = map location fragments}]
-  where
-    text =
-      T.concat
-        [ "Cannot spread fragment \""
-        , uid $ head fragments
-        , "\" within itself via "
-        , T.intercalate "," (map uid fragments)
-        , "."
-        ]
+  [GQLError { message = text, locations = map refPosition fragments }]
+ where
+  text = T.concat
+    [ "Cannot spread fragment \""
+    , refName $ head fragments
+    , "\" within itself via "
+    , T.intercalate "," (map refName fragments)
+    , "."
+    ]
 
 -- {...H} -> "Unknown fragment \"H\"."
 unknownFragment :: Text -> Position -> GQLErrors
 unknownFragment key' position' = errorMessage position' text
-  where
-    text = T.concat ["Unknown Fragment \"", key', "\"."]
+  where text = T.concat ["Unknown Fragment \"", key', "\"."]
 
 -- Fragment type mismatch -> "Fragment \"H\" cannot be spread here as objects of type \"Hobby\" can never be of type \"Experience\"."
 cannotBeSpreadOnType :: Maybe Text -> Text -> Position -> Text -> GQLErrors
-cannotBeSpreadOnType key' type' position' selectionType' =
-  errorMessage position' text
-  where
-    text =
-      T.concat
-        [ "Fragment"
-        , getName key'
-        , " cannot be spread here as objects of type \""
-        , selectionType'
-        , "\" can never be of type \""
-        , type'
-        , "\"."
-        ]
-    getName (Just x') = T.concat [" \"", x', "\""]
-    getName Nothing   = ""
+cannotBeSpreadOnType key' type' position' selectionType' = errorMessage
+  position'
+  text
+ where
+  text = T.concat
+    [ "Fragment"
+    , getName key'
+    , " cannot be spread here as objects of type \""
+    , selectionType'
+    , "\" can never be of type \""
+    , type'
+    , "\"."
+    ]
+  getName (Just x') = T.concat [" \"", x', "\""]
+  getName Nothing   = ""
diff --git a/src/Data/Morpheus/Error/Input.hs b/src/Data/Morpheus/Error/Input.hs
--- a/src/Data/Morpheus/Error/Input.hs
+++ b/src/Data/Morpheus/Error/Input.hs
@@ -1,18 +1,25 @@
 {-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
 
 module Data.Morpheus.Error.Input
   ( inputErrorMessage
   , InputError(..)
   , Prop(..)
   , InputValidation
-  ) where
-
-import           Data.Aeson                         (encode)
-import           Data.ByteString.Lazy.Char8         (unpack)
-import           Data.Morpheus.Types.Internal.Value (Value)
-import           Data.Text                          (Text)
-import qualified Data.Text                          as T (concat, intercalate, pack)
+  )
+where
 
+import           Data.Aeson                     ( encode )
+import           Data.ByteString.Lazy.Char8     ( unpack )
+import           Data.Morpheus.Types.Internal.AST.Value
+                                                ( Value )
+import           Data.Text                      ( Text )
+import qualified Data.Text                     as T
+                                                ( concat
+                                                , intercalate
+                                                , pack
+                                                )
 type InputValidation a = Either InputError a
 
 data InputError
@@ -30,33 +37,31 @@
 inputErrorMessage (UnexpectedType path type' value errorMessage) =
   expectedTypeAFoundB path type' value errorMessage
 inputErrorMessage (UndefinedField path' field') = undefinedField path' field'
-inputErrorMessage (UnknownField path' field') = unknownField path' field'
+inputErrorMessage (UnknownField   path' field') = unknownField path' field'
 
 pathToText :: [Prop] -> Text
 pathToText []    = ""
 pathToText path' = T.concat ["on ", T.intercalate "." $ fmap propKey path']
 
 expectedTypeAFoundB :: [Prop] -> Text -> Value -> Maybe Text -> Text
-expectedTypeAFoundB path' expected found Nothing =
-  T.concat
-    [ pathToText path'
-    , " Expected type \""
-    , expected
-    , "\" found "
-    , T.pack (unpack $ encode found)
-    , "."
-    ]
-expectedTypeAFoundB path' expected found (Just errorMessage) =
-  T.concat
-    [ pathToText path'
-    , " Expected type \""
-    , expected
-    , "\" found "
-    , T.pack (unpack $ encode found)
-    , "; "
-    , errorMessage
-    , "."
-    ]
+expectedTypeAFoundB path' expected found Nothing = T.concat
+  [ pathToText path'
+  , " Expected type \""
+  , expected
+  , "\" found "
+  , T.pack (unpack $ encode found)
+  , "."
+  ]
+expectedTypeAFoundB path' expected found (Just errorMessage) = T.concat
+  [ pathToText path'
+  , " Expected type \""
+  , expected
+  , "\" found "
+  , T.pack (unpack $ encode found)
+  , "; "
+  , errorMessage
+  , "."
+  ]
 
 undefinedField :: [Prop] -> Text -> Text
 undefinedField path' field' =
diff --git a/src/Data/Morpheus/Error/Internal.hs b/src/Data/Morpheus/Error/Internal.hs
--- a/src/Data/Morpheus/Error/Internal.hs
+++ b/src/Data/Morpheus/Error/Internal.hs
@@ -5,33 +5,42 @@
   , internalArgumentError
   , internalUnknownTypeMessage
   , internalError
-  ) where
+  )
+where
 
-import           Data.Text                               (Text)
-import qualified Data.Text                               as T (concat, pack)
+import           Data.Text                      ( Text )
+import qualified Data.Text                     as T
+                                                ( concat
+                                                , pack
+                                                )
+import           Data.Semigroup                 ( (<>) )
 
 -- MORPHEUS
-import           Data.Morpheus.Error.Utils               (globalErrorMessage)
-import           Data.Morpheus.Types.Internal.Validation (GQLErrors)
-import           Data.Morpheus.Types.Internal.Value      (Value (..))
+import           Data.Morpheus.Error.Utils      ( globalErrorMessage )
+import           Data.Morpheus.Types.Internal.Resolving.Core
+                                                ( Validation
+                                                , GQLErrors
+                                                , Failure(..)
+                                                )
+import           Data.Morpheus.Types.Internal.AST.Value
+                                                ( Value(..) )
 
 
 -- GQL:: if no mutation defined -> "Schema is not configured for mutations."
 -- all kind internal error in development
-internalError :: Text -> Either GQLErrors b
-internalError x = Left $ globalErrorMessage $ T.concat ["INTERNAL ERROR: ", x]
+internalError :: Text -> Validation b
+internalError x = failure $ globalErrorMessage $ "INTERNAL ERROR: " <> x
 
 -- if type did not not found, but was defined by Schema
 internalUnknownTypeMessage :: Text -> GQLErrors
-internalUnknownTypeMessage x =
-  globalErrorMessage $
-  T.concat ["type did not not found, but was defined by Schema", x]
+internalUnknownTypeMessage x = globalErrorMessage
+  $ T.concat ["type did not not found, but was defined by Schema", x]
 
 -- if arguments is already validated but has not found required argument
-internalArgumentError :: Text -> Either GQLErrors b
-internalArgumentError x = internalError $ T.concat ["Argument ", x]
+internalArgumentError :: Text -> Validation b
+internalArgumentError x = internalError $ "Argument " <> x
 
 -- if value is already validated but value has different type
-internalTypeMismatch :: Text -> Value -> Either GQLErrors b
+internalTypeMismatch :: Text -> Value -> Validation b
 internalTypeMismatch text jsType =
-  internalError $ T.concat ["Type mismatch ", text, T.pack $ show jsType]
+  internalError $ "Type mismatch " <> text <> T.pack (show jsType)
diff --git a/src/Data/Morpheus/Error/Mutation.hs b/src/Data/Morpheus/Error/Mutation.hs
--- a/src/Data/Morpheus/Error/Mutation.hs
+++ b/src/Data/Morpheus/Error/Mutation.hs
@@ -2,11 +2,14 @@
 
 module Data.Morpheus.Error.Mutation
   ( mutationIsNotDefined
-  ) where
+  )
+where
 
-import           Data.Morpheus.Error.Utils               (errorMessage)
-import           Data.Morpheus.Types.Internal.Base       (Position)
-import           Data.Morpheus.Types.Internal.Validation (GQLErrors)
+import           Data.Morpheus.Error.Utils      ( errorMessage )
+import           Data.Morpheus.Types.Internal.AST.Base
+                                                ( Position )
+import           Data.Morpheus.Types.Internal.Resolving.Core
+                                                ( GQLErrors )
 
 mutationIsNotDefined :: Position -> GQLErrors
 mutationIsNotDefined position' =
diff --git a/src/Data/Morpheus/Error/Schema.hs b/src/Data/Morpheus/Error/Schema.hs
--- a/src/Data/Morpheus/Error/Schema.hs
+++ b/src/Data/Morpheus/Error/Schema.hs
@@ -3,12 +3,14 @@
 module Data.Morpheus.Error.Schema
   ( nameCollisionError
   , schemaValidationError
-  ) where
+  )
+where
 
-import           Data.Morpheus.Error.Utils               (globalErrorMessage)
-import           Data.Morpheus.Types.Internal.Validation (GQLErrors)
-import           Data.Semigroup                          ((<>))
-import           Data.Text                               (Text)
+import           Data.Morpheus.Error.Utils      ( globalErrorMessage )
+import           Data.Morpheus.Types.Internal.Resolving.Core
+                                                ( GQLErrors )
+import           Data.Semigroup                 ( (<>) )
+import           Data.Text                      ( Text )
 
 schemaValidationError :: Text -> GQLErrors
 schemaValidationError error' =
@@ -16,6 +18,7 @@
 
 nameCollisionError :: Text -> GQLErrors
 nameCollisionError name =
-  schemaValidationError $
-  "Name collision: \"" <> name <>
-  "\" is used for different dataTypes in two separate modules"
+  schemaValidationError
+    $  "Name collision: \""
+    <> name
+    <> "\" is used for different dataTypes in two separate modules"
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
@@ -5,43 +5,66 @@
   , subfieldsNotSelected
   , duplicateQuerySelections
   , hasNoSubfields
-  , fieldNotResolved
-  , resolverError
-  ) where
+  , resolvingFailedError
+  )
+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, pack)
-import qualified Data.Text                               as T (concat)
+import           Data.Semigroup                 ( (<>) )
+import           Data.Morpheus.Error.Utils      ( errorMessage )
+import           Data.Morpheus.Types.Internal.AST.Base
+                                                ( Ref(..)
+                                                , Position
+                                                )
+import           Data.Morpheus.Types.Internal.Resolving.Core
+                                                ( GQLError(..)
+                                                , GQLErrors
+                                                )
+import           Data.Text                      ( Text )
+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
-    text = T.concat ["Failure on Resolving Field \"", key', "\": ", message']
+resolvingFailedError :: Position -> Text -> Text -> GQLError
+resolvingFailedError position name reason = GQLError
+  { message   = "Failure on Resolving Field \"" <> name <> "\": " <> reason
+  , locations = [position]
+  }
 
+
 -- GQL: "Field \"default\" must not have a selection since type \"String!\" has no subfields."
 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."]
+ where
+  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, "\"."]
+ where
+  text =
+    T.concat ["Cannot query field \"", key, "\" on type \"", typeName, "\"."]
 
-duplicateQuerySelections :: Text -> [EnhancedKey] -> GQLErrors
+duplicateQuerySelections :: Text -> [Ref] -> 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, "\"."]
+ where
+  keyToError (Ref key' pos) =
+    GQLError { message = toMessage key', locations = [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"]
+ where
+  text = T.concat
+    [ "Field \""
+    , key
+    , "\" of type \""
+    , typeName
+    , "\" must have a selection of subfields"
+    ]
diff --git a/src/Data/Morpheus/Error/Subscription.hs b/src/Data/Morpheus/Error/Subscription.hs
--- a/src/Data/Morpheus/Error/Subscription.hs
+++ b/src/Data/Morpheus/Error/Subscription.hs
@@ -2,11 +2,14 @@
 
 module Data.Morpheus.Error.Subscription
   ( subscriptionIsNotDefined
-  ) where
+  )
+where
 
-import           Data.Morpheus.Error.Utils               (errorMessage)
-import           Data.Morpheus.Types.Internal.Base       (Position)
-import           Data.Morpheus.Types.Internal.Validation (GQLErrors)
+import           Data.Morpheus.Error.Utils      ( errorMessage )
+import           Data.Morpheus.Types.Internal.AST.Base
+                                                ( Position )
+import           Data.Morpheus.Types.Internal.Resolving.Core
+                                                ( GQLErrors )
 
 subscriptionIsNotDefined :: Position -> GQLErrors
 subscriptionIsNotDefined position' =
diff --git a/src/Data/Morpheus/Error/Utils.hs b/src/Data/Morpheus/Error/Utils.hs
--- a/src/Data/Morpheus/Error/Utils.hs
+++ b/src/Data/Morpheus/Error/Utils.hs
@@ -3,31 +3,39 @@
 module Data.Morpheus.Error.Utils
   ( errorMessage
   , globalErrorMessage
-  , renderErrors
   , badRequestError
   , toLocation
-  ) where
+  )
+where
 
-import           Data.ByteString.Lazy.Char8              (ByteString, pack)
-import           Data.Morpheus.Types.Internal.Base       (Position)
-import           Data.Morpheus.Types.Internal.Validation (GQLError (..), GQLErrors, JSONError (..), Location (..))
-import           Data.Text                               (Text)
-import           Text.Megaparsec                         (SourcePos (SourcePos), sourceColumn, sourceLine, unPos)
+import           Data.ByteString.Lazy.Char8     ( ByteString
+                                                , pack
+                                                )
+import           Data.Morpheus.Types.Internal.AST.Base
+                                                ( Position )
+import           Data.Morpheus.Types.Internal.Resolving.Core
+                                                ( GQLError(..)
+                                                , GQLErrors
+                                                , GQLError(..)
+                                                , Position(..)
+                                                )
+import           Data.Text                      ( Text )
+import           Text.Megaparsec                ( SourcePos(SourcePos)
+                                                , sourceColumn
+                                                , sourceLine
+                                                , unPos
+                                                )
 
 errorMessage :: Position -> Text -> GQLErrors
-errorMessage position text = [GQLError {desc = text, positions = [position]}]
+errorMessage position message = [GQLError { message, locations = [position] }]
 
 globalErrorMessage :: Text -> GQLErrors
-globalErrorMessage text = [GQLError {desc = text, positions = []}]
-
-renderErrors :: [GQLError] -> [JSONError]
-renderErrors = map renderError
-
-renderError :: GQLError -> JSONError
-renderError GQLError {desc, positions} = JSONError {message = desc, locations = positions}
+globalErrorMessage message = [GQLError { message, locations = [] }]
 
-toLocation :: SourcePos -> Location
-toLocation SourcePos {sourceLine, sourceColumn} = Location {line = unPos sourceLine, column = unPos sourceColumn}
+toLocation :: SourcePos -> Position
+toLocation SourcePos { sourceLine, sourceColumn } =
+  Position { line = unPos sourceLine, column = unPos sourceColumn }
 
 badRequestError :: String -> ByteString
-badRequestError aesonError' = pack $ "Bad Request. Could not decode Request body: " ++ aesonError'
+badRequestError aesonError' =
+  pack $ "Bad Request. Could not decode Request body: " ++ aesonError'
diff --git a/src/Data/Morpheus/Error/Variable.hs b/src/Data/Morpheus/Error/Variable.hs
--- a/src/Data/Morpheus/Error/Variable.hs
+++ b/src/Data/Morpheus/Error/Variable.hs
@@ -7,75 +7,78 @@
   , uninitializedVariable
   , unusedVariables
   , incompatibleVariableType
-  ) where
+  )
+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.Semigroup                          ((<>))
-import           Data.Text                               (Text)
-import qualified Data.Text                               as T (concat)
+import           Data.Morpheus.Error.Utils      ( errorMessage )
+import           Data.Morpheus.Types.Internal.AST.Base
+                                                ( Ref(..)
+                                                , Position
+                                                )
+import           Data.Morpheus.Types.Internal.Resolving.Core
+                                                ( GQLError(..)
+                                                , GQLErrors
+                                                )
+import           Data.Semigroup                 ( (<>) )
+import           Data.Text                      ( Text )
+import qualified Data.Text                     as T
+                                                ( concat )
 
 -- query M ( $v : String ) { a(p:$v) } -> "Variable \"$v\" of type \"String\" used in position expecting type \"LANGUAGE\"."
 incompatibleVariableType :: Text -> Text -> Text -> Position -> GQLErrors
 incompatibleVariableType variableName variableType argType argPosition =
   errorMessage argPosition text
-  where
-    text =
-      "Variable \"$" <> variableName <> "\" of type \"" <> variableType <>
-      "\" used in position expecting type \"" <>
-      argType <>
-      "\"."
+ where
+  text =
+    "Variable \"$"
+      <> variableName
+      <> "\" of type \""
+      <> variableType
+      <> "\" used in position expecting type \""
+      <> argType
+      <> "\"."
 
 -- query M ( $v : String ) { a } -> "Variable \"$bla\" is never used in operation \"MyMutation\".",
-unusedVariables :: Text -> [EnhancedKey] -> GQLErrors
+unusedVariables :: Text -> [Ref] -> GQLErrors
 unusedVariables operator' = map keyToError
-  where
-    keyToError (EnhancedKey key' position') =
-      GQLError {desc = text key', positions = [position']}
-    text key' =
-      T.concat
-        [ "Variable \"$"
-        , key'
-        , "\" is never used in operation \""
-        , operator'
-        , "\"."
-        ]
+ where
+  keyToError (Ref key' position') =
+    GQLError { message = text key', locations = [position'] }
+  text key' = T.concat
+    ["Variable \"$", key', "\" is never used in operation \"", operator', "\"."]
 
 -- type mismatch
 -- { "v": 1  }        "Variable \"$v\" got invalid value 1; Expected type LANGUAGE."
 variableGotInvalidValue :: Text -> Text -> Position -> GQLErrors
-variableGotInvalidValue name' inputMessage' position' =
-  errorMessage position' text
-  where
-    text =
-      T.concat ["Variable \"$", name', "\" got invalid value; ", inputMessage']
+variableGotInvalidValue name' inputMessage' position' = errorMessage
+  position'
+  text
+ where
+  text =
+    T.concat ["Variable \"$", name', "\" got invalid value; ", inputMessage']
 
 unknownType :: Text -> Position -> GQLErrors
 unknownType type' position' = errorMessage position' text
-  where
-    text = T.concat ["Unknown type \"", type', "\"."]
+  where text = T.concat ["Unknown type \"", type', "\"."]
 
 undefinedVariable :: Text -> Position -> Text -> GQLErrors
 undefinedVariable operation' position' key' = errorMessage position' text
-  where
-    text =
-      T.concat
-        [ "Variable \""
-        , key'
-        , "\" is not defined by operation \""
-        , operation'
-        , "\"."
-        ]
+ where
+  text = T.concat
+    [ "Variable \""
+    , key'
+    , "\" is not defined by operation \""
+    , operation'
+    , "\"."
+    ]
 
 uninitializedVariable :: Position -> Text -> Text -> GQLErrors
 uninitializedVariable position' type' key' = errorMessage position' text
-  where
-    text =
-      T.concat
-        [ "Variable \"$"
-        , key'
-        , "\" of required type \""
-        , type'
-        , "!\" was not provided."
-        ]
+ where
+  text = T.concat
+    [ "Variable \"$"
+    , key'
+    , "\" of required type \""
+    , type'
+    , "!\" was not provided."
+    ]
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
@@ -12,129 +12,147 @@
   ( deriveFromJSON
   , deriveToJSON
   , takeValueType
-  ) where
+  )
+where
 
 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
 
-import           Data.Morpheus.Execution.Internal.Utils (nameSpaceTypeString)
+import           Data.Morpheus.Execution.Internal.Utils
+                                                ( nameSpaceTypeString )
 
 --
 -- MORPHEUS
-import           Data.Morpheus.Types.Internal.Data      (DataField (..), isFieldNullable)
-import           Data.Morpheus.Types.Internal.DataD     (ConsD (..), TypeD (..))
-import           Data.Morpheus.Types.Internal.TH        (destructRecord, instanceFunD, instanceHeadT)
+import           Data.Morpheus.Types.Internal.AST
+                                                ( DataField(..)
+                                                , isFieldNullable
+                                                , ConsD(..)
+                                                , TypeD(..)
+                                                )
+import           Data.Morpheus.Types.Internal.TH
+                                                ( destructRecord
+                                                , instanceFunD
+                                                , instanceHeadT
+                                                )
 
 -- FromJSON
 deriveFromJSON :: TypeD -> Q Dec
-deriveFromJSON TypeD {tCons = []} = fail "Type Should Have at least one Constructor"
-deriveFromJSON TypeD {tName, tNamespace, tCons = [cons]} = defineFromJSON name (aesonObject tNamespace) cons
-  where
-    name = nameSpaceTypeString tNamespace tName
-deriveFromJSON typeD@TypeD {tName, tCons, tNamespace}
+deriveFromJSON TypeD { tCons = [] } =
+  fail "Type Should Have at least one Constructor"
+deriveFromJSON TypeD { tName, tNamespace, tCons = [cons] } = defineFromJSON
+  name
+  (aesonObject tNamespace)
+  cons
+  where name = nameSpaceTypeString tNamespace tName
+deriveFromJSON typeD@TypeD { tName, tCons, tNamespace }
   | isEnum tCons = defineFromJSON name aesonEnum tCons
-  | otherwise = defineFromJSON name (aesonUnionObject tNamespace) typeD
-  where
-    name = nameSpaceTypeString tNamespace tName
+  | otherwise    = defineFromJSON name (aesonUnionObject tNamespace) typeD
+  where name = nameSpaceTypeString tNamespace tName
 
 aesonObject :: [String] -> ConsD -> ExpQ
-aesonObject tNamespace con@ConsD {cName} =
-  appE [|withObject name|] (lamE [varP (mkName "o")] ((aesonObjectBody tNamespace) con))
-  where
-    name = nameSpaceTypeString tNamespace cName
+aesonObject tNamespace con@ConsD { cName } = appE
+  [|withObject name|]
+  (lamE [varP (mkName "o")] (aesonObjectBody tNamespace con))
+  where name = nameSpaceTypeString tNamespace cName
 
 aesonObjectBody :: [String] -> ConsD -> ExpQ
-aesonObjectBody namespace ConsD {cName, cFields} = handleFields cFields
-  where
-    consName = mkName $ nameSpaceTypeString namespace cName
-    ------------------------------------------
-    handleFields [] = fail $ "No Empty Object"
-    handleFields fields = startExp fields
-    ----------------------------------------------------------------------------------
-      -- Optional Field
-      where
-        defField field@DataField {fieldName}
-          | isFieldNullable field = [|o .:? fName|]
-          | otherwise = [|o .: fName|]
-          where
-            fName = unpack fieldName
-            -------------------------------------------------------------------
-        startExp fNames = uInfixE (conE consName) (varE '(<$>)) (applyFields fNames)
-          where
-            applyFields []     = fail "No Empty fields"
-            applyFields [x]    = defField x
-            applyFields (x:xs) = uInfixE (defField x) (varE '(<*>)) (applyFields xs)
+aesonObjectBody namespace ConsD { cName, cFields } = handleFields cFields
+ where
+  consName = mkName $ nameSpaceTypeString namespace cName
+  ------------------------------------------
+  handleFields []     = fail "No Empty Object"
+  handleFields fields = startExp fields
+  ----------------------------------------------------------------------------------
+   where
+    defField field@DataField { fieldName }
+      | isFieldNullable field = [|o .:? fName|]
+      | otherwise             = [|o .: fName|]
+      where fName = unpack fieldName
+        -------------------------------------------------------------------
+    startExp fNames = uInfixE (conE consName)
+                              (varE '(<$>))
+                              (applyFields fNames)
+     where
+      applyFields []  = fail "No Empty fields"
+      applyFields [x] = defField x
+      applyFields (x : xs) =
+        uInfixE (defField x) (varE '(<*>)) (applyFields xs)
 
 aesonUnionObject :: [String] -> TypeD -> ExpQ
-aesonUnionObject namespace TypeD {tCons} =
-  appE (varE $ 'takeValueType) (lamCaseE ((map buildMatch tCons) <> [elseCaseEXP]))
-  where
-    buildMatch cons@ConsD {cName} = match pattern body []
-      where
-        pattern = tupP [litP (stringL cName), varP $ mkName "o"]
-        body = normalB $ aesonObjectBody namespace cons
+aesonUnionObject namespace TypeD { tCons } = appE
+  (varE 'takeValueType)
+  (lamCaseE (map buildMatch tCons <> [elseCaseEXP]))
+ where
+  buildMatch cons@ConsD { cName } = match objectPattern body []
+   where
+    objectPattern = tupP [litP (stringL cName), varP $ mkName "o"]
+    body          = normalB $ aesonObjectBody namespace cons
 
 takeValueType :: ((String, Object) -> Parser a) -> Value -> Parser a
-takeValueType f (Object hMap) =
-  case H.lookup "__typename" hMap of
-    Nothing         -> fail "key \"__typename\" not found on object"
-    Just (String x) -> pure (unpack x, hMap) >>= f
-    Just val        -> fail $ "key \"__typename\" should be string but found: " <> show val
-takeValueType _ _ = fail $ "expected Object"
+takeValueType f (Object hMap) = case H.lookup "__typename" hMap of
+  Nothing         -> fail "key \"__typename\" not found on object"
+  Just (String x) -> pure (unpack x, hMap) >>= f
+  Just val ->
+    fail $ "key \"__typename\" should be string but found: " <> show val
+takeValueType _ _ = fail "expected Object"
 
 defineFromJSON :: String -> (t -> ExpQ) -> t -> DecQ
 defineFromJSON tName parseJ cFields = instanceD (cxt []) iHead [method]
-  where
-    iHead = instanceHeadT ''FromJSON tName []
-    -----------------------------------------
-    method = instanceFunD 'parseJSON [] (parseJ cFields)
+ where
+  iHead  = instanceHeadT ''FromJSON tName []
+  -----------------------------------------
+  method = instanceFunD 'parseJSON [] (parseJ cFields)
 
 isEnum :: [ConsD] -> Bool
 isEnum = not . isEmpty . filter (isEmpty . cFields)
-  where
-    isEmpty = (0 ==) . length
+  where isEmpty = (0 ==) . length
 
 aesonEnum :: [ConsD] -> ExpQ
 aesonEnum cons = lamCaseE handlers
-  where
-    handlers = (map buildMatch cons) <> [elseCaseEXP]
-      where
-        buildMatch ConsD {cName} = match pattern body []
-          where
-            pattern = litP $ stringL cName
-            body = normalB $ appE (varE 'pure) (conE $ mkName cName)
+ where
+  handlers = map buildMatch cons <> [elseCaseEXP]
+   where
+    buildMatch ConsD { cName } = match enumPat body []
+     where
+      enumPat = litP $ stringL cName
+      body    = normalB $ appE (varE 'pure) (conE $ mkName cName)
 
 elseCaseEXP :: MatchQ
 elseCaseEXP = match (varP varName) body []
-  where
-    varName = mkName "invalidValue"
-    body =
-      normalB $
-      appE
-        (varE $ mkName "fail")
-        (uInfixE (appE (varE 'show) (varE varName)) (varE '(<>)) (stringE $ " is Not Valid Union Constructor"))
+ where
+  varName = mkName "invalidValue"
+  body    = normalB $ appE
+    (varE $ mkName "fail")
+    (uInfixE (appE (varE 'show) (varE varName))
+             (varE '(<>))
+             (stringE " is Not Valid Union Constructor")
+    )
 
 -- ToJSON
 deriveToJSON :: TypeD -> Q [Dec]
-deriveToJSON TypeD {tCons = []} = fail "Type Should Have at least one Constructor"
-deriveToJSON TypeD {tName, tCons = [ConsD {cFields}]} = pure <$> instanceD (cxt []) appHead methods
-  where
-    appHead = instanceHeadT ''ToJSON tName []
-    ------------------------------------------------------------------
-    -- defines: toJSON (User field1 field2 ...)= object ["name" .= name, "age" .= age, ...]
-    methods = [funD 'toJSON [clause argsE (normalB body) []]]
-      where
-        argsE = [destructRecord tName varNames]
-        body = appE (varE 'object) (listE $ map decodeVar varNames)
-        decodeVar name = [|name .= $(varName)|]
-          where
-            varName = varE $ mkName name
-        varNames = map (unpack . fieldName) cFields
-deriveToJSON TypeD {tName, tCons}
-  | isEnum tCons = pure <$> instanceD (cxt []) (instanceHeadT ''ToJSON tName []) []
+deriveToJSON TypeD { tCons = [] } =
+  fail "Type Should Have at least one Constructor"
+deriveToJSON TypeD { tName, tCons = [ConsD { cFields }] } =
+  pure <$> instanceD (cxt []) appHead methods
+ where
+  appHead = instanceHeadT ''ToJSON tName []
+  ------------------------------------------------------------------
+  -- defines: toJSON (User field1 field2 ...)= object ["name" .= name, "age" .= age, ...]
+  methods = [funD 'toJSON [clause argsE (normalB body) []]]
+   where
+    argsE = [destructRecord tName varNames]
+    body  = appE (varE 'object) (listE $ map decodeVar varNames)
+    decodeVar name = [|name .= $(varName)|] where varName = varE $ mkName name
+    varNames = map (unpack . fieldName) cFields
+deriveToJSON TypeD { tName, tCons }
+  | isEnum tCons
+  = pure <$> instanceD (cxt []) (instanceHeadT ''ToJSON tName []) []
+  |
     -- enum: uses default aeson instance derivation methods
-  | otherwise = fail "Input Unions are not yet supported"
+    otherwise
+  = fail "Input Unions are not yet supported"
diff --git a/src/Data/Morpheus/Execution/Client/Build.hs b/src/Data/Morpheus/Execution/Client/Build.hs
--- a/src/Data/Morpheus/Execution/Client/Build.hs
+++ b/src/Data/Morpheus/Execution/Client/Build.hs
@@ -6,42 +6,70 @@
 
 module Data.Morpheus.Execution.Client.Build
   ( defineQuery
-  ) where
+  )
+where
 
-import           Data.Semigroup                           ((<>))
+import           Data.Semigroup                 ( (<>) )
 import           Language.Haskell.TH
 
 --
 -- MORPHEUS
-import           Data.Morpheus.Error.Client.Client        (renderGQLErrors)
-import           Data.Morpheus.Execution.Client.Aeson     (deriveFromJSON, deriveToJSON)
-import           Data.Morpheus.Execution.Client.Compile   (validateWith)
-import           Data.Morpheus.Execution.Client.Fetch     (deriveFetch)
-import           Data.Morpheus.Execution.Internal.Declare (declareType)
-import           Data.Morpheus.Types.Internal.Data        (DataTypeKind (..), DataTypeLib, isOutputObject)
-import           Data.Morpheus.Types.Internal.DataD       (GQLTypeD (..), QueryD (..), TypeD (..))
-import           Data.Morpheus.Types.Internal.Validation  (Validation)
-import           Data.Morpheus.Types.Types                (GQLQueryRoot (..))
+import           Data.Morpheus.Error.Client.Client
+                                                ( renderGQLErrors
+                                                , gqlWarnings
+                                                )
+import           Data.Morpheus.Execution.Client.Aeson
+                                                ( deriveFromJSON
+                                                , deriveToJSON
+                                                )
+import           Data.Morpheus.Execution.Client.Compile
+                                                ( validateWith )
+import           Data.Morpheus.Execution.Client.Fetch
+                                                ( deriveFetch )
+import           Data.Morpheus.Execution.Internal.Declare
+                                                ( declareType )
 
-defineQuery :: IO (Validation DataTypeLib) -> (GQLQueryRoot, String) -> Q [Dec]
+import           Data.Morpheus.Types.Internal.AST
+                                                ( GQLQuery(..)
+                                                , DataTypeKind(..)
+                                                , DataTypeLib
+                                                , isOutputObject
+                                                , ClientType(..)
+                                                , ClientQuery(..)
+                                                , TypeD(..)
+                                                )
+import           Data.Morpheus.Types.Internal.Resolving
+                                                ( Validation
+                                                , Result(..)
+                                                )
+
+
+
+defineQuery :: IO (Validation DataTypeLib) -> (GQLQuery, String) -> Q [Dec]
 defineQuery ioSchema queryRoot = do
   schema <- runIO ioSchema
   case schema >>= (`validateWith` queryRoot) of
-    Left errors  -> fail (renderGQLErrors errors)
-    Right queryD -> defineQueryD queryD
+    Failure errors               -> fail (renderGQLErrors errors)
+    Success { result, warnings } -> gqlWarnings warnings >> defineQueryD result
 
-defineQueryD :: QueryD -> Q [Dec]
-defineQueryD QueryD {queryTypes = rootType:subTypes, queryText, queryArgsType} = do
-  rootDecs <- defineOperationType (queryArgumentType queryArgsType) queryText rootType
-  subTypeDecs <- concat <$> traverse declareT subTypes
-  return $ rootDecs ++ subTypeDecs
-  where
-    declareT GQLTypeD {typeD, typeKindD}
-      | isOutputObject typeKindD || typeKindD == KindUnion = withToJSON declareOutputType typeD
-      | typeKindD == KindEnum = withToJSON declareInputType typeD
-      | otherwise = declareInputType typeD
-defineQueryD QueryD {queryTypes = []} = return []
 
+defineQueryD :: ClientQuery -> Q [Dec]
+defineQueryD ClientQuery { queryTypes = rootType : subTypes, queryText, queryArgsType }
+  = do
+    rootDecs <- defineOperationType (queryArgumentType queryArgsType)
+                                    queryText
+                                    rootType
+    subTypeDecs <- concat <$> traverse declareT subTypes
+    return $ rootDecs ++ subTypeDecs
+ where
+  declareT ClientType { clientType, clientKind }
+    | isOutputObject clientKind || clientKind == KindUnion = withToJSON
+      declareOutputType
+      clientType
+    | clientKind == KindEnum = withToJSON declareInputType clientType
+    | otherwise = declareInputType clientType
+defineQueryD ClientQuery { queryTypes = [] } = return []
+
 declareOutputType :: TypeD -> Q [Dec]
 declareOutputType typeD = pure [declareType False Nothing [''Show] typeD]
 
@@ -53,16 +81,18 @@
 withToJSON :: (TypeD -> Q [Dec]) -> TypeD -> Q [Dec]
 withToJSON f datatype = do
   toJson <- deriveFromJSON datatype
-  dec <- f datatype
+  dec    <- f datatype
   pure (toJson : dec)
 
 queryArgumentType :: Maybe TypeD -> (Type, Q [Dec])
-queryArgumentType Nothing                       = (ConT $ mkName "()", pure [])
-queryArgumentType (Just rootType@TypeD {tName}) = (ConT $ mkName tName, declareInputType rootType)
+queryArgumentType Nothing = (ConT $ mkName "()", pure [])
+queryArgumentType (Just rootType@TypeD { tName }) =
+  (ConT $ mkName tName, declareInputType rootType)
 
-defineOperationType :: (Type, Q [Dec]) -> String -> GQLTypeD -> Q [Dec]
-defineOperationType (argType, argumentTypes) query GQLTypeD {typeD} = do
-  rootType <- withToJSON declareOutputType typeD
-  typeClassFetch <- deriveFetch argType (tName typeD) query
-  argsT <- argumentTypes
-  pure $ rootType <> typeClassFetch <> argsT
+defineOperationType :: (Type, Q [Dec]) -> String -> ClientType -> Q [Dec]
+defineOperationType (argType, argumentTypes) query ClientType { clientType } =
+  do
+    rootType       <- withToJSON declareOutputType clientType
+    typeClassFetch <- deriveFetch argType (tName clientType) query
+    argsT          <- argumentTypes
+    pure $ rootType <> typeClassFetch <> argsT
diff --git a/src/Data/Morpheus/Execution/Client/Compile.hs b/src/Data/Morpheus/Execution/Client/Compile.hs
--- a/src/Data/Morpheus/Execution/Client/Compile.hs
+++ b/src/Data/Morpheus/Execution/Client/Compile.hs
@@ -5,37 +5,60 @@
 module Data.Morpheus.Execution.Client.Compile
   ( compileSyntax
   , validateWith
-  ) where
+  )
+where
 
-import qualified Data.Text                                  as T (pack)
+import qualified Data.Text                     as T
+                                                ( pack )
 import           Language.Haskell.TH
 
-import           Data.Morpheus.Error.Client.Client          (renderGQLErrors)
-
-import           Data.Morpheus.Execution.Client.Selection   (operationTypes)
-import           Data.Morpheus.Parsing.Request.Parser       (parseGQL)
-import qualified Data.Morpheus.Types.Internal.AST.Operation as O (Operation (..))
-import           Data.Morpheus.Types.Internal.Data          (DataTypeLib)
-import           Data.Morpheus.Types.IO                     (GQLRequest (..))
-
 --
 --  Morpheus
-import           Data.Morpheus.Types.Internal.DataD         (QueryD (..))
-import           Data.Morpheus.Types.Internal.Validation    (Validation)
-import           Data.Morpheus.Types.Types                  (GQLQueryRoot (..))
-import           Data.Morpheus.Validation.Internal.Utils    (VALIDATION_MODE (..))
-import           Data.Morpheus.Validation.Query.Validation  (validateRequest)
 
+
+import           Data.Morpheus.Error.Client.Client
+                                                ( renderGQLErrors
+                                                , gqlWarnings
+                                                )
+
+import           Data.Morpheus.Execution.Client.Selection
+                                                ( operationTypes )
+import           Data.Morpheus.Parsing.Request.Parser
+                                                ( parseGQL )
+import qualified Data.Morpheus.Types.Internal.AST
+                                               as O
+                                                ( Operation(..) )
+import           Data.Morpheus.Types.IO         ( GQLRequest(..) )
+
+import           Data.Morpheus.Types.Internal.AST
+                                                ( GQLQuery(..)
+                                                , DataTypeLib
+                                                , ClientQuery(..)
+                                                )
+import           Data.Morpheus.Types.Internal.Resolving
+                                                ( Validation
+                                                , Result(..)
+                                                )
+import           Data.Morpheus.Validation.Internal.Utils
+                                                ( VALIDATION_MODE(..) )
+import           Data.Morpheus.Validation.Query.Validation
+                                                ( validateRequest )
+
 compileSyntax :: String -> Q Exp
-compileSyntax queryText =
-  case parseGQL request of
-    Left errors -> fail (renderGQLErrors errors)
-    Right root  -> [|(root, queryText)|]
-  where
-    request = GQLRequest {query = T.pack queryText, operationName = Nothing, variables = Nothing}
+compileSyntax queryText = case parseGQL request of
+  Failure errors -> fail (renderGQLErrors errors)
+  Success { result, warnings } ->
+    gqlWarnings warnings >> [|(result, queryText)|]
+ where
+  request = GQLRequest { query         = T.pack queryText
+                       , operationName = Nothing
+                       , variables     = Nothing
+                       }
 
-validateWith :: DataTypeLib -> (GQLQueryRoot, String) -> Validation QueryD
-validateWith schema (rawRequest@GQLQueryRoot {operation}, queryText) = do
+validateWith :: DataTypeLib -> (GQLQuery, String) -> Validation ClientQuery
+validateWith schema (rawRequest@GQLQuery { operation }, queryText) = do
   validOperation <- validateRequest schema WITHOUT_VARIABLES rawRequest
-  (queryArgsType, queryTypes) <- operationTypes schema (O.operationArgs operation) validOperation
-  return QueryD {queryText, queryTypes, queryArgsType}
+  (queryArgsType, queryTypes) <- operationTypes schema
+                                                (O.operationArgs operation)
+                                                validOperation
+  return ClientQuery { queryText, queryTypes, queryArgsType }
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
@@ -8,27 +8,36 @@
 module Data.Morpheus.Execution.Client.Fetch
   ( Fetch(..)
   , deriveFetch
-  ) where
+  )
+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
 
 
-import qualified Data.Aeson                      as A
-import qualified Data.Aeson.Types                as A
+import qualified Data.Aeson                    as A
+import qualified Data.Aeson.Types              as A
 
 --
 -- MORPHEUS
-import           Data.Morpheus.Types.Internal.TH (instanceHeadT, typeInstanceDec)
-import           Data.Morpheus.Types.IO          (GQLRequest (..), JSONResponse (..))
+import           Data.Morpheus.Types.Internal.TH
+                                                ( instanceHeadT
+                                                , typeInstanceDec
+                                                )
+import           Data.Morpheus.Types.IO         ( GQLRequest(..)
+                                                , JSONResponse(..)
+                                                )
 
 fixVars :: A.Value -> Maybe A.Value
-fixVars x
-  | x == A.emptyArray = Nothing
-  | otherwise         = Just x
+fixVars x | x == A.emptyArray = Nothing
+          | otherwise         = Just x
 
 class Fetch a where
   type Args a :: *
@@ -48,10 +57,11 @@
   fetch :: (Monad m, FromJSON a) => (ByteString -> m ByteString) -> Args a -> m (Either String a)
 
 deriveFetch :: Type -> String -> String -> Q [Dec]
-deriveFetch resultType typeName query = pure <$> instanceD (cxt []) iHead methods
-  where
-    iHead = instanceHeadT ''Fetch typeName []
-    methods =
-      [ funD 'fetch [clause [] (normalB [|__fetch query typeName|]) []]
-      , pure $ typeInstanceDec  ''Args  (ConT $ mkName typeName) resultType
-      ]
+deriveFetch resultType typeName queryString =
+  pure <$> instanceD (cxt []) iHead methods
+ where
+  iHead = instanceHeadT ''Fetch typeName []
+  methods =
+    [ funD 'fetch [clause [] (normalB [|__fetch queryString typeName|]) []]
+    , pure $ typeInstanceDec ''Args (ConT $ mkName typeName) resultType
+    ]
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
@@ -6,201 +6,302 @@
 
 module Data.Morpheus.Execution.Client.Selection
   ( operationTypes
-  ) where
+  )
+where
 
-import           Data.Maybe                                    (fromMaybe)
-import           Data.Semigroup                                ((<>))
-import           Data.Text                                     (Text, pack, unpack)
+import           Data.Maybe                     ( fromMaybe )
+import           Data.Semigroup                 ( (<>) )
+import           Data.Text                      ( Text
+                                                , pack
+                                                , unpack
+                                                )
 --
 -- MORPHEUS
-import           Data.Morpheus.Error.Utils                     (globalErrorMessage)
-import           Data.Morpheus.Execution.Internal.GraphScanner (LibUpdater, resolveUpdates)
-import           Data.Morpheus.Execution.Internal.Utils        (nameSpaceType)
-import           Data.Morpheus.Types.Internal.AST.Operation    (DefaultValue, Operation (..), ValidOperation,
-                                                                Variable (..), VariableDefinitions, getOperationName)
-import           Data.Morpheus.Types.Internal.AST.Selection    (Selection (..), SelectionRec (..), SelectionSet,
-                                                                ValidSelection)
-import           Data.Morpheus.Types.Internal.Data             (DataField (..), DataType (..), DataTyCon (..),
-                                                                DataTypeKind (..), DataTypeLib (..), Key,
-                                                                TypeAlias (..), allDataTypes)
-import           Data.Morpheus.Types.Internal.DataD            (ConsD (..), GQLTypeD (..), TypeD (..))
-import           Data.Morpheus.Types.Internal.Validation       (GQLErrors, Validation)
-import           Data.Morpheus.Validation.Internal.Utils       (lookupType)
-import           Data.Set                                      (fromList, toList)
+import           Data.Morpheus.Error.Client.Client
+                                                ( deprecatedField )
+import           Data.Morpheus.Error.Utils      ( globalErrorMessage )
+import           Data.Morpheus.Execution.Internal.Utils
+                                                ( nameSpaceType )
+import           Data.Morpheus.Types.Internal.AST
+                                                ( DefaultValue
+                                                , Operation(..)
+                                                , ValidOperation
+                                                , Variable(..)
+                                                , VariableDefinitions
+                                                , getOperationName
+                                                , getOperationDataType
+                                                , Selection(..)
+                                                , SelectionRec(..)
+                                                , SelectionSet
+                                                , ValidSelection
+                                                , Ref(..) 
+                                                , DataField(..)
+                                                , DataTyCon(..)
+                                                , DataType(..)
+                                                , DataTypeKind(..)
+                                                , DataTypeLib(..)
+                                                , Key
+                                                , TypeAlias(..)
+                                                , DataEnumValue(..)
+                                                , allDataTypes
+                                                , lookupType
+                                                , ConsD(..)
+                                                , ClientType(..)
+                                                , TypeD(..)
+                                                , lookupDeprecated
+                                                , lookupDeprecatedReason
+                                                )
+import           Data.Morpheus.Types.Internal.Resolving
+                                                ( GQLErrors
+                                                , Validation
+                                                , Failure(..)
+                                                , Result(..)
+                                                , Position
+                                                , LibUpdater
+                                                , resolveUpdates
+                                                )
+import           Data.Set                       ( fromList
+                                                , toList
+                                                )
 
 removeDuplicates :: [Text] -> [Text]
 removeDuplicates = toList . fromList
 
 compileError :: Text -> GQLErrors
-compileError x = globalErrorMessage $ "Unhandled Compile Time Error: \"" <> x <> "\" ;"
+compileError x =
+  globalErrorMessage $ "Unhandled Compile Time Error: \"" <> x <> "\" ;"
 
-operationTypes :: DataTypeLib -> VariableDefinitions -> ValidOperation -> Validation (Maybe TypeD, [GQLTypeD])
+operationTypes
+  :: DataTypeLib
+  -> VariableDefinitions
+  -> ValidOperation
+  -> Validation (Maybe TypeD, [ClientType])
 operationTypes lib variables = genOperation
-  where
-    genOperation Operation {operationName, operationSelection} = do
-      (queryTypes, enums) <- genRecordType [] (getOperationName operationName) queryDataType operationSelection
-      inputTypeRequests <- resolveUpdates [] $ map (scanInputTypes lib . variableType . snd) variables
-      inputTypesAndEnums <- buildListedTypes (inputTypeRequests <> enums)
-      pure (rootArguments (getOperationName operationName <> "Args"), queryTypes <> inputTypesAndEnums)
-      where
-        queryDataType = DataObject $ snd $ query lib
-    -------------------------------------------------------------------------
-    buildListedTypes = fmap concat . traverse (buildInputType lib) . removeDuplicates
-    -------------------------------------------------------------------------
-    -- generates argument types for Operation Head
-    rootArguments :: Text -> Maybe TypeD
-    rootArguments argsName
-      | null variables = Nothing
-      | otherwise = Just rootArgumentsType
+ where
+  genOperation operation@Operation { operationName, operationSelection } = do
+    datatype            <- DataObject <$> getOperationDataType operation lib
+    (queryTypes, enums) <- genRecordType []
+                                         (getOperationName operationName)
+                                         datatype
+                                         operationSelection
+    inputTypeRequests <- resolveUpdates []
+      $ map (scanInputTypes lib . variableType . snd) variables
+    inputTypesAndEnums <- buildListedTypes (inputTypeRequests <> enums)
+    pure
+      ( rootArguments (getOperationName operationName <> "Args")
+      , queryTypes <> inputTypesAndEnums
+      )
+  -------------------------------------------------------------------------
+  buildListedTypes =
+    fmap concat . traverse (buildInputType lib) . removeDuplicates
+  -------------------------------------------------------------------------
+  -- generates argument types for Operation Head
+  rootArguments :: Text -> Maybe TypeD
+  rootArguments argsName | null variables = Nothing
+                         | otherwise      = Just rootArgumentsType
+
+   where
+    rootArgumentsType :: TypeD
+    rootArgumentsType = TypeD
+      { tName      = unpack argsName
+      , tNamespace = []
+      , tCons      = [ ConsD { cName   = unpack argsName
+                             , cFields = map fieldD variables
+                             }
+                     ]
+      , tMeta      = Nothing
+      }
+     where
+      fieldD :: (Text, Variable DefaultValue) -> DataField
+      fieldD (key, Variable { variableType, variableTypeWrappers }) = DataField
+        { fieldName     = key
+        , fieldArgs     = []
+        , fieldArgsType = Nothing
+        , fieldType     = TypeAlias { aliasWrappers = variableTypeWrappers
+                                    , aliasTyCon    = variableType
+                                    , aliasArgs     = Nothing
+                                    }
+        , fieldMeta     = Nothing
+        }
+  ---------------------------------------------------------
+  -- generates selection Object Types
+  genRecordType
+    :: [Key]
+    -> Key
+    -> DataType
+    -> SelectionSet
+    -> Validation ([ClientType], [Text])
+  genRecordType path name dataType recordSelSet = do
+    (con, subTypes, requests) <- genConsD (unpack name) dataType recordSelSet
+    pure
+      ( ClientType
+          { clientType = TypeD { tName
+                               , tNamespace = map unpack path
+                               , tCons      = [con]
+                               , tMeta      = Nothing
+                               }
+          , clientKind = KindObject Nothing
+          }
+        : subTypes
+      , requests
+      )
+   where
+    tName = unpack name
+    genConsD
+      :: String
+      -> DataType
+      -> SelectionSet
+      -> Validation (ConsD, [ClientType], [Text])
+    genConsD cName datatype selSet = do
+      (cFields, subTypes, requests) <- unzip3 <$> traverse genField selSet
+      pure (ConsD { cName, cFields }, concat subTypes, concat requests)
+     where
+      genField
+        :: (Text, ValidSelection)
+        -> Validation (DataField, [ClientType], [Text])
+      genField (fName, sel@Selection { selectionAlias, selectionPosition }) =
+        do
+          (fieldDataType, fieldType) <- lookupFieldType lib
+                                                        fieldPath
+                                                        datatype
+                                                        selectionPosition
+                                                        fName
+          (subTypes, requests) <- subTypesBySelection fieldDataType sel
+          pure
+            ( DataField { fieldName
+                        , fieldArgs     = []
+                        , fieldArgsType = Nothing
+                        , fieldType
+                        , fieldMeta     = Nothing
+                        }
+            , subTypes
+            , requests
+            )
+       where
+        fieldPath = path <> [fieldName]
+        -------------------------------
+        fieldName = fromMaybe fName selectionAlias
         ------------------------------------------
-      where
-        rootArgumentsType :: TypeD
-        rootArgumentsType =
-          TypeD
-            { tName = unpack argsName
-            , tNamespace = []
-            , tCons = [ConsD {cName = unpack argsName, cFields = map fieldD variables}]
-            }
-          where
-            fieldD :: (Text, Variable DefaultValue) -> DataField
-            fieldD (key, Variable {variableType, variableTypeWrappers}) =
-              DataField
-                { fieldName = key
-                , fieldArgs = []
-                , fieldArgsType = Nothing
-                , fieldType =
-                    TypeAlias {aliasWrappers = variableTypeWrappers, aliasTyCon = variableType, aliasArgs = Nothing}
-                , fieldHidden = False
-                }
-    ---------------------------------------------------------
-    -- generates selection Object Types
-    genRecordType :: [Key] -> Key -> DataType -> SelectionSet -> Validation ([GQLTypeD], [Text])
-    genRecordType path name dataType recordSelSet = do
-      (con, subTypes, requests) <- genConsD (unpack name) dataType recordSelSet
-      pure
-        ( GQLTypeD
-            { typeD = TypeD {tName, tNamespace = map unpack path, tCons = [con]}
-            , typeKindD = KindObject Nothing
-            , typeArgD = []
-            } :
-          subTypes
-        , requests)
-      where
-        tName = unpack name
-        genConsD :: String -> DataType -> SelectionSet -> Validation (ConsD, [GQLTypeD], [Text])
-        genConsD cName datatype selSet = do
-          cFields <- traverse genField selSet
-          (subTypes, requests) <- newFieldTypes datatype selSet
-          pure (ConsD {cName, cFields}, concat subTypes, concat requests)
-          ---------------------------------------------------------------------------------------------
-          where
-            genField :: (Text, ValidSelection) -> Validation DataField
-            genField (fieldName, sel@Selection { selectionAlias }) = genFieldD sel
-              where
-                fieldPath = path <> [fromMaybe fieldName selectionAlias]
-                -------------------------------
-                genFieldD Selection {selectionAlias = Just aliasFieldName} = do
-                  fieldType <- snd <$> lookupFieldType lib fieldPath datatype fieldName
-                  pure $ DataField {fieldName = aliasFieldName, fieldArgs = [], fieldArgsType = Nothing, fieldType, fieldHidden = False}
-                genFieldD _ = do
-                  fieldType <- snd <$> lookupFieldType lib fieldPath datatype fieldName
-                  pure $ DataField {fieldName, fieldArgs = [], fieldArgsType = Nothing, fieldType, fieldHidden = False}
-            ------------------------------------------------------------------------------------------------------------
-            newFieldTypes :: DataType -> SelectionSet -> Validation ([[GQLTypeD]], [[Text]])
-            newFieldTypes parentType seSet = unzip <$> mapM valSelection seSet
-              where
-                valSelection (key, selection@Selection { selectionAlias }) = do
-                  fieldDatatype <- fst <$> lookupFieldType lib fieldPath parentType key
-                  validateSelection fieldDatatype selection
-                  --------------------------------------------------------------------
-                  where
-                    fieldPath = path <> [fromMaybe key selectionAlias]
-                    --------------------------------------------------------------------
-                    validateSelection :: DataType -> ValidSelection -> Validation ([GQLTypeD], [Text])
-                    validateSelection dType Selection {selectionRec = SelectionField} = leafType dType
-                    --withLeaf buildLeaf dType
-                    validateSelection dType Selection {selectionRec = SelectionSet selectionSet} =
-                      genRecordType fieldPath (typeFrom [] dType) dType selectionSet
-                    ---- UNION
-                    validateSelection dType Selection {selectionRec = UnionSelection unionSelections} = do
-                      (tCons, subTypes, requests) <- unzip3 <$> mapM getUnionType unionSelections
-                      pure
-                        ( GQLTypeD
-                            { typeD =
-                                TypeD {tNamespace = map unpack fieldPath, tName = unpack $ typeFrom [] dType, tCons}
-                            , typeKindD = KindUnion
-                            , typeArgD = []
-                            } :
-                          concat subTypes
-                        , concat requests)
-                      where
-                        getUnionType (selectedTyName, selectionVariant) = do
-                          conDatatype <- getType lib selectedTyName
-                          genConsD (unpack selectedTyName) conDatatype selectionVariant
+        subTypesBySelection
+          :: DataType -> ValidSelection -> Validation ([ClientType], [Text])
+        subTypesBySelection dType Selection { selectionRec = SelectionField } =
+          leafType dType
+          --withLeaf buildLeaf dType
+        subTypesBySelection dType Selection { selectionRec = SelectionSet selectionSet }
+          = genRecordType fieldPath (typeFrom [] dType) dType selectionSet
+          ---- UNION
+        subTypesBySelection dType Selection { selectionRec = UnionSelection unionSelections }
+          = do
+            (tCons, subTypes, requests) <-
+              unzip3 <$> mapM getUnionType unionSelections
+            pure
+              ( ClientType
+                  { clientType = TypeD { tNamespace = map unpack fieldPath
+                                       , tName      = unpack $ typeFrom [] dType
+                                       , tCons
+                                       , tMeta      = Nothing
+                                       }
+                  , clientKind = KindUnion
+                  }
+                : concat subTypes
+              , concat requests
+              )
+         where
+          getUnionType (selectedTyName, selectionVariant) = do
+            conDatatype <- getType lib selectedTyName
+            genConsD (unpack selectedTyName) conDatatype selectionVariant
 
 scanInputTypes :: DataTypeLib -> Key -> LibUpdater [Key]
-scanInputTypes lib name collected
-  | name `elem` collected = pure collected
-  | otherwise = getType lib name >>= scanType
-  where
-    scanType (DataInputObject DataTyCon {typeData}) = resolveUpdates (name : collected) (map toInputTypeD typeData)
-      where
-        toInputTypeD :: (Text, DataField) -> LibUpdater [Key]
-        toInputTypeD (_, DataField {fieldType = TypeAlias {aliasTyCon}}) = scanInputTypes lib aliasTyCon
-    scanType (DataEnum DataTyCon {typeName}) = pure (collected <> [typeName])
-    scanType _ = pure collected
+scanInputTypes lib name collected | name `elem` collected = pure collected
+                                  | otherwise = getType lib name >>= scanType
+ where
+  scanType (DataInputObject DataTyCon { typeData }) = resolveUpdates
+    (name : collected)
+    (map toInputTypeD typeData)
+   where
+    toInputTypeD :: (Text, DataField) -> LibUpdater [Key]
+    toInputTypeD (_, DataField { fieldType = TypeAlias { aliasTyCon } }) =
+      scanInputTypes lib aliasTyCon
+  scanType (DataEnum DataTyCon { typeName }) = pure (collected <> [typeName])
+  scanType _ = pure collected
 
-buildInputType :: DataTypeLib -> Text -> Validation [GQLTypeD]
+buildInputType :: DataTypeLib -> Text -> Validation [ClientType]
 buildInputType lib name = getType lib name >>= subTypes
-  where
-    subTypes (DataInputObject DataTyCon {typeName, typeData}) = do
-      fields <- traverse toFieldD typeData
-      pure
-        [ GQLTypeD
-            { typeD =
-                TypeD
-                  { tName = unpack typeName
-                  , tNamespace = []
-                  , tCons = [ConsD {cName = unpack typeName, cFields = fields}]
-                  }
-            , typeArgD = []
-            , typeKindD = KindInputObject
-            }
-        ]
-          ----------------------------------------------------------------
-      where
-        toFieldD :: (Text, DataField) -> Validation DataField
-        toFieldD (_, field@DataField {fieldType}) = do
-          aliasTyCon <- typeFrom [] <$> getType lib (aliasTyCon fieldType)
-          pure $ field {fieldType = fieldType {aliasTyCon}}
-    subTypes (DataEnum DataTyCon {typeName, typeData}) =
-      pure
-        [ GQLTypeD
-            { typeD = TypeD {tName = unpack typeName, tNamespace = [], tCons = map enumOption typeData}
-            , typeArgD = []
-            , typeKindD = KindEnum
-            }
-        ]
-      where
-        enumOption eName = ConsD {cName = unpack eName, cFields = []}
-    subTypes _ = pure []
+ where
+  subTypes (DataInputObject DataTyCon { typeName, typeData }) = do
+    fields <- traverse toFieldD typeData
+    pure
+      [ ClientType
+          { clientType =
+            TypeD
+              { tName      = unpack typeName
+              , tNamespace = []
+              , tCons = [ConsD { cName = unpack typeName, cFields = fields }]
+              , tMeta      = Nothing
+              }
+          , clientKind = KindInputObject
+          }
+      ]
 
-lookupFieldType :: DataTypeLib -> [Key] -> DataType -> Text -> Validation (DataType, TypeAlias)
-lookupFieldType lib path (DataObject DataTyCon {typeData}) key =
-  case lookup key typeData of
-    Just DataField {fieldType = alias@TypeAlias {aliasTyCon}} -> trans <$> getType lib aliasTyCon
-      where trans x = (x, alias {aliasTyCon = typeFrom path x, aliasArgs = Nothing})
-    Nothing -> Left (compileError $ "cant find field \""<> key<>"\"")
-lookupFieldType _ _ dt _ = Left (compileError $ "Type should be output Object \"" <> pack (show dt))
+   where
+    toFieldD :: (Text, DataField) -> Validation DataField
+    toFieldD (_, field@DataField { fieldType }) = do
+      aliasTyCon <- typeFrom [] <$> getType lib (aliasTyCon fieldType)
+      pure $ field { fieldType = fieldType { aliasTyCon } }
+  subTypes (DataEnum DataTyCon { typeName, typeData }) = pure
+    [ ClientType
+        { clientType = TypeD { tName      = unpack typeName
+                             , tNamespace = []
+                             , tCons      = map enumOption typeData
+                             , tMeta      = Nothing
+                             }
+        , clientKind = KindEnum
+        }
+    ]
+   where
+    enumOption DataEnumValue { enumName } =
+      ConsD { cName = unpack enumName, cFields = [] }
+  subTypes _ = pure []
 
 
-leafType :: DataType -> Validation ([GQLTypeD], [Text])
-leafType (DataEnum DataTyCon {typeName}) = pure ([],[typeName])
-leafType DataScalar {}                   = pure ([],[])
-leafType _                               = Left $ compileError "Invalid schema Expected scalar"
+lookupFieldType
+  :: DataTypeLib
+  -> [Key]
+  -> DataType
+  -> Position
+  -> Text
+  -> Validation (DataType, TypeAlias)
+lookupFieldType lib path (DataObject DataTyCon { typeData, typeName }) refPosition key
+  = case lookup key typeData of
+    Just DataField { fieldType = alias@TypeAlias { aliasTyCon }, fieldMeta } ->
+      checkDeprecated >> (trans <$> getType lib aliasTyCon)
+     where
+      trans x =
+        (x, alias { aliasTyCon = typeFrom path x, aliasArgs = Nothing })
+      ------------------------------------------------------------------
+      checkDeprecated :: Validation ()
+      checkDeprecated = case fieldMeta >>= lookupDeprecated of
+        Just deprecation -> Success { result = (), warnings, events = [] }
+         where
+          warnings = deprecatedField typeName
+                                     Ref { refName = key, refPosition }
+                                     (lookupDeprecatedReason deprecation)
+        Nothing -> pure ()
+    ------------------
+    Nothing -> failure
+      (compileError $ "cant find field \"" <> pack (show typeData) <> "\"")
+lookupFieldType _ _ dt _ _ =
+  failure (compileError $ "Type should be output Object \"" <> pack (show dt))
 
+
+leafType :: DataType -> Validation ([ClientType], [Text])
+leafType (DataEnum DataTyCon { typeName }) = pure ([], [typeName])
+leafType DataScalar{} = pure ([], [])
+leafType _ = failure $ compileError "Invalid schema Expected scalar"
+
 getType :: DataTypeLib -> Text -> Validation DataType
-getType lib typename = lookupType (compileError typename) (allDataTypes lib) typename
+getType lib typename =
+  lookupType (compileError typename) (allDataTypes lib) typename
 
 typeFromScalar :: Text -> Text
 typeFromScalar "Boolean" = "Bool"
@@ -211,9 +312,9 @@
 typeFromScalar _         = "ScalarValue"
 
 typeFrom :: [Key] -> DataType -> Text
-typeFrom _ (DataScalar DataTyCon {typeName}) = typeFromScalar typeName
-typeFrom _ (DataEnum x)                      = typeName x
-typeFrom _ (DataInputObject x)               = typeName x
-typeFrom path (DataObject x)                 = pack $ nameSpaceType path $ typeName x
-typeFrom path (DataUnion x)                  = pack $ nameSpaceType path $ typeName x
-typeFrom _ (DataInputUnion x)                = typeName x
+typeFrom _ (DataScalar DataTyCon { typeName }) = typeFromScalar typeName
+typeFrom _ (DataEnum x) = typeName x
+typeFrom _ (DataInputObject x) = typeName x
+typeFrom path (DataObject x) = pack $ nameSpaceType path $ typeName x
+typeFrom path (DataUnion x) = pack $ nameSpaceType path $ typeName x
+typeFrom _ (DataInputUnion 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,47 +1,61 @@
-{-# LANGUAGE NamedFieldPuns #-}
+{-#LANGUAGE NamedFieldPuns #-}
 
 module Data.Morpheus.Execution.Document.Compile
   ( compileDocument
   , gqlDocument
   , gqlDocumentNamespace
-  ) where
+  )
+where
 
-import qualified Data.Text                                    as T (pack)
+import qualified Data.Text                     as T
+                                                ( pack )
 import           Language.Haskell.TH
 import           Language.Haskell.TH.Quote
 
 --
 --  Morpheus
-import           Data.Morpheus.Error.Client.Client            (renderGQLErrors)
-import           Data.Morpheus.Execution.Document.Convert     (renderTHTypes)
-import           Data.Morpheus.Execution.Document.Declare     (declareTypes)
-import           Data.Morpheus.Parsing.Document.Parser        (parseTypes)
+import           Data.Morpheus.Error.Client.Client
+                                                ( renderGQLErrors
+                                                , gqlWarnings
+                                                )
+import           Data.Morpheus.Execution.Document.Convert
+                                                ( renderTHTypes )
+import           Data.Morpheus.Execution.Document.Declare
+                                                ( declareTypes )
+import           Data.Morpheus.Parsing.Document.Parser
+                                                ( parseTypes )
 import           Data.Morpheus.Validation.Document.Validation
+import           Data.Morpheus.Types.Internal.Resolving
+                                                ( Result(..) )
 
+
 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"
+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"
 
 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"
+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
+  case
+      parseTypes (T.pack documentTXT)
+      >>= validatePartialDocument
+      >>= renderTHTypes namespace
+    of
+      Failure errors -> fail (renderGQLErrors errors)
+      Success { result = schema, warnings } ->
+        gqlWarnings warnings >> 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
@@ -6,140 +6,180 @@
 
 module Data.Morpheus.Execution.Document.Convert
   ( renderTHTypes
-  ) where
+  )
+where
 
-import           Data.Semigroup                          ((<>))
-import           Data.Text                               (Text, pack, unpack)
+import           Data.Semigroup                 ( (<>) )
+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       (ArgsType (..), DataField (..), DataType (..),
-                                                          DataTyCon (..), DataTypeKind (..), OperationType (..),
-                                                          ResolverKind (..), TypeAlias (..), sysTypes)
-import           Data.Morpheus.Types.Internal.DataD      (ConsD (..), GQLTypeD (..), TypeD (..))
-import           Data.Morpheus.Types.Internal.Validation (Validation)
+import           Data.Morpheus.Error.Internal   ( internalError )
+import           Data.Morpheus.Execution.Internal.Utils
+                                                ( capital )
+import           Data.Morpheus.Types.Internal.AST
+                                                ( ArgsType(..)
+                                                , DataField(..)
+                                                , DataTyCon(..)
+                                                , DataType(..)
+                                                , DataTypeKind(..)
+                                                , OperationType(..)
+                                                , ResolverKind(..)
+                                                , TypeAlias(..)
+                                                , DataEnumValue(..)
+                                                , sysTypes
+                                                , ConsD(..)
+                                                , GQLTypeD(..)
+                                                , TypeD(..)
+                                                )
+import           Data.Morpheus.Types.Internal.Resolving
+                                                ( Validation )
 
 renderTHTypes :: Bool -> [(Text, DataType)] -> Validation [GQLTypeD]
 renderTHTypes namespace lib = traverse renderTHType lib
-  where
-    renderTHType :: (Text, DataType) -> Validation GQLTypeD
-    renderTHType (tyConName, x) = genType x
-      where
-        genArgsTypeName fieldName
-          | namespace = sysName tyConName <> argTName
-          | otherwise = argTName
-          where
-            argTName = capital fieldName <> "Args"
-        genArgumentType :: (Text, DataField) -> Validation [TypeD]
-        genArgumentType (_, DataField {fieldArgs = []}) = pure []
-        genArgumentType (fieldName, DataField {fieldArgs}) =
-          pure
-            [ TypeD
-                { tName
-                , tNamespace = []
-                , 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 DataObject {} -> Just "m"
-                Just DataUnion {}  -> 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 DataObject {} -> TypeVarResolver
-                    Just DataUnion {}  -> TypeVarResolver
-                    Just _             -> PlainResolver
-        --------------------------------------------
-        genType (DataEnum DataTyCon {typeName, typeData}) =
-          pure
-            GQLTypeD
-              { typeD = TypeD {tName = sysName typeName, tNamespace = [], tCons = map enumOption typeData}
-              , typeKindD = KindEnum
-              , typeArgD = []
-              }
-          where
-            enumOption name = ConsD {cName = sysName name, cFields = []}
-        genType (DataScalar _) = internalError "Scalar Types should defined By Native Haskell Types"
-        genType (DataInputUnion _) = internalError "Input Unions not Supported"
-        genType (DataInputObject DataTyCon {typeName, typeData}) =
-          pure
-            GQLTypeD
-              { typeD =
-                  TypeD
-                    { tName = sysName typeName
-                    , tNamespace = []
-                    , tCons = [ConsD {cName = sysName typeName, cFields = map genField typeData}]
-                    }
-              , typeKindD = KindInputObject
-              , typeArgD = []
+ where
+  renderTHType :: (Text, DataType) -> Validation GQLTypeD
+  renderTHType (tyConName, x) = genType x
+   where
+    genArgsTypeName fieldName | namespace = sysName tyConName <> argTName
+                              | otherwise = argTName
+      where argTName = capital fieldName <> "Args"
+    genArgumentType :: (Text, DataField) -> Validation [TypeD]
+    genArgumentType (_        , DataField { fieldArgs = [] }) = pure []
+    genArgumentType (fieldName, DataField { fieldArgs }     ) = pure
+      [ TypeD
+          { tName
+          , tNamespace = []
+          , tCons      = [ ConsD { cName   = sysName $ pack tName
+                                 , cFields = map genField fieldArgs
+                                 }
+                         ]
+          , tMeta      = Nothing
+          }
+      ]
+      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 }
               }
-        genType (DataObject DataTyCon {typeName, typeData}) = do
-          typeArgD <- concat <$> traverse genArgumentType typeData
-          pure
-            GQLTypeD
-              { typeD =
-                  TypeD
-                    { tName = sysName typeName
-                    , tNamespace = []
-                    , tCons = [ConsD {cName = sysName typeName, cFields = map genResField typeData}]
-                    }
-              , typeKindD =
-                  if typeName == "Subscription"
-                    then KindObject (Just Subscription)
-                    else KindObject Nothing
-              , typeArgD
+    ---------------------------------------------------------------------------------------------
+    genResField :: (Text, DataField) -> DataField
+    genResField (_, field@DataField { fieldName, fieldArgs, fieldType = alias@TypeAlias { aliasTyCon } })
+      = field { fieldType     = alias { aliasTyCon = ftName, aliasArgs }
+              , fieldArgsType
               }
-        genType (DataUnion DataTyCon {typeName, typeData}) = do
-          let tCons = map unionCon typeData
-          pure
-            GQLTypeD
-              {typeD = TypeD {tName = unpack typeName, tNamespace = [], 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
+      ftName    = genFieldTypeName aliasTyCon
+      ---------------------------------------
+      aliasArgs = case lookup aliasTyCon lib of
+        Just DataObject{} -> Just "m"
+        Just DataUnion{}  -> 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 DataObject{} -> TypeVarResolver
+          Just DataUnion{}  -> TypeVarResolver
+          Just _            -> PlainResolver
+    --------------------------------------------
+    genType dt@(DataEnum DataTyCon { typeName, typeData, typeMeta }) = pure
+      GQLTypeD
+        { typeD        = TypeD { tName      = sysName typeName
+                               , tNamespace = []
+                               , tCons      = map enumOption typeData
+                               , tMeta      = typeMeta
+                               }
+        , typeKindD    = KindEnum
+        , typeArgD     = []
+        , typeOriginal = (typeName, dt)
+        }
+     where
+      enumOption DataEnumValue { enumName } =
+        ConsD { cName = sysName enumName, cFields = [] }
+    genType (DataScalar _) =
+      internalError "Scalar Types should defined By Native Haskell Types"
+    genType (DataInputUnion _) = internalError "Input Unions not Supported"
+    genType dt@(DataInputObject DataTyCon { typeName, typeData, typeMeta }) =
+      pure GQLTypeD
+        { typeD        =
+          TypeD
+            { tName      = sysName typeName
+            , tNamespace = []
+            , tCons      = [ ConsD { cName   = sysName typeName
+                                   , cFields = map genField typeData
+                                   }
+                           ]
+            , tMeta      = typeMeta
+            }
+        , typeKindD    = KindInputObject
+        , typeArgD     = []
+        , typeOriginal = (typeName, dt)
+        }
+    genType dt@(DataObject DataTyCon { typeName, typeData, typeMeta }) = do
+      typeArgD <- concat <$> traverse genArgumentType typeData
+      pure GQLTypeD
+        { typeD        = TypeD
+                           { tName      = sysName typeName
+                           , tNamespace = []
+                           , tCons = [ ConsD { cName = sysName typeName
+                                             , cFields = map genResField typeData
+                                             }
+                                     ]
+                           , tMeta      = typeMeta
+                           }
+        , typeKindD    = if typeName == "Subscription"
+                           then KindObject (Just Subscription)
+                           else KindObject Nothing
+        , typeArgD
+        , typeOriginal = (typeName, dt)
+        }
+    genType dt@(DataUnion DataTyCon { typeName, typeData, typeMeta }) = do
+      let tCons = map unionCon typeData
+      pure GQLTypeD
+        { typeD        = TypeD { tName      = unpack typeName
+                               , tNamespace = []
+                               , tCons
+                               , tMeta      = typeMeta
+                               }
+        , typeKindD    = KindUnion
+        , typeArgD     = []
+        , typeOriginal = (typeName, dt)
+        }
+     where
+      unionCon memberName = ConsD
+        { cName
+        , cFields = [ DataField
+                        { fieldName     = pack $ "un" <> cName
+                        , fieldType     = TypeAlias { aliasTyCon = pack utName
+                                                    , aliasArgs = Just "m"
+                                                    , aliasWrappers = []
+                                                    }
+                        , fieldMeta     = Nothing
+                        , fieldArgs     = []
+                        , fieldArgsType = Nothing
                         }
                     ]
-                }
-              where
-                cName = sysName typeName <> utName
-                utName = sysName $ aliasTyCon fieldType
+        }
+       where
+        cName  = sysName typeName <> utName
+        utName = sysName memberName
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
@@ -4,51 +4,67 @@
 
 module Data.Morpheus.Execution.Document.Declare
   ( declareTypes
-  ) where
+  )
+where
 
-import           Data.Semigroup                              ((<>))
+import           Data.Semigroup                 ( (<>) )
 import           Language.Haskell.TH
 
 --
 -- MORPHEUS
-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    (declareType)
-import           Data.Morpheus.Types.Internal.Data           (isInput, isObject)
-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
+                                                , instanceIntrospect
+                                                )
+import           Data.Morpheus.Execution.Internal.Declare
+                                                ( declareType )
+import           Data.Morpheus.Types.Internal.AST
+                                                ( isInput
+                                                , isObject
+                                                , GQLTypeD(..)
+                                                )
 
 declareTypes :: Bool -> [GQLTypeD] -> Q [Dec]
 declareTypes namespace = fmap concat . traverse (declareGQLType namespace)
 
 declareGQLType :: Bool -> GQLTypeD -> Q [Dec]
-declareGQLType namespace gqlType@GQLTypeD {typeD, typeKindD, typeArgD} = do
-  mainType <- declareMainType
-  argTypes <- declareArgTypes
-  gqlInstances <- deriveGQLInstances
-  typeClasses <- deriveGQLType gqlType
-  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 (declareType namespace Nothing []) typeArgD
-        --------------------------------------------------
-    declareMainType = declareT
-      where
-        declareT = pure [declareType namespace (Just typeKindD) derivingClasses typeD]
-        derivingClasses
-          | isInput typeKindD = [''Show]
-          | otherwise = []
+declareGQLType namespace gqlType@GQLTypeD { typeD, typeKindD, typeArgD, typeOriginal }
+  = do
+    mainType       <- declareMainType
+    argTypes       <- declareArgTypes
+    gqlInstances   <- deriveGQLInstances
+    typeClasses    <- deriveGQLType gqlType
+    introspectEnum <- instanceIntrospect typeOriginal
+    pure $ mainType <> typeClasses <> argTypes <> gqlInstances <> introspectEnum
+ 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 (declareType namespace Nothing []) typeArgD
+      --------------------------------------------------
+  declareMainType = declareT
+   where
+    declareT =
+      pure [declareType 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
--- a/src/Data/Morpheus/Execution/Document/Decode.hs
+++ b/src/Data/Morpheus/Execution/Document/Decode.hs
@@ -7,29 +7,42 @@
 
 module Data.Morpheus.Execution.Document.Decode
   ( deriveDecode
-  ) where
+  )
+where
 
-import           Data.Text                               (Text)
+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)
+import           Data.Morpheus.Execution.Internal.Decode
+                                                ( decodeFieldWith
+                                                , decodeObjectExpQ
+                                                )
+import           Data.Morpheus.Execution.Server.Decode
+                                                ( Decode(..)
+                                                , DecodeObject(..)
+                                                )
+import           Data.Morpheus.Types.Internal.AST
+                                                ( TypeD(..)
+                                                , Object
+                                                )
+import           Data.Morpheus.Types.Internal.TH
+                                                ( instanceHeadT )
+import           Data.Morpheus.Types.Internal.Resolving
+                                                ( Validation )
 
+
 (.:) :: 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 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
--- a/src/Data/Morpheus/Execution/Document/Encode.hs
+++ b/src/Data/Morpheus/Execution/Document/Encode.hs
@@ -5,65 +5,98 @@
 
 module Data.Morpheus.Execution.Document.Encode
   ( deriveEncode
-  ) where
+  )
+where
 
-import           Data.Text                             (unpack)
-import           Data.Typeable                         (Typeable)
+import           Data.Text                      ( unpack )
+import           Data.Typeable                  ( Typeable )
 import           Language.Haskell.TH
-import           Data.Semigroup                        ((<>))
+import           Data.Semigroup                 ( (<>) )
 
 --
 -- MORPHEUS
-import           Data.Morpheus.Execution.Server.Encode (Encode (..), ObjectResolvers (..))
-import           Data.Morpheus.Types.GQLType           (TRUE)
-import           Data.Morpheus.Types.Internal.Data     (DataField (..), QUERY, SUBSCRIPTION, isSubscription)
-import           Data.Morpheus.Types.Internal.DataD    (ConsD (..), GQLTypeD (..), TypeD (..))
-import           Data.Morpheus.Types.Internal.Resolver (Resolver, MapGraphQLT (..), Resolving,PureOperation)
-import           Data.Morpheus.Types.Internal.TH       (applyT, destructRecord, instanceHeadMultiT, typeT)
+import           Data.Morpheus.Execution.Server.Encode
+                                                ( Encode(..)
+                                                , ObjectResolvers(..)
+                                                )
+import           Data.Morpheus.Types.GQLType    ( TRUE )
+import           Data.Morpheus.Types.Internal.AST
+                                                ( DataField(..)
+                                                , QUERY
+                                                , SUBSCRIPTION
+                                                , isSubscription
+                                                , ConsD(..)
+                                                , GQLTypeD(..)
+                                                , TypeD(..)
+                                                )
+import           Data.Morpheus.Types.Internal.Resolving
+                                                ( Resolver
+                                                , MapStrategy(..)
+                                                , LiftEither
+                                                , ResolvingStrategy
+                                                )
+import           Data.Morpheus.Types.Internal.TH
+                                                ( applyT
+                                                , destructRecord
+                                                , instanceHeadMultiT
+                                                , typeT
+                                                )
 
--- @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)]
---
---
- 
+encodeVars :: [String]
+encodeVars = ["e", "m"]
 
+encodeVarsT :: [TypeQ]
+encodeVarsT = map (varT . mkName) encodeVars
+
 deriveEncode :: GQLTypeD -> Q [Dec]
-deriveEncode GQLTypeD {typeKindD, typeD = TypeD {tName, tCons = [ConsD {cFields}]}} =
-  pure <$> instanceD (cxt constrains) appHead methods
-  where 
-    subARgs = conT ''SUBSCRIPTION : map (varT . mkName) ["m","e"]
-    instanceArgs
-          | isSubscription typeKindD = subARgs
-          | otherwise =  map (varT . mkName) ["o","m","e"]
-    mainType = applyT (mkName tName) [mainTypeArg]
-      where
-        mainTypeArg
-          | isSubscription typeKindD = applyT ''Resolver subARgs
-          | otherwise = typeT ''Resolver ["fieldOKind","m","e"] 
-    -----------------------------------------------------------------------------------------
+deriveEncode GQLTypeD { typeKindD, typeD = TypeD { tName, tCons = [ConsD { cFields }] } }
+  = pure <$> instanceD (cxt constrains) appHead methods
+ where
+  subARgs = conT ''SUBSCRIPTION : encodeVarsT
+  instanceArgs | isSubscription typeKindD = subARgs
+               | otherwise = map (varT . mkName) ("o" : encodeVars)
+  mainType = applyT (mkName tName) [mainTypeArg]
+   where
+    mainTypeArg | isSubscription typeKindD = applyT ''Resolver subARgs
+                | otherwise                = typeT ''Resolver (fo_ : encodeVars)
+  -----------------------------------------------------------------------------------------
+  fo_ = "fieldOperationKind"
+  po_ = "o"
+  ---------------------
+  typeables
+    | isSubscription typeKindD
+    = [applyT ''MapStrategy $ map conT [''QUERY, ''SUBSCRIPTION]]
+    | otherwise
+    = [ iLiftEither ''ResolvingStrategy
+      , iLiftEither ''Resolver
+      , typeT ''MapStrategy [fo_, po_]
+      , iTypeable fo_
+      , iTypeable po_
+      ]
+  -------------------------
+  iLiftEither name = applyT ''LiftEither [varT $ mkName fo_, conT name]
+  -------------------------
+  iTypeable name = typeT ''Typeable [name]
+  -------------------------------------------
+  -- defines Constraint: (Typeable m, Monad m)
+  constrains =
     typeables
-         | isSubscription typeKindD =  [applyT ''MapGraphQLT $ map conT [''QUERY, ''SUBSCRIPTION],applyT ''Resolving [conT ''QUERY, varT $ mkName "m", varT $ mkName "e"]]
-         | otherwise = [typeT ''PureOperation ["fieldOKind"],typeT ''MapGraphQLT ["fieldOKind","o"] , typeT ''Resolving ["fieldOKind","m","e"] , typeT ''Typeable ["fieldOKind"] , typeT ''Typeable ["o"]]
-    -- defines Constraint: (Typeable m, Monad m)
-    constrains = typeables <>[typeT ''Monad ["m"], applyT ''Encode (mainType:instanceArgs) , typeT ''Typeable ["m"],typeT ''Typeable ["e"]]
-    -------------------------------------------------------------------
-    -- defines: instance <constraint> =>  ObjectResolvers ('TRUE) (<Type> (ResolveT m)) (ResolveT m value) where
-    appHead = instanceHeadMultiT ''ObjectResolvers (conT ''TRUE) (mainType: instanceArgs)
-    ------------------------------------------------------------------
-    -- defines: objectResolvers <Type field1 field2 ...> = [("field1",encode field1),("field2",encode field2), ...]
-    methods = [funD 'objectResolvers [clause argsE (normalB body) []]]
-      where
-        argsE = [varP (mkName "_"), destructRecord tName varNames]
-        body = listE $ map decodeVar varNames
-        decodeVar name = [|(name, encode $(varName))|]
-          where
-            varName = varE $ mkName name
-        varNames = map (unpack . fieldName) cFields
+      <> [ typeT ''Monad ["m"]
+         , applyT ''Encode (mainType : instanceArgs)
+         , iTypeable "e"
+         , iTypeable "m"
+         ]
+  -------------------------------------------------------------------
+  -- defines: instance <constraint> =>  ObjectResolvers ('TRUE) (<Type> (ResolveT m)) (ResolveT m value) where
+  appHead =
+    instanceHeadMultiT ''ObjectResolvers (conT ''TRUE) (mainType : instanceArgs)
+  ------------------------------------------------------------------
+  -- defines: objectResolvers <Type field1 field2 ...> = [("field1",encode field1),("field2",encode field2), ...]
+  methods = [funD 'objectResolvers [clause argsE (normalB body) []]]
+   where
+    argsE = [varP (mkName "_"), destructRecord tName 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
@@ -6,67 +6,87 @@
 
 module Data.Morpheus.Execution.Document.GQLType
   ( deriveGQLType
-  ) where
+  )
+where
 
-import           Data.Text                                (pack)
+import           Data.Text                      ( pack
+                                                , unpack
+                                                )
 import           Language.Haskell.TH
-
+import           Data.Semigroup                 ( (<>) )
 --
 -- MORPHEUS
-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, isSchemaTypeName)
-import           Data.Morpheus.Types.Internal.DataD       (GQLTypeD (..), TypeD (..))
-import           Data.Morpheus.Types.Internal.TH          (instanceHeadT, typeT, typeInstanceDec)
-import           Data.Typeable                            (Typeable)
+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.AST
+                                                ( DataTypeKind(..)
+                                                , Meta(..)
+                                                , isObject
+                                                , isSchemaTypeName
+                                                , GQLTypeD(..)
+                                                , TypeD(..)
+                                                )
+import           Data.Morpheus.Types.Internal.TH
+                                                ( instanceHeadT
+                                                , typeT
+                                                , typeInstanceDec
+                                                , instanceProxyFunD
+                                                )
+import           Data.Typeable                  ( Typeable )
 
 genTypeName :: String -> String
-genTypeName ('S':name)
-  | isSchemaTypeName (pack name) = name
+genTypeName ('S' : name) | isSchemaTypeName (pack name) = name
 genTypeName name = name
 
-
-
 deriveGQLType :: GQLTypeD -> Q [Dec]
-deriveGQLType GQLTypeD {typeD = TypeD {tName}, typeKindD} =
-  pure <$> instanceD (cxt constrains) iHead (def__typeName : typeFamilies)
-  where
-    def__typeName = funD '__typeName [clause argsE (normalB body) []]
-      where
-        body = [|pack name|]
-          where
-            name = genTypeName tName
-    -- defines method: __typeName _ = tName
-    argsE = map (varP . mkName) ["_"]
-    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 $ typeInstanceDec ''CUSTOM typeN (ConT ''TRUE)
-        ---------------------------------------------------------------
-        deriveKind = do
-          typeN <- headSig
-          pure $ typeInstanceDec ''KIND 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
+deriveGQLType GQLTypeD { typeD = TypeD { tName, tMeta }, typeKindD } =
+  pure <$> instanceD (cxt constrains) iHead (functions <> typeFamilies)
+ where
+  functions = map
+    instanceProxyFunD
+    [ ('__typeName , [|pack (genTypeName tName)|])
+    , ('description, descriptionValue)
+    ]
+   where
+    descriptionValue = case tMeta >>= metaDescription of
+      Nothing -> [| Nothing  |]
+      Just x  -> [| Just (pack desc)|] where desc = unpack x
+  -------------------------------------------------
+  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 $ typeInstanceDec ''CUSTOM typeN (ConT ''TRUE)
+    ---------------------------------------------------------------
+    deriveKind = do
+      typeN <- headSig
+      pure $ typeInstanceDec ''KIND 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
--- a/src/Data/Morpheus/Execution/Document/Introspect.hs
+++ b/src/Data/Morpheus/Execution/Document/Introspect.hs
@@ -4,32 +4,43 @@
 {-# LANGUAGE TemplateHaskell   #-}
 
 module Data.Morpheus.Execution.Document.Introspect
-  ( deriveObjectRep
+  ( deriveObjectRep , instanceIntrospect
   ) where
 
+import Data.Maybe(maybeToList)
 import           Data.Proxy                                (Proxy (..))
 import           Data.Text                                 (unpack)
 import           Data.Typeable                             (Typeable)
-import           Language.Haskell.TH
+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)
+import           Data.Morpheus.Types.Internal.AST          (ConsD (..), TypeD (..), ArgsType (..),Key, DataType(..), DataField (..),insertType,DataTypeKind(..), TypeAlias (..))
+import           Data.Morpheus.Types.Internal.TH           (instanceFunD, instanceProxyFunD,instanceHeadT, instanceHeadMultiT, typeT)
 
+
+instanceIntrospect :: (Key,DataType) -> Q [Dec]
+-- FIXME: dirty fix for introspection
+instanceIntrospect ("__DirectiveLocation",_) = pure []
+instanceIntrospect ("__TypeKind",_) = pure []
+instanceIntrospect (name, DataEnum enumType) =
+  pure <$> instanceD (cxt []) iHead [defineIntrospect]
+  where
+    -----------------------------------------------
+    iHead = instanceHeadT ''Introspect  (unpack name) []
+    defineIntrospect = instanceProxyFunD ('introspect,body)
+      where
+        body =[| insertType (name, DataEnum enumType) |]
+instanceIntrospect _ = pure []
+
 -- [((Text, DataField), TypeUpdater)]
 deriveObjectRep :: (TypeD, Maybe DataTypeKind) -> Q [Dec]
 deriveObjectRep (TypeD {tName, tCons = [ConsD {cFields}]}, tKind) =
-  pure <$> instanceWithOverlapD overlapping (cxt constrains) iHead methods
+  pure <$> instanceD (cxt constrains) iHead methods
   where
-    overlapping = Just Overlapping
-    typeArgs =
-      case tKind of
-        Just typeKind -> tyConArgs typeKind
-        Nothing       -> []
+    typeArgs = concatMap tyConArgs (maybeToList tKind)
     constrains = map conTypeable typeArgs
       where
         conTypeable name = typeT ''Typeable [name]
@@ -61,14 +72,14 @@
 buildFields :: [DataField] -> ExpQ
 buildFields = listE . map buildField
   where
-    buildField DataField {fieldName, fieldArgs, fieldType = alias@TypeAlias {aliasArgs, aliasWrappers}} =
+    buildField DataField {fieldName, fieldArgs, fieldType = alias@TypeAlias {aliasArgs, aliasWrappers}, fieldMeta} =
       [|( fName
         , DataField
             { fieldName = fName
             , fieldArgs = fArgs
             , fieldArgsType = Nothing
             , fieldType = TypeAlias {aliasTyCon = __typeName $(proxyT alias), aliasArgs = aArgs, aliasWrappers}
-            , fieldHidden = False
+            , fieldMeta
             })|]
       where
         fName = unpack fieldName
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
@@ -10,74 +10,92 @@
 module Data.Morpheus.Execution.Internal.Declare
   ( declareType
   , tyConArgs
-  ) where
+  )
+where
 
-import           Data.Maybe                             (maybe)
-import           Data.Text                              (pack, unpack)
-import           GHC.Generics                           (Generic)
+import           Data.Maybe                     ( maybe )
+import           Data.Text                      ( pack
+                                                , unpack
+                                                )
+import           GHC.Generics                   ( Generic )
 import           Language.Haskell.TH
 
 -- MORPHEUS
-import           Data.Morpheus.Execution.Internal.Utils (nameSpaceType, 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.Internal.Resolver  (UnSubResolver)
+import           Data.Morpheus.Execution.Internal.Utils
+                                                ( nameSpaceType
+                                                , nameSpaceWith
+                                                )
+import           Data.Morpheus.Types.Internal.AST
+                                                ( ArgsType(..)
+                                                , DataField(..)
+                                                , DataTypeKind(..)
+                                                , DataTypeKind(..)
+                                                , TypeAlias(..)
+                                                , TypeWrapper(..)
+                                                , isOutputObject
+                                                , isSubscription
+                                                , ConsD(..)
+                                                , TypeD(..)
+                                                )
+import           Data.Morpheus.Types.Internal.Resolving
+                                                ( UnSubResolver )
 
 type Arrow = (->)
 
 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
+declareTypeAlias isSub TypeAlias { aliasTyCon, aliasWrappers, aliasArgs } =
+  wrappedT aliasWrappers
+ where
+  wrappedT :: [TypeWrapper] -> Type
+  wrappedT (TypeList  : xs) = AppT (ConT ''[]) $ wrappedT xs
+  wrappedT (TypeMaybe : 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 = []
+tyConArgs kindD | isOutputObject kindD || kindD == KindUnion = ["m"]
+                | otherwise = []
 
 -- declareType
 declareType :: Bool -> Maybe DataTypeKind -> [Name] -> TypeD -> Dec
-declareType namespace kindD derivingList TypeD {tName, tCons, tNamespace} =
-  DataD [] (genName tName) tVars Nothing (map cons tCons) $ map derive (''Generic : derivingList)
-  where
-    genName = mkName . nameSpaceType (map pack tNamespace) . pack
-    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 (genName cName) (map declareField cFields)
-      where
-        declareField DataField {fieldName, fieldArgsType, fieldType} = (fName, defBang, fiType)
-          where
-            fName
-              | namespace = mkName (nameSpaceWith tName (unpack fieldName))
-              | otherwise = mkName (unpack fieldName)
-            fiType = genFieldT fieldArgsType
-              where
-                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 ''Arrow
-                ------------------------------------------------
-                fType isResolver
-                  | maybe False isSubscription kindD = AppT monadVar result
-                  | isResolver = AppT monadVar result
-                  | otherwise = result
-                ------------------------------------------------
-                result = declareTypeAlias (maybe False isSubscription kindD) fieldType
+declareType namespace kindD derivingList TypeD { tName, tCons, tNamespace } =
+  DataD [] (genName tName) tVars Nothing (map cons tCons)
+    $ map derive (''Generic : derivingList)
+ where
+  genName = mkName . nameSpaceType (map pack tNamespace) . pack
+  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 (genName cName)
+                                       (map declareField cFields)
+   where
+    declareField DataField { fieldName, fieldArgsType, fieldType } =
+      (fName, defBang, fiType)
+     where
+      fName | namespace = mkName (nameSpaceWith tName (unpack fieldName))
+            | otherwise = mkName (unpack fieldName)
+      fiType = genFieldT fieldArgsType
+       where
+        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 ''Arrow
+        ------------------------------------------------
+        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
--- a/src/Data/Morpheus/Execution/Internal/Decode.hs
+++ b/src/Data/Morpheus/Execution/Internal/Decode.hs
@@ -10,62 +10,74 @@
   , withUnion
   , decodeFieldWith
   , decodeObjectExpQ
-  ) where
+  )
+where
 
-import           Data.Semigroup                          ((<>))
-import           Data.Text                               (unpack)
-import           Language.Haskell.TH                     (ExpQ, conE, mkName, uInfixE, varE)
+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 (..))
+import           Data.Morpheus.Error.Internal   ( internalArgumentError
+                                                , internalTypeMismatch
+                                                )
+import           Data.Morpheus.Types.Internal.AST
+                                                ( DataField(..)
+                                                , Key
+                                                , ConsD(..) 
+                                                , Object
+                                                , Value(..))
+import           Data.Morpheus.Types.Internal.Resolving
+                                                ( Validation )
 
+
 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
+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
+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
+withList _      isType    = internalTypeMismatch "List" isType
 
 withEnum :: (Key -> Validation a) -> Value -> Validation a
 withEnum decode (Enum value) = decode value
-withEnum _ isType            = internalTypeMismatch "Enum" isType
+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"
+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
+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/Internal/GraphScanner.hs b/src/Data/Morpheus/Execution/Internal/GraphScanner.hs
deleted file mode 100644
--- a/src/Data/Morpheus/Execution/Internal/GraphScanner.hs
+++ /dev/null
@@ -1,14 +0,0 @@
-module Data.Morpheus.Execution.Internal.GraphScanner
-  ( LibUpdater
-  , resolveUpdates
-  ) where
-
-import           Control.Monad                           (foldM)
-import           Data.Function                           ((&))
-import           Data.Morpheus.Types.Internal.Validation (Validation)
-
-type LibUpdater lib = lib -> Validation lib
-
--- Helper Functions
-resolveUpdates :: lib -> [LibUpdater lib] -> Validation lib
-resolveUpdates = foldM (&)
diff --git a/src/Data/Morpheus/Execution/Internal/Utils.hs b/src/Data/Morpheus/Execution/Internal/Utils.hs
--- a/src/Data/Morpheus/Execution/Internal/Utils.hs
+++ b/src/Data/Morpheus/Execution/Internal/Utils.hs
@@ -4,11 +4,16 @@
   , nameSpaceWith
   , nameSpaceType
   , nameSpaceTypeString
-  ) where
+  )
+where
 
-import           Data.Char      (toLower, toUpper)
-import           Data.Semigroup ((<>))
-import           Data.Text      (Text, unpack)
+import           Data.Char                      ( toLower
+                                                , toUpper
+                                                )
+import           Data.Semigroup                 ( (<>) )
+import           Data.Text                      ( Text
+                                                , unpack
+                                                )
 
 
 nameSpaceTypeString :: [String] -> String -> String
@@ -21,9 +26,9 @@
 nameSpaceWith nSpace name = nonCapital nSpace <> capital name
 
 nonCapital :: String -> String
-nonCapital []     = []
-nonCapital (x:xs) = toLower x : xs
+nonCapital []       = []
+nonCapital (x : xs) = toLower x : xs
 
 capital :: String -> String
-capital []     = []
-capital (x:xs) = toUpper x : xs
+capital []       = []
+capital (x : xs) = toUpper x : xs
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
@@ -14,26 +14,49 @@
   ( decodeArguments
   , Decode(..)
   , DecodeObject(..)
-  ) where
+  )
+where
 
-import           Data.Proxy                                      (Proxy (..))
-import           Data.Semigroup                                  ((<>))
-import           Data.Text                                       (pack)
+import           Data.Proxy                     ( Proxy(..) )
+import           Data.Semigroup                 ( (<>) )
+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)
-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              (Object, Value (..))
+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
+                                                )
+import           Data.Morpheus.Types.GQLScalar  ( GQLScalar(..)
+                                                , toScalar
+                                                )
+import           Data.Morpheus.Types.GQLType    ( GQLType(KIND, __typeName) )
+import           Data.Morpheus.Types.Internal.AST
+                                                ( Key
+                                                , Argument(..)
+                                                , Arguments
+                                                , Object
+                                                , Value(..)
+                                                )
+import           Data.Morpheus.Types.Internal.Resolving
+                                                ( Validation )
 
+
 -- | Decode GraphQL query arguments and input values
 class Decode a where
   decode :: Value -> Validation a
@@ -53,10 +76,9 @@
 
 -- SCALAR
 instance (GQLScalar a) => DecodeKind SCALAR a where
-  decodeKind _ value =
-    case toScalar value >>= parseValue of
-      Right scalar      -> return scalar
-      Left errorMessage -> internalTypeMismatch errorMessage value
+  decodeKind _ value = case toScalar value >>= parseValue of
+    Right scalar       -> return scalar
+    Left  errorMessage -> internalTypeMismatch errorMessage value
 
 -- ENUM
 instance (Generic a, EnumRep (Rep a)) => DecodeKind ENUM a where
@@ -73,8 +95,7 @@
 -- GENERIC
 decodeArguments :: DecodeObject p => Arguments -> Validation p
 decodeArguments = decodeObject . fmap toObject
-  where
-    toObject (x, y) = (x, argumentValue y)
+  where toObject (x, y) = (x, argumentValue y)
 
 class DecodeObject a where
   decodeObject :: Object -> Validation a
@@ -98,11 +119,11 @@
 -- 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
+  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)
+   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
@@ -119,14 +140,15 @@
 
 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
+   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
@@ -19,109 +19,153 @@
   , encodeSubscription
   , encodeMutation
   , ObjectResolvers(..)
-  ) where
+  )
+where
 
-import           Data.Map                                        (Map)
-import qualified Data.Map                                        as M (toList)
-import           Data.Maybe                                      (fromMaybe)
-import           Data.Proxy                                      (Proxy (..))
-import           Data.Semigroup                                  ((<>))
-import           Data.Set                                        (Set)
-import qualified Data.Set                                        as S (toList)
-import           Data.Text                                       (pack)
+import           Data.Map                       ( Map )
+import qualified Data.Map                      as M
+                                                ( toList )
+import           Data.Maybe                     ( fromMaybe )
+import           Data.Proxy                     ( Proxy(..) )
+import           Data.Semigroup                 ( (<>) )
+import           Data.Set                       ( Set )
+import qualified Data.Set                      as S
+                                                ( toList )
+import           Data.Text                      ( pack )
 import           GHC.Generics
 
 -- MORPHEUS
-import           Data.Morpheus.Error.Internal                    (internalUnknownTypeMessage)
-import           Data.Morpheus.Execution.Server.Decode           (DecodeObject, decodeArguments)
-import           Data.Morpheus.Execution.Server.Generics.EnumRep (EnumRep (..))
-import           Data.Morpheus.Kind                              (ENUM, GQL_KIND, OBJECT, ResContext (..), SCALAR,
-                                                                  UNION, VContext (..))
-import           Data.Morpheus.Types.Custom                      (MapKind, Pair (..), mapKindFromList)
-import           Data.Morpheus.Types.GQLScalar                   (GQLScalar (..))
-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 (..), ValidSelection)
-import           Data.Morpheus.Types.Internal.Base               (Key)
-import           Data.Morpheus.Types.Internal.Data               (MUTATION, OperationType, QUERY, SUBSCRIPTION)
-import           Data.Morpheus.Types.Internal.Resolver           (MapGraphQLT (..), PureOperation (..), Resolver (..),
-                                                                  Resolving (..), ResolvingStrategy (..), resolveObject,
-                                                                  withObject)
-import           Data.Morpheus.Types.Internal.Validation         (Validation)
-import           Data.Morpheus.Types.Internal.Value              (GQLValue (..), Value (..))
+import           Data.Morpheus.Error.Internal   ( internalUnknownTypeMessage )
+import           Data.Morpheus.Execution.Server.Decode
+                                                ( DecodeObject
+                                                , decodeArguments
+                                                )
+import           Data.Morpheus.Execution.Server.Generics.EnumRep
+                                                ( EnumRep(..) )
+import           Data.Morpheus.Kind             ( ENUM
+                                                , GQL_KIND
+                                                , OBJECT
+                                                , ResContext(..)
+                                                , SCALAR
+                                                , UNION
+                                                , VContext(..)
+                                                )
+import           Data.Morpheus.Types.Types     ( MapKind
+                                                , Pair(..)
+                                                , mapKindFromList
+                                                )
+import           Data.Morpheus.Types.GQLScalar  ( GQLScalar(..) )
+import           Data.Morpheus.Types.GQLType    ( GQLType
+                                                  ( CUSTOM
+                                                  , KIND
+                                                  , __typeName
+                                                  )
+                                                )
+import           Data.Morpheus.Types.Internal.AST
+                                                ( Operation(..)
+                                                , ValidOperation
+                                                , Key,
+                                                  MUTATION
+                                                , OperationType
+                                                , QUERY
+                                                , SUBSCRIPTION
+                                                , Selection(..)
+                                                , SelectionRec(..)
+                                                , ValidSelection
+                                                , GQLValue(..)
+                                                , Value(..)
+                                                )
+import           Data.Morpheus.Types.Internal.Resolving
+                                                ( MapStrategy(..)
+                                                , LiftEither(..)
+                                                , Resolver(..)
+                                                , resolving
+                                                , toResolver
+                                                , ResolvingStrategy(..)
+                                                , resolveObject
+                                                , withObject
+                                                , Validation
+                                                , failure
+                                                )
 
-class Encode resolver o m e where
-  encode :: PureOperation o => resolver -> (Key, ValidSelection) -> ResolvingStrategy o m e Value
+class Encode resolver o e (m :: * -> *) where
+  encode :: resolver -> (Key, ValidSelection) -> ResolvingStrategy o e m Value
 
-instance {-# OVERLAPPABLE #-} (EncodeKind (KIND a) a o m e , PureOperation o) => Encode a o m e where
+instance {-# OVERLAPPABLE #-} (EncodeKind (KIND a) a o e m , LiftEither o ResolvingStrategy) => Encode a o e m where
   encode resolver = encodeKind (VContext resolver :: VContext (KIND a) a)
 
 -- MAYBE
-instance (Monad m , Encode a o m e) => Encode (Maybe a) o m e where
+instance (Monad m , LiftEither o ResolvingStrategy,Encode a o e m) => Encode (Maybe a) o e m where
   encode = maybe (const $ pure gqlNull) encode
 
 --  Tuple  (a,b)
-instance Encode (Pair k v) o m e => Encode (k, v) o m e where
+instance Encode (Pair k v) o e m => Encode (k, v) o e m where
   encode (key, value) = encode (Pair key value)
 
 --  Set
-instance Encode [a] o m e => Encode (Set a) o m e where
+instance Encode [a] o e m => Encode (Set a) o e m where
   encode = encode . S.toList
 
 --  Map
-instance (Eq k, Monad m, Encode (MapKind k v (Resolver o m e)) o m e) => Encode (Map k v)  o m e  where
-  encode value = encode ((mapKindFromList $ M.toList value) :: MapKind k v (Resolver o m e))
+instance (Eq k, Monad m,LiftEither o Resolver, Encode (MapKind k v (Resolver o e m)) o e m) => Encode (Map k v)  o e m where
+  encode value =
+    encode ((mapKindFromList $ M.toList value) :: MapKind k v (Resolver o e m))
 
 -- LIST []
-instance (Monad m, Encode a o m e) => Encode [a] o m e where
+instance (Monad m, Encode a o e m, LiftEither o ResolvingStrategy) => Encode [a] o e m where
   encode list query = gqlList <$> traverse (`encode` query) list
 
-
 --  GQL a -> Resolver b, MUTATION, SUBSCRIPTION, QUERY
-instance (DecodeObject a, Resolving fO m e ,Monad m,PureOperation fO, MapGraphQLT fO o, Encode b fO m e ) => Encode (a -> Resolver fO m e b) o m e where
-  encode resolver selection@(_, Selection { selectionArguments }) = mapGraphQLT $ resolving encode (getArgs args resolver)  selection
-     where
-      args :: Validation a
-      args =  decodeArguments selectionArguments
+instance (DecodeObject a, Monad m,LiftEither fo Resolver, MapStrategy fo o, Encode b fo e m) => Encode (a -> Resolver fo e m b) o e m where
+  encode resolver selection@(_, Selection { selectionArguments }) =
+    mapStrategy $ resolving encode (toResolver args resolver) selection
+   where
+    args :: Validation a
+    args = decodeArguments selectionArguments
 
 -- ENCODE GQL KIND
-class EncodeKind (kind :: GQL_KIND) a o m e  where
-  encodeKind :: PureOperation o =>  VContext kind a -> (Key, ValidSelection) -> ResolvingStrategy o m e Value
+class EncodeKind (kind :: GQL_KIND) a o e (m :: * -> *) where
+  encodeKind :: LiftEither o ResolvingStrategy =>  VContext kind a -> (Key, ValidSelection) -> ResolvingStrategy o e m Value
 
 -- SCALAR
-instance (GQLScalar a, Monad m) => EncodeKind SCALAR a o m e where
+instance (GQLScalar a, Monad m) => EncodeKind SCALAR a o e m where
   encodeKind = pure . pure . gqlScalar . serialize . unVContext
 
 -- ENUM
-instance (Generic a, EnumRep (Rep a), Monad m) => EncodeKind ENUM a o m e where
+instance (Generic a, EnumRep (Rep a), Monad m) => EncodeKind ENUM a o e m where
   encodeKind = pure . pure . gqlString . encodeRep . from . unVContext
 
 --  OBJECT
-instance (Monad m, EncodeCon o m e a, Monad m, GResolver OBJECT (Rep a) o m e) => EncodeKind OBJECT a o m e where
-  encodeKind (VContext value)  = withObject encodeK
-    where
-      encodeK selection = resolveObject selection (__typenameResolver : objectResolvers (Proxy :: Proxy (CUSTOM a)) value)
-      __typenameResolver = ("__typename", const $ pure $ gqlString $ __typeName (Proxy @a))
+instance (Monad m, EncodeCon o e m a, Monad m, GResolver OBJECT (Rep a) o e m) => EncodeKind OBJECT a o e m where
+  encodeKind (VContext value) = withObject encodeK
+   where
+    encodeK selection = resolveObject
+      selection
+      (__typenameResolver : objectResolvers (Proxy :: Proxy (CUSTOM a)) value)
+    __typenameResolver =
+      ("__typename", const $ pure $ gqlString $ __typeName (Proxy @a))
 
 -- exploreKindChannels
 -- UNION
-instance (Monad m, GQL_RES a, GResolver UNION (Rep a) o m e) => EncodeKind UNION a o m e 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 _ _ = Fail $ internalUnknownTypeMessage "union Resolver only should recieve UnionSelection"
+instance (Monad m, GQL_RES a, GResolver UNION (Rep a) o e m) => EncodeKind UNION a o e m where
+  encodeKind (VContext value) (key, sel@Selection { selectionRec = UnionSelection selections })
+    = resolver (key, sel { selectionRec = SelectionSet lookupSelection })
+   where
+    lookupSelection      = fromMaybe [] $ lookup typeName selections
+    (typeName, resolver) = unionResolver value
+  encodeKind _ _ = failure $ internalUnknownTypeMessage
+    "union Resolver only should recieve UnionSelection"
 
 -- Types & Constrains -------------------------------------------------------
 type GQL_RES a = (Generic a, GQLType a)
 
-type EncodeOperator o m e a  = a -> ValidOperation -> ResolvingStrategy o m e Value
+type EncodeOperator o e m a
+  = a -> ValidOperation -> ResolvingStrategy o e m Value
 
-type EncodeCon o m e a = (GQL_RES a,  ObjectResolvers (CUSTOM a) a o m e)
+type EncodeCon o e m a = (GQL_RES a, ObjectResolvers (CUSTOM a) a o e m)
 
-type FieldRes  o m e   = (Key, (Key, ValidSelection) -> ResolvingStrategy o m e Value)
+type FieldRes o e m
+  = (Key, (Key, ValidSelection) -> ResolvingStrategy o e m Value)
 
 type family GRes (kind :: GQL_KIND) value :: *
 
@@ -130,64 +174,82 @@
 type instance GRes UNION v = (Key, (Key, ValidSelection) -> v)
 
 --- GENERICS ------------------------------------------------
-class ObjectResolvers (custom :: Bool) a (o :: OperationType) (m :: * -> *) e where
-  objectResolvers :: PureOperation o =>  Proxy custom -> a -> [(Key, (Key, ValidSelection) -> ResolvingStrategy o m e Value)]
+class ObjectResolvers (custom :: Bool) a (o :: OperationType) e (m :: * -> *) where
+  objectResolvers :: Proxy custom -> a -> [(Key, (Key, ValidSelection) -> ResolvingStrategy o e m Value)]
 
-instance (Generic a, GResolver OBJECT (Rep a) o m e ) => ObjectResolvers 'False a o m e where
-  objectResolvers _ = getResolvers (ResContext :: ResContext OBJECT o m e value) . from
+instance (Generic a, GResolver OBJECT (Rep a) o e m ) => ObjectResolvers 'False a o e m where
+  objectResolvers _ =
+    getResolvers (ResContext :: ResContext OBJECT o e m value) . from
 
-unionResolver :: (Generic a, PureOperation o, GResolver UNION (Rep a) o m e) => a -> (Key, (Key, ValidSelection) -> ResolvingStrategy o m e Value)
-unionResolver = getResolvers (ResContext :: ResContext UNION o m e value) . from
+unionResolver
+  :: (Generic a, GResolver UNION (Rep a) o e m)
+  => a
+  -> (Key, (Key, ValidSelection) -> ResolvingStrategy o e m Value)
+unionResolver =
+  getResolvers (ResContext :: ResContext UNION o e m value) . from
 
 -- | Derives resolvers for OBJECT and UNION
-class GResolver (kind :: GQL_KIND) f o m e where
-  getResolvers :: PureOperation o => ResContext kind o m e value -> f a -> GRes kind (ResolvingStrategy o m e Value)
+class GResolver (kind :: GQL_KIND) f o e (m :: * -> *) where
+  getResolvers :: ResContext kind o e m value -> f a -> GRes kind (ResolvingStrategy o e m Value)
 
-instance GResolver kind f o m e => GResolver kind (M1 D c f) o m e where
+instance GResolver kind f o e m => GResolver kind (M1 D c f) o e m where
   getResolvers context (M1 src) = getResolvers context src
 
-instance GResolver kind f o m e => GResolver kind (M1 C c f) o m e where
+instance GResolver kind f o e m => GResolver kind (M1 C c f) o e m where
   getResolvers context (M1 src) = getResolvers context src
 
 -- OBJECT
-instance GResolver OBJECT U1 o m e where
+instance GResolver OBJECT U1 o e m where
   getResolvers _ _ = []
 
-instance (Selector s, GQLType a, Encode a o m e) => GResolver OBJECT (M1 S s (K1 s2 a)) o m e where
+instance (Selector s, GQLType a, Encode a o e m) => GResolver OBJECT (M1 S s (K1 s2 a)) o e m where
   getResolvers _ m@(M1 (K1 src)) = [(pack (selName m), encode src)]
 
-instance (GResolver OBJECT f o m e, GResolver OBJECT g o m e) => GResolver OBJECT (f :*: g) o m e where
-  getResolvers context (a :*: b)  = getResolvers context a  ++ getResolvers context b
+instance (GResolver OBJECT f o e m, GResolver OBJECT g o e m) => GResolver OBJECT (f :*: g) o e m where
+  getResolvers context (a :*: b) =
+    getResolvers context a ++ getResolvers context b
 
 -- UNION
-instance (Selector s, GQLType a, Encode a o m e ) => GResolver UNION (M1 S s (K1 s2 a)) o m e where
+instance (Selector s, GQLType a, Encode a o e m ) => GResolver UNION (M1 S s (K1 s2 a)) o e m where
   getResolvers _ (M1 (K1 src)) = (__typeName (Proxy @a), encode src)
 
-instance (GResolver UNION a o m e, GResolver UNION b o m e) => GResolver UNION (a :+: b) o m e where
+instance (GResolver UNION a o e m, GResolver UNION b o e m) => GResolver UNION (a :+: b) o e m where
   getResolvers context (L1 x) = getResolvers context x
   getResolvers context (R1 x) = getResolvers context x
 
 ----- HELPERS ----------------------------
-encodeQuery ::
-     forall m event query (schema :: (* -> *) -> *). (Monad m, EncodeCon QUERY m event (schema (Resolver QUERY m event)), EncodeCon QUERY m event query, Resolving QUERY m event)
-  => schema (Resolver QUERY m event)
-  -> EncodeOperator QUERY m event query
-encodeQuery schema = encodeOperationWith (objectResolvers (Proxy :: Proxy (CUSTOM (schema (Resolver QUERY m event)))) schema)
+encodeQuery
+  :: forall m event query (schema :: (* -> *) -> *)
+   . ( Monad m
+     , EncodeCon QUERY event m (schema (Resolver QUERY event m))
+     , EncodeCon QUERY event m query
+     )
+  => schema (Resolver QUERY event m)
+  -> EncodeOperator QUERY event m query
+encodeQuery schema = encodeOperationWith
+  (objectResolvers (Proxy :: Proxy (CUSTOM (schema (Resolver QUERY event m))))
+                   schema
+  )
 
-encodeMutation ::
-     forall m event mut. (Monad m, EncodeCon MUTATION m event mut, Resolving MUTATION m event)
-  => EncodeOperator MUTATION m event mut
+encodeMutation
+  :: forall event m mut
+   . (Monad m, EncodeCon MUTATION event m mut)
+  => EncodeOperator MUTATION event m mut
 encodeMutation = encodeOperationWith []
 
-encodeSubscription ::
-     forall m event mut. (Monad m, EncodeCon SUBSCRIPTION m event mut, Resolving SUBSCRIPTION m event)
-  => EncodeOperator SUBSCRIPTION m event mut
+encodeSubscription
+  :: forall m event mut
+   . (Monad m, EncodeCon SUBSCRIPTION event m mut)
+  => EncodeOperator SUBSCRIPTION event m mut
 encodeSubscription = encodeOperationWith []
 
-encodeOperationWith ::
-     forall o m e a . (Monad m, EncodeCon o m e a, Resolving o m e, PureOperation o)
-  => [FieldRes o m e]
-  -> EncodeOperator o m e a
-encodeOperationWith externalRes rootResolver Operation {operationSelection} = resolveObject operationSelection resolvers
-    where
-       resolvers = externalRes <> objectResolvers (Proxy :: Proxy (CUSTOM a)) rootResolver
+encodeOperationWith
+  :: forall o e m a
+   . (Monad m, EncodeCon o e m a, LiftEither o ResolvingStrategy)
+  => [FieldRes o e m]
+  -> EncodeOperator o e m a
+encodeOperationWith externalRes rootResolver Operation { operationSelection } =
+  resolveObject operationSelection resolvers
+ where
+  resolvers =
+    externalRes <> objectResolvers (Proxy :: Proxy (CUSTOM a)) rootResolver
diff --git a/src/Data/Morpheus/Execution/Server/Generics/EnumRep.hs b/src/Data/Morpheus/Execution/Server/Generics/EnumRep.hs
--- a/src/Data/Morpheus/Execution/Server/Generics/EnumRep.hs
+++ b/src/Data/Morpheus/Execution/Server/Generics/EnumRep.hs
@@ -6,16 +6,20 @@
 
 module Data.Morpheus.Execution.Server.Generics.EnumRep
   ( EnumRep(..)
-  ) where
+  )
+where
 
-import           Data.Proxy                              (Proxy (..))
-import           Data.Semigroup                          ((<>))
-import           Data.Text                               (Text, pack)
+import           Data.Proxy                     ( Proxy(..) )
+import           Data.Semigroup                 ( (<>) )
+import           Data.Text                      ( Text
+                                                , pack
+                                                )
 import           GHC.Generics
 
 -- MORPHEUS
-import           Data.Morpheus.Error.Internal            (internalError)
-import           Data.Morpheus.Types.Internal.Validation (Validation)
+import           Data.Morpheus.Error.Internal   ( internalError )
+import           Data.Morpheus.Types.Internal.Resolving
+                                                ( Validation )
 
 class EnumRep f where
   encodeRep :: f a -> Text
@@ -38,6 +42,6 @@
   decodeEnum name
     | name `elem` enumTags (Proxy @a) = L1 <$> decodeEnum name
     | name `elem` enumTags (Proxy @b) = R1 <$> decodeEnum name
-    | otherwise =
-      internalError ("Constructor \"" <> name <> "\" could not find in Union")
+    | otherwise = internalError
+      ("Constructor \"" <> name <> "\" could not find in Union")
   enumTags _ = enumTags (Proxy @a) ++ enumTags (Proxy @b)
diff --git a/src/Data/Morpheus/Execution/Server/Interpreter.hs b/src/Data/Morpheus/Execution/Server/Interpreter.hs
--- a/src/Data/Morpheus/Execution/Server/Interpreter.hs
+++ b/src/Data/Morpheus/Execution/Server/Interpreter.hs
@@ -5,22 +5,44 @@
 
 module Data.Morpheus.Execution.Server.Interpreter
   ( Interpreter(..)
-  ) where
+  )
+where
 
-import           Data.Aeson                                          (encode)
-import           Data.ByteString                                     (ByteString)
-import qualified Data.ByteString.Lazy.Char8                          as LB (ByteString, fromStrict, toStrict)
-import           Data.Text                                           (Text)
-import qualified Data.Text.Lazy                                      as LT (Text, fromStrict, toStrict)
-import           Data.Text.Lazy.Encoding                             (decodeUtf8, encodeUtf8)
+import           Data.Aeson                     ( encode )
+import           Data.ByteString                ( ByteString )
+import qualified Data.ByteString.Lazy.Char8    as LB
+                                                ( ByteString
+                                                , fromStrict
+                                                , toStrict
+                                                )
+import           Data.Text                      ( Text )
+import qualified Data.Text.Lazy                as LT
+                                                ( Text
+                                                , fromStrict
+                                                , toStrict
+                                                )
+import           Data.Text.Lazy.Encoding        ( decodeUtf8
+                                                , encodeUtf8
+                                                )
 
 -- MORPHEUS
-import           Data.Morpheus.Execution.Server.Resolve              (RootResCon, byteStringIO, statefulResolver,
-                                                                      statelessResolver, streamResolver)
-import           Data.Morpheus.Execution.Subscription.ClientRegister (GQLState)
-import           Data.Morpheus.Types.Internal.Resolver               (GQLRootResolver (..))
-import           Data.Morpheus.Types.Internal.Stream                 (ResponseStream)
-import           Data.Morpheus.Types.IO                              (GQLRequest, GQLResponse)
+import           Data.Morpheus.Execution.Server.Resolve
+                                                ( RootResCon
+                                                , byteStringIO
+                                                , statefulResolver
+                                                , statelessResolver
+                                                , streamResolver
+                                                , coreResolver
+                                                )
+import           Data.Morpheus.Execution.Subscription.ClientRegister
+                                                ( GQLState )
+import           Data.Morpheus.Types.Internal.Resolving
+                                                ( GQLRootResolver(..)
+                                                , ResponseStream
+                                                )
+import           Data.Morpheus.Types.IO         ( GQLRequest
+                                                , GQLResponse
+                                                )
 
 -- | main query processor and resolver
 --  possible versions of interpreter
@@ -50,7 +72,7 @@
 -}
 type StateLess m a = a -> m a
 
-instance Interpreter (GQLRequest -> m GQLResponse) m e  where
+instance Interpreter (GQLRequest -> m GQLResponse) m e   where
   interpreter = statelessResolver
 
 instance Interpreter (StateLess m LB.ByteString) m e  where
@@ -60,11 +82,11 @@
   interpreter root request =
     decodeUtf8 <$> interpreter root (encodeUtf8 request)
 
-instance Interpreter (StateLess m ByteString) m e where
+instance Interpreter (StateLess m ByteString) m e  where
   interpreter root request =
     LB.toStrict <$> interpreter root (LB.fromStrict request)
 
-instance Interpreter (StateLess m Text) m e where
+instance Interpreter (StateLess m Text) m e  where
   interpreter root request =
     LT.toStrict <$> interpreter root (LT.fromStrict request)
 
@@ -72,17 +94,16 @@
    HTTP Interpreter with state and side effects, every mutation will
    trigger subscriptions in  shared `GQLState`
 -}
-type WSPub m e  a = GQLState m e -> a -> m a
+type WSPub m e a = GQLState m e -> a -> m a
 
-instance Interpreter (WSPub IO e LB.ByteString) IO e  where
-  interpreter root state =
-    statefulResolver state (byteStringIO (streamResolver root))
+instance Interpreter (WSPub IO e LB.ByteString) IO e where
+  interpreter root state = statefulResolver state (coreResolver root)
 
-instance Interpreter (WSPub IO e  LT.Text) IO e  where
+instance Interpreter (WSPub IO e  LT.Text) IO e where
   interpreter root state request =
     decodeUtf8 <$> interpreter root state (encodeUtf8 request)
 
-instance Interpreter (WSPub IO e  ByteString) IO e  where
+instance Interpreter (WSPub IO e  ByteString) IO e where
   interpreter root state request =
     LB.toStrict <$> interpreter root state (LB.fromStrict request)
 
@@ -94,22 +115,22 @@
    WebSocket Interpreter without state and side effects, mutations and subscription will return Actions
    that will be executed in WebSocket server
 -}
-type WSSub m e a = a -> ResponseStream m e a
+type WSSub m e a = a -> ResponseStream e m a
 
-instance Interpreter (GQLRequest -> ResponseStream m e  LB.ByteString) m e where
+instance Interpreter (GQLRequest -> ResponseStream e m LB.ByteString) m e where
   interpreter root request = encode <$> streamResolver root request
 
-instance Interpreter (WSSub m e  LB.ByteString) m e  where
+instance Interpreter (WSSub m e  LB.ByteString) m e where
   interpreter root = byteStringIO (streamResolver root)
 
-instance Interpreter (WSSub m e  LT.Text) m e  where
+instance Interpreter (WSSub m e  LT.Text)  m e where
   interpreter root request =
     decodeUtf8 <$> interpreter root (encodeUtf8 request)
 
-instance Interpreter (WSSub m e ByteString) m e  where
+instance Interpreter (WSSub m e ByteString) m e where
   interpreter root request =
     LB.toStrict <$> interpreter root (LB.fromStrict request)
 
-instance Interpreter (WSSub m e Text) m e where
+instance Interpreter (WSSub m e Text)  m e where
   interpreter root request =
     LT.toStrict <$> interpreter root (LT.fromStrict request)
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
@@ -21,28 +21,54 @@
   , IntroCon
   , updateLib
   , buildType
-  ) where
+  )
+where
 
-import           Data.Map                                        (Map)
-import           Data.Proxy                                      (Proxy (..))
-import           Data.Semigroup                                  ((<>))
-import           Data.Set                                        (Set)
-import           Data.Text                                       (Text, pack)
+import           Data.Map                       ( Map )
+import           Data.Proxy                     ( Proxy(..) )
+import           Data.Set                       ( Set )
+import           Data.Text                      ( Text
+                                                , pack
+                                                )
 import           GHC.Generics
 
 -- MORPHEUS
-import           Data.Morpheus.Error.Schema                      (nameCollisionError)
-import           Data.Morpheus.Execution.Internal.GraphScanner   (LibUpdater, resolveUpdates)
-import           Data.Morpheus.Execution.Server.Generics.EnumRep (EnumRep (..))
-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 (..), DataType (..),
-                                                                  DataTyCon (..), DataTypeLib, TypeAlias (..),
-                                                                  defineType, isTypeDefined, toListField,
-                                                                  toNullableField)
+import           Data.Morpheus.Error.Schema     ( nameCollisionError )
+import           Data.Morpheus.Execution.Server.Generics.EnumRep
+                                                ( EnumRep(..) )
+import           Data.Morpheus.Kind             ( Context(..)
+                                                , ENUM
+                                                , GQL_KIND
+                                                , INPUT_OBJECT
+                                                , INPUT_UNION
+                                                , OBJECT
+                                                , SCALAR
+                                                , UNION
+                                                )
+import           Data.Morpheus.Types.Types     ( MapKind
+                                                , Pair
+                                                )
+import           Data.Morpheus.Types.GQLScalar  ( GQLScalar(..) )
+import           Data.Morpheus.Types.GQLType    ( GQLType(..) )
+import           Data.Morpheus.Types.Internal.Resolving
+                                                ( Failure(..)
+                                                , resolveUpdates
+                                                )
+import           Data.Morpheus.Types.Internal.AST
+                                                ( DataArguments
+                                                , Meta(..)
+                                                , DataField(..)
+                                                , DataTyCon(..)
+                                                , DataType(..)
+                                                , Key
+                                                , createAlias
+                                                , defineType
+                                                , isTypeDefined
+                                                , toListField
+                                                , toNullableField
+                                                , createEnumValue
+                                                , TypeUpdater
+                                                )
 
 
 type IntroCon a = (GQLType a, ObjectFields (CUSTOM a) a)
@@ -86,11 +112,14 @@
 
 -- 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 = resolveUpdates typeLib (introspect (Proxy @b) : argTypes)
-    where
-      argTypes :: [TypeUpdater]
-      argTypes = snd $ objectFields (Proxy :: Proxy 'False) (Proxy @a)
+  field _ name = (field (Proxy @b) name)
+    { fieldArgs = fst $ objectFields (Proxy :: Proxy 'False) (Proxy @a)
+    }
+  introspect _ typeLib = resolveUpdates typeLib
+                                        (introspect (Proxy @b) : argTypes)
+   where
+    argTypes :: [TypeUpdater]
+    argTypes = snd $ objectFields (Proxy :: Proxy 'False) (Proxy @a)
 
 -- | Introspect With specific Kind: 'kind': object, scalar, enum ...
 class IntrospectKind (kind :: GQL_KIND) a where
@@ -99,72 +128,56 @@
 -- SCALAR
 instance (GQLType a, GQLScalar a) => IntrospectKind SCALAR a where
   introspectKind _ = updateLib scalarType [] (Proxy @a)
-    where
-      scalarType = DataScalar . buildType (scalarValidator (Proxy @a))
+    where scalarType = DataScalar . buildType (scalarValidator (Proxy @a))
 
 -- ENUM
 instance (GQL_TYPE a, EnumRep (Rep a)) => IntrospectKind ENUM a where
   introspectKind _ = updateLib enumType [] (Proxy @a)
-    where
-      enumType = DataEnum . buildType (enumTags (Proxy @(Rep a)))
+   where
+    enumType =
+      DataEnum . buildType (map createEnumValue $ enumTags (Proxy @(Rep a)))
 
 -- INPUT_OBJECT
 instance (GQL_TYPE a, ObjectFields (CUSTOM a) a) => IntrospectKind INPUT_OBJECT a where
-  introspectKind _ = updateLib (DataInputObject . buildType fields) types (Proxy @a)
-    where
-      (fields, types) = objectFields (Proxy @(CUSTOM a)) (Proxy @a)
+  introspectKind _ = updateLib (DataInputObject . buildType fields)
+                               types
+                               (Proxy @a)
+    where (fields, types) = objectFields (Proxy @(CUSTOM a)) (Proxy @a)
 
 -- OBJECTS
 instance (GQL_TYPE a, ObjectFields (CUSTOM a) a) => IntrospectKind OBJECT a where
-  introspectKind _ = updateLib (DataObject . buildType (__typename : fields)) types (Proxy @a)
-    where
-      __typename =
-        ( "__typename"
-        , DataField
-            { fieldName = "__typename"
-            , fieldArgs = []
-            , fieldArgsType = Nothing
-            , fieldType = buildAlias "String"
-            , fieldHidden = True
-            })
-      (fields, types) = objectFields (Proxy @(CUSTOM a)) (Proxy @a)
+  introspectKind _ = updateLib (DataObject . buildType (__typename : fields))
+                               types
+                               (Proxy @a)
+   where
+    __typename =
+      ( "__typename"
+      , DataField { fieldName     = "__typename"
+                  , fieldArgs     = []
+                  , fieldArgsType = Nothing
+                  , fieldType     = createAlias "String"
+                  , fieldMeta     = Nothing
+                  }
+      )
+    (fields, types) = objectFields (Proxy @(CUSTOM a)) (Proxy @a)
 
 -- UNION
 instance (GQL_TYPE a, GQLRep UNION (Rep a)) => IntrospectKind UNION a where
-  introspectKind _ = updateLib (DataUnion . buildType fields) stack (Proxy @a)
-    where
-      (fields, stack) = unzip $ gqlRep (Context :: Context UNION (Rep a))
+  introspectKind _ = updateLib (DataUnion . buildType memberTypes)
+                               stack
+                               (Proxy @a)
+   where
+    (memberTypes, stack) = unzip $ gqlRep (Context :: Context UNION (Rep a))
 
 -- INPUT_UNION
 instance (GQL_TYPE a, GQLRep UNION (Rep a)) => IntrospectKind INPUT_UNION a where
-  introspectKind _ = updateLib (DataInputUnion . buildType (fieldTag : fields)) (tagsEnumType : stack) (Proxy @a)
-    where
-      (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 (typeName, DataEnum tagsEnum) x
-        where
-          tagsEnum =
-            DataTyCon
-              { typeName
-                -- has same fingerprint as object because it depends on it
-              , typeFingerprint = __typeFingerprint (Proxy @a)
-              , typeDescription = Nothing
-              , typeData = map fieldName inputUnions
-              }
-      typeName = __typeName (Proxy @a) <> "Tags"
-      fieldTag =
-        DataField
-          { fieldName = "tag"
-          , fieldArgs = []
-          , fieldArgsType = Nothing
-          , fieldType = buildAlias typeName
-          , fieldHidden = False
-          }
+  introspectKind _ = updateLib (DataInputUnion . buildType memberTypes)
+                               stack
+                               (Proxy @a)
+   where
+    (memberTypes, stack) = unzip $ gqlRep (Context :: Context UNION (Rep a))
 
 -- Types
-type TypeUpdater = LibUpdater DataTypeLib
 
 type GQL_TYPE a = (Generic a, GQLType a)
 
@@ -179,7 +192,7 @@
 
 type instance GQLRepResult OBJECT = (Text, DataField)
 
-type instance GQLRepResult UNION = DataField
+type instance GQLRepResult UNION = Key
 
 --  GENERIC UNION
 class GQLRep (kind :: GQL_KIND) f where
@@ -193,45 +206,55 @@
 
 -- | 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)
+  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))]
+  gqlRep _ = [(__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)
+  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
-      name = pack $ selName (undefined :: M1 S s (Rec0 ()) ())
+    where name = pack $ selName (undefined :: M1 S s (Rec0 ()) ())
 
 instance GQLRep OBJECT U1 where
   gqlRep _ = []
 
-buildAlias :: Text -> TypeAlias
-buildAlias aliasTyCon = TypeAlias {aliasTyCon, aliasWrappers = [], aliasArgs = Nothing}
 
 buildField :: GQLType a => Proxy a -> DataArguments -> Text -> DataField
-buildField proxy fieldArgs fieldName =
-  DataField
-    {fieldName, fieldArgs, fieldArgsType = Nothing, fieldType = buildAlias $ __typeName proxy, fieldHidden = False}
+buildField proxy fieldArgs fieldName = DataField
+  { fieldName
+  , fieldArgs
+  , fieldArgsType = Nothing
+  , fieldType     = createAlias $ __typeName proxy
+  , fieldMeta     = Nothing
+  }
 
 buildType :: GQLType a => t -> Proxy a -> DataTyCon t
-buildType typeData proxy =
-  DataTyCon
-    { typeName = __typeName proxy
-    , typeFingerprint = __typeFingerprint proxy
-    , typeDescription = description proxy
-    , typeData
-    }
+buildType typeData proxy = DataTyCon
+  { typeName        = __typeName proxy
+  , typeFingerprint = __typeFingerprint proxy
+  , typeMeta        = Just Meta { metaDescription = description proxy
+                                , metaDirectives  = []
+                                }
+  , typeData
+  }
 
-updateLib :: GQLType a => (Proxy a -> DataType) -> [TypeUpdater] -> Proxy a -> TypeUpdater
+updateLib
+  :: GQLType a
+  => (Proxy a -> DataType)
+  -> [TypeUpdater]
+  -> Proxy a
+  -> TypeUpdater
 updateLib typeBuilder stack proxy lib' =
   case isTypeDefined (__typeName proxy) lib' of
-    Nothing -> resolveUpdates (defineType (__typeName proxy, typeBuilder proxy) lib') stack
-    Just fingerprint'
-      | fingerprint' == __typeFingerprint proxy -> return lib'
+    Nothing -> resolveUpdates
+      (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)
+    Just _ -> failure $ 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
@@ -14,138 +14,214 @@
   , statefulResolver
   , RootResCon
   , fullSchema
-  ) where
+  , coreResolver
+  )
+where
 
-import           Control.Monad.Except                                (liftEither)
-import           Control.Monad.Trans.Except                          (runExceptT)
-import           Data.Aeson                                          (encode)
-import           Data.Aeson.Internal                                 (formatError, ifromJSON)
-import           Data.Aeson.Parser                                   (eitherDecodeWith, jsonNoDup)
-import qualified Data.ByteString.Lazy.Char8                          as L
-import           Data.Functor.Identity                               (Identity (..))
-import           Data.Proxy                                          (Proxy (..))
+import           Data.Aeson                     ( encode )
+import           Data.Aeson.Internal            ( formatError
+                                                , ifromJSON
+                                                )
+import           Data.Aeson.Parser              ( eitherDecodeWith
+                                                , jsonNoDup
+                                                )
+import qualified Data.ByteString.Lazy.Char8    as L
+import           Data.Functor.Identity          ( Identity(..) )
+import           Data.Proxy                     ( Proxy(..) )
 
 -- MORPHEUS
-import           Data.Morpheus.Error.Utils                           (badRequestError)
-import           Data.Morpheus.Execution.Internal.GraphScanner       (resolveUpdates)
-import           Data.Morpheus.Execution.Server.Encode               (EncodeCon, encodeMutation, encodeQuery,
-                                                                      encodeSubscription)
-import           Data.Morpheus.Execution.Server.Introspect           (IntroCon, ObjectFields (..))
-import           Data.Morpheus.Execution.Subscription.ClientRegister (GQLState, publishUpdates)
-import           Data.Morpheus.Parsing.Request.Parser                (parseGQL)
+import           Data.Morpheus.Error.Utils      ( badRequestError )
+import           Data.Morpheus.Execution.Server.Encode
+                                                ( EncodeCon
+                                                , encodeMutation
+                                                , encodeQuery
+                                                , encodeSubscription
+                                                )
+import           Data.Morpheus.Execution.Server.Introspect
+                                                ( IntroCon
+                                                , ObjectFields(..)
+                                                )
+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.GQLType                         (GQLType (CUSTOM))
-import           Data.Morpheus.Types.Internal.AST.Operation          (Operation (..), ValidOperation)
-import           Data.Morpheus.Types.Internal.Data                   (DataFingerprint (..), DataTyCon (..),
-                                                                      DataTypeLib (..), MUTATION, OperationType (..),
-                                                                      QUERY, SUBSCRIPTION, initTypeLib)
-import           Data.Morpheus.Types.Internal.Resolver               (GQLRootResolver (..), Resolver (..), ResponseT,
-                                                                      toResponseRes)
-import           Data.Morpheus.Types.Internal.Stream                 (GQLChannel (..), ResponseEvent (..),
-                                                                      ResponseStream, closeStream)
-import           Data.Morpheus.Types.Internal.Validation             (Validation)
-import           Data.Morpheus.Types.IO                              (GQLRequest (..), GQLResponse (..), renderResponse)
-import           Data.Morpheus.Validation.Internal.Utils             (VALIDATION_MODE (..))
-import           Data.Morpheus.Validation.Query.Validation           (validateRequest)
-import           Data.Typeable                                       (Typeable)
+import           Data.Morpheus.Schema.SchemaAPI ( defaultTypes
+                                                , hiddenRootFields
+                                                , schemaAPI
+                                                )
+import           Data.Morpheus.Types.GQLType    ( GQLType(CUSTOM) )
+import           Data.Morpheus.Types.Internal.AST
+                                                ( Operation(..)
+                                                , ValidOperation
+                                                , DataFingerprint(..)
+                                                , DataTyCon(..)
+                                                , DataTypeLib(..)
+                                                , MUTATION
+                                                , OperationType(..)
+                                                , QUERY
+                                                , SUBSCRIPTION
+                                                , initTypeLib
+                                                , Value
+                                                )
+import           Data.Morpheus.Types.Internal.Resolving
+                                                ( GQLRootResolver(..)
+                                                , Resolver(..)
+                                                , toResponseRes
+                                                , GQLChannel(..)
+                                                , ResponseEvent(..)
+                                                , ResponseStream
+                                                , Validation
+                                                , cleanEvents
+                                                , ResultT(..)
+                                                , unpackEvents
+                                                , Failure(..)
+                                                , resolveUpdates
+                                                )
+import           Data.Morpheus.Types.IO         ( GQLRequest(..)
+                                                , GQLResponse(..)
+                                                , renderResponse
+                                                )
+import           Data.Morpheus.Validation.Internal.Utils
+                                                ( VALIDATION_MODE(..) )
+import           Data.Morpheus.Validation.Query.Validation
+                                                ( validateRequest )
+import           Data.Typeable                  ( Typeable )
 
-type EventCon event = (Eq (StreamChannel event), Typeable event, GQLChannel event)
 
-type IntrospectConstraint  m event query mutation subscription = (
-                                  IntroCon (query (Resolver QUERY m event))
-                                 , IntroCon (mutation (Resolver MUTATION m event))
-                                 , IntroCon (subscription (Resolver SUBSCRIPTION m event)))
+type EventCon event
+  = (Eq (StreamChannel event), Typeable event, GQLChannel event)
 
+type IntrospectConstraint m event query mutation subscription
+  = ( IntroCon (query (Resolver QUERY event m))
+    , IntroCon (mutation (Resolver MUTATION event m))
+    , IntroCon (subscription (Resolver SUBSCRIPTION event m))
+    )
+
 type RootResCon m event query mutation subscription
-   = ( EventCon event
-     , Typeable m
-     , IntrospectConstraint m event query mutation subscription
-    -- , OBJ_RES m (Root (Resolver m)) Value
-     -- Resolving
-     , EncodeCon QUERY m event (query (Resolver QUERY m event))
-     , EncodeCon MUTATION m event (mutation (Resolver MUTATION m event))
-     , EncodeCon SUBSCRIPTION m event (subscription (Resolver SUBSCRIPTION m event)))
+  = ( EventCon event
+    , Typeable m
+    , IntrospectConstraint m event query mutation subscription
+    , EncodeCon QUERY event m (query (Resolver QUERY event m))
+    , EncodeCon MUTATION event m (mutation (Resolver MUTATION event m))
+    , EncodeCon
+        SUBSCRIPTION
+        event
+        m
+        (subscription (Resolver SUBSCRIPTION event m))
+    )
 
-decodeNoDup :: L.ByteString -> Either String GQLRequest
-decodeNoDup str =
-  case eitherDecodeWith jsonNoDup ifromJSON str of
-    Left (path, x) -> Left $ formatError path x
-    Right value    -> Right value
+decodeNoDup :: Failure String m => L.ByteString -> m GQLRequest
+decodeNoDup str = case eitherDecodeWith jsonNoDup ifromJSON str of
+  Left  (path, x) -> failure $ formatError path x
+  Right value     -> pure value
 
-byteStringIO :: Monad m => (GQLRequest -> m GQLResponse) -> L.ByteString -> m L.ByteString
-byteStringIO resolver request =
-  case decodeNoDup request of
-    Left aesonError' -> return $ badRequestError aesonError'
-    Right req        -> encode <$> resolver req
 
-statelessResolver ::
-     (Monad m, RootResCon m event query mut sub)
-  => GQLRootResolver m event  query mut sub
+byteStringIO
+  :: Monad m => (GQLRequest -> m GQLResponse) -> L.ByteString -> m L.ByteString
+byteStringIO resolver request = case decodeNoDup request of
+  Left  aesonError' -> return $ badRequestError aesonError'
+  Right req         -> encode <$> resolver req
+
+statelessResolver
+  :: (Monad m, RootResCon m event query mut sub)
+  => GQLRootResolver m event query mut sub
   -> GQLRequest
   -> m GQLResponse
-statelessResolver root = fmap snd . closeStream . streamResolver root
+statelessResolver root req =
+  renderResponse <$> runResultT (coreResolver root req)
 
-streamResolver ::
-     (Monad m, RootResCon m event  query mut sub)
+streamResolver
+  :: forall event m query mut sub
+   . (Monad m, RootResCon m event query mut sub)
   => GQLRootResolver m event query mut sub
   -> GQLRequest
-  -> ResponseStream m event GQLResponse
-streamResolver root@GQLRootResolver {queryResolver, mutationResolver, subscriptionResolver} request =
-  renderResponse <$> runExceptT (validRequest >>= execOperator)
-  ------------------------------------------------------------
-  where
-    ---------------------------------------------------------
-    validRequest :: Monad m => ResponseT m event (DataTypeLib, ValidOperation)
-    validRequest =
-      liftEither $ do
-        schema <- fullSchema $ Identity root
-        query <- parseGQL request >>= validateRequest schema FULL_VALIDATION
-        Right (schema, query)
-    ----------------------------------------------------------
-    execOperator (schema, operation@Operation {operationType = Query}) =
-        toResponseRes (encodeQuery (schemaAPI schema) queryResolver operation)
-    execOperator (_, operation@Operation {operationType = Mutation}) = toResponseRes (encodeMutation mutationResolver operation)
-    execOperator (_, operation@Operation {operationType = Subscription}) = response
-        where
-         response = toResponseRes (encodeSubscription subscriptionResolver operation)
+  -> ResponseStream event m GQLResponse
+streamResolver root req =
+  ResultT $ pure . renderResponse <$> runResultT (coreResolver root req)
 
-statefulResolver ::
-     EventCon s
-  => GQLState IO s
-  -> (L.ByteString -> ResponseStream IO s  L.ByteString)
+coreResolver
+  :: forall event m query mut sub
+   . (Monad m, RootResCon m event query mut sub)
+  => GQLRootResolver m event query mut sub
+  -> GQLRequest
+  -> ResponseStream event m Value
+coreResolver root@GQLRootResolver { queryResolver, mutationResolver, subscriptionResolver } request
+  = validRequest >>= execOperator
+ where
+  validRequest
+    :: Monad m => ResponseStream event m (DataTypeLib, ValidOperation)
+  validRequest = cleanEvents $ ResultT $ pure $ do
+    schema <- fullSchema $ Identity root
+    query  <- parseGQL request >>= validateRequest schema FULL_VALIDATION
+    pure (schema, query)
+  ----------------------------------------------------------
+  execOperator (schema, operation@Operation { operationType = Query }) =
+    toResponseRes (encodeQuery (schemaAPI schema) queryResolver operation)
+  execOperator (_, operation@Operation { operationType = Mutation }) =
+    toResponseRes (encodeMutation mutationResolver operation)
+  execOperator (_, operation@Operation { operationType = Subscription }) =
+    response
+   where
+    response =
+      toResponseRes (encodeSubscription subscriptionResolver operation)
+
+statefulResolver
+  :: EventCon event
+  => GQLState IO event
+  -> (GQLRequest -> ResponseStream event IO Value)
   -> L.ByteString
   -> IO L.ByteString
-statefulResolver state streamApi request = do
-  (actions, value) <- closeStream (streamApi request)
-  mapM_ execute actions
-  pure value
-  where
-    execute (Publish updates) = publishUpdates state updates
-    execute Subscribe {}      = pure ()
+statefulResolver state streamApi requestText = do
+  res <- runResultT (decodeNoDup requestText >>= streamApi)
+  mapM_ execute (unpackEvents res)
+  pure $ encode $ renderResponse res
+ where
+  execute (Publish updates) = publishUpdates state updates
+  execute Subscribe{}       = pure ()
 
-fullSchema ::
-     forall proxy m event query mutation subscription. (IntrospectConstraint m event query mutation subscription)
+
+fullSchema
+  :: forall proxy m event query mutation subscription
+   . (IntrospectConstraint m event query mutation subscription)
   => proxy (GQLRootResolver m event query mutation subscription)
   -> Validation DataTypeLib
 fullSchema _ = querySchema >>= mutationSchema >>= subscriptionSchema
-  where
-    querySchema =
-      resolveUpdates (initTypeLib (operatorType (hiddenRootFields ++ fields) "Query")) (defaultTypes : types)
-      where
-        (fields, types) = objectFields (Proxy @(CUSTOM (query (Resolver QUERY m event)))) (Proxy @(query (Resolver QUERY m event)))
-    ------------------------------
-    mutationSchema lib = resolveUpdates (lib {mutation = maybeOperator fields "Mutation"}) types
-      where
-        (fields, types) = objectFields (Proxy @(CUSTOM (mutation (Resolver MUTATION m event)))) (Proxy @(mutation (Resolver MUTATION m event)))
-    ------------------------------
-    subscriptionSchema lib = resolveUpdates (lib {subscription = maybeOperator fields "Subscription"}) types
-      where
-        (fields, types) = objectFields (Proxy @(CUSTOM (subscription (Resolver SUBSCRIPTION m event)))) (Proxy @(subscription (Resolver SUBSCRIPTION m event)))
-     -- maybeOperator :: [a] -> Text -> Maybe (Text, DataTyCon[a])
-    maybeOperator []     = const Nothing
-    maybeOperator fields = Just . operatorType fields
-    -- operatorType :: [a] -> Text -> (Text, DataTyCon[a])
-    operatorType typeData typeName =
-      ( typeName
-      , DataTyCon {typeData, typeName, typeFingerprint = SystemFingerprint typeName, typeDescription = Nothing})
+ where
+  querySchema = resolveUpdates
+    (initTypeLib (operatorType (hiddenRootFields ++ fields) "Query"))
+    (defaultTypes : types)
+   where
+    (fields, types) = objectFields
+      (Proxy @(CUSTOM (query (Resolver QUERY event m))))
+      (Proxy @(query (Resolver QUERY event m)))
+  ------------------------------
+  mutationSchema lib = resolveUpdates
+    (lib { mutation = maybeOperator fields "Mutation" })
+    types
+   where
+    (fields, types) = objectFields
+      (Proxy @(CUSTOM (mutation (Resolver MUTATION event m))))
+      (Proxy @(mutation (Resolver MUTATION event m)))
+  ------------------------------
+  subscriptionSchema lib = resolveUpdates
+    (lib { subscription = maybeOperator fields "Subscription" })
+    types
+   where
+    (fields, types) = objectFields
+      (Proxy @(CUSTOM (subscription (Resolver SUBSCRIPTION event m))))
+      (Proxy @(subscription (Resolver SUBSCRIPTION event m)))
+   -- maybeOperator :: [a] -> Text -> Maybe (Text, DataTyCon[a])
+  maybeOperator []     = const Nothing
+  maybeOperator fields = Just . operatorType fields
+  -- operatorType :: [a] -> Text -> (Text, DataTyCon[a])
+  operatorType typeData typeName =
+    ( typeName
+    , DataTyCon { typeData
+                , typeName
+                , typeFingerprint = SystemFingerprint typeName
+                , typeMeta        = Nothing
+                }
+    )
diff --git a/src/Data/Morpheus/Execution/Subscription/ClientRegister.hs b/src/Data/Morpheus/Execution/Subscription/ClientRegister.hs
--- a/src/Data/Morpheus/Execution/Subscription/ClientRegister.hs
+++ b/src/Data/Morpheus/Execution/Subscription/ClientRegister.hs
@@ -10,25 +10,41 @@
   , publishUpdates
   , addClientSubscription
   , removeClientSubscription
-  ) where
+  )
+where
 
-import           Control.Concurrent                          (MVar, modifyMVar, modifyMVar_, newMVar, readMVar)
-import           Data.Foldable                               (traverse_)
-import           Data.List                                   (intersect)
-import           Data.Text                                   (Text)
-import           Data.UUID.V4                                (nextRandom)
-import           Network.WebSockets                          (Connection, sendTextData)
- 
+import           Control.Concurrent             ( MVar
+                                                , modifyMVar
+                                                , modifyMVar_
+                                                , newMVar
+                                                , readMVar
+                                                )
+import           Data.Foldable                  ( traverse_ )
+import           Data.List                      ( intersect )
+import           Data.Text                      ( Text )
+import           Data.UUID.V4                   ( nextRandom )
+import           Network.WebSockets             ( Connection
+                                                , sendTextData
+                                                )
 -- MORPHEUS
-import           Data.Morpheus.Execution.Subscription.Apollo (toApolloResponse)
-import           Data.Morpheus.Types.Internal.Stream         (Event (..),GQLChannel(..),  SubEvent)
-import           Data.Morpheus.Types.Internal.WebSocket      (ClientID, ClientSession (..), GQLClient (..))
+import           Data.Morpheus.Execution.Subscription.Apollo
+                                                ( toApolloResponse )
+import           Data.Morpheus.Types.Internal.Resolving
+                                                ( Event(..)
+                                                , GQLChannel(..)
+                                                , SubEvent
+                                                )
+import           Data.Morpheus.Types.Internal.WebSocket
+                                                ( ClientID
+                                                , ClientSession(..)
+                                                , GQLClient(..)
+                                                )
 
-type ClientRegister m e  = [(ClientID, GQLClient m e)]
+type ClientRegister m e = [(ClientID, GQLClient m e)]
 
 -- | shared GraphQL state between __websocket__ and __http__ server,
 -- stores information about subscriptions
-type GQLState m e  = MVar (ClientRegister m e ) -- SharedState
+type GQLState m e = MVar (ClientRegister m e) -- SharedState
 
 -- | initializes empty GraphQL state
 initGQLState :: IO (GQLState m e)
@@ -39,71 +55,70 @@
   client' <- newClient
   modifyMVar_ varState' (addClient client')
   return (snd client')
-  where
-    newClient = do
-      clientID <- nextRandom
-      return
-        (clientID, GQLClient {clientID, clientConnection, clientSessions = []})
-    addClient client' state' = return (client' : state')
+ where
+  newClient = do
+    clientID <- nextRandom
+    return
+      (clientID, GQLClient { clientID, clientConnection, clientSessions = [] })
+  addClient client' state' = return (client' : state')
 
-disconnectClient ::
-     GQLClient m e  -> GQLState m e -> IO (ClientRegister m e)
+disconnectClient :: GQLClient m e -> GQLState m e -> IO (ClientRegister m e)
 disconnectClient client state = modifyMVar state removeUser
-  where
-    removeUser state' =
-      let s' = removeClient state'
-       in return (s', s')
-    removeClient :: ClientRegister m e  -> ClientRegister m e
-    removeClient = filter ((/= clientID client) . fst)
+ where
+  removeUser state' = let s' = removeClient state' in return (s', s')
+  removeClient :: ClientRegister m e -> ClientRegister m e
+  removeClient = filter ((/= clientID client) . fst)
 
-updateClientByID ::
-     ClientID
+updateClientByID
+  :: ClientID
   -> (GQLClient m e -> GQLClient m e)
-  -> MVar (ClientRegister m e )
+  -> MVar (ClientRegister m e)
   -> IO ()
-updateClientByID id' updateFunc state =
-  modifyMVar_ state (return . map updateClient)
-  where
-    updateClient (key', client')
-      | key' == id' = (key', updateFunc client')
-    updateClient state' = state'
+updateClientByID id' updateFunc state = modifyMVar_
+  state
+  (return . map updateClient)
+ where
+  updateClient (key, client') | key == id' = (key, updateFunc client')
+  updateClient state'                      = state'
 
-publishUpdates :: (Eq (StreamChannel e), GQLChannel e) => GQLState IO e -> e -> IO ()
+publishUpdates
+  :: (Eq (StreamChannel e), GQLChannel e) => GQLState IO e -> e -> IO ()
 publishUpdates state event = do
   state' <- readMVar state
   traverse_ sendMessage state'
-  where
-    sendMessage (_, GQLClient {clientSessions = []}) = return ()
-    sendMessage (_, GQLClient {clientSessions, clientConnection}) =
-      mapM_ __send (filterByChannels clientSessions)
-      where
-        __send ClientSession { sessionId
-                             , sessionSubscription = Event {content = subscriptionRes}
-                             } =
-          subscriptionRes event >>=
-          sendTextData clientConnection . toApolloResponse sessionId
-        filterByChannels =
-          filter
-            (not . null .
-             intersect (streamChannels event) . channels . sessionSubscription)
+ where
+  sendMessage (_, GQLClient { clientSessions = [] }             ) = return ()
+  sendMessage (_, GQLClient { clientSessions, clientConnection }) = mapM_
+    __send
+    (filterByChannels clientSessions)
+   where
+    __send ClientSession { sessionId, sessionSubscription = Event { content = subscriptionRes } }
+      = subscriptionRes event
+        >>= sendTextData clientConnection
+        .   toApolloResponse sessionId
+    ---------------------------
+    filterByChannels = filter
+      ( not
+      . null
+      . intersect (streamChannels event)
+      . channels
+      . sessionSubscription
+      )
 
-removeClientSubscription :: ClientID -> Text -> GQLState m e  -> IO ()
+removeClientSubscription :: ClientID -> Text -> GQLState m e -> IO ()
 removeClientSubscription id' sid' = updateClientByID id' stopSubscription
-  where
-    stopSubscription client' =
-      client'
-        { clientSessions =
-            filter ((sid' /=) . sessionId) (clientSessions client')
-        }
+ where
+  stopSubscription client' = client'
+    { clientSessions = filter ((sid' /=) . sessionId) (clientSessions client')
+    }
 
-addClientSubscription ::
-     ClientID -> SubEvent m e  -> Text -> GQLState m e  -> IO ()
-addClientSubscription id' sessionSubscription sessionId =
-  updateClientByID id' startSubscription
-  where
-    startSubscription client' =
-      client'
-        { clientSessions =
-            ClientSession {sessionId, sessionSubscription} :
-            clientSessions client'
-        }
+addClientSubscription
+  :: ClientID -> SubEvent m e -> Text -> GQLState m e -> IO ()
+addClientSubscription id' sessionSubscription sessionId = updateClientByID
+  id'
+  startSubscription
+ where
+  startSubscription client' = client'
+    { clientSessions = ClientSession { sessionId, sessionSubscription }
+                         : clientSessions client'
+    }
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
@@ -16,9 +16,11 @@
   , Context(..)
   , VContext(..)
   , ResContext(..)
-  ) where
+  )
+where
 
-import           Data.Morpheus.Types.Internal.Data (OperationType (..))
+import           Data.Morpheus.Types.Internal.AST
+                                                ( OperationType(..) )
 
 data GQL_KIND
   = SCALAR
@@ -30,7 +32,7 @@
   | WRAPPER
 
 
-data ResContext (kind :: GQL_KIND) (operation:: OperationType) (m :: * -> * ) event value = ResContext
+data ResContext (kind :: GQL_KIND) (operation:: OperationType) event (m :: * -> * )  value = ResContext
 
 --type ObjectConstraint a =
 -- | context , like Proxy with multiple parameters
diff --git a/src/Data/Morpheus/Parsing/Document/Parser.hs b/src/Data/Morpheus/Parsing/Document/Parser.hs
--- a/src/Data/Morpheus/Parsing/Document/Parser.hs
+++ b/src/Data/Morpheus/Parsing/Document/Parser.hs
@@ -1,28 +1,37 @@
-{-# LANGUAGE NamedFieldPuns    #-}
 {-# LANGUAGE OverloadedStrings #-}
 
 module Data.Morpheus.Parsing.Document.Parser
   ( parseTypes
-  ) where
+  )
+where
 
-import           Data.Text                                 (Text)
-import           Text.Megaparsec                           (eof, label, manyTill, runParser)
+import           Data.Text                      ( Text )
+import           Text.Megaparsec                ( eof
+                                                , label
+                                                , manyTill
+                                                , runParser
+                                                )
 
 -- MORPHEUS
-import           Data.Morpheus.Parsing.Document.TypeSystem (parseDataType)
-import           Data.Morpheus.Parsing.Internal.Internal   (processErrorBundle)
-import           Data.Morpheus.Parsing.Internal.Terms      (spaceAndComments)
-import           Data.Morpheus.Types.Internal.Data         (RawDataType)
-import           Data.Morpheus.Types.Internal.Validation   (Validation)
+import           Data.Morpheus.Parsing.Document.TypeSystem
+                                                ( parseDataType )
+import           Data.Morpheus.Parsing.Internal.Internal
+                                                ( processErrorBundle )
+import           Data.Morpheus.Parsing.Internal.Terms
+                                                ( spaceAndComments )
+import           Data.Morpheus.Types.Internal.AST
+                                                ( RawDataType )
+import           Data.Morpheus.Types.Internal.Resolving
+                                                ( Validation
+                                                , Failure(..)
+                                                )
 
 parseTypes :: Text -> Validation [(Text, RawDataType)]
-parseTypes doc =
-  case parseDoc of
-    Right root      -> Right root
-    Left parseError -> Left $ processErrorBundle parseError
-  where
-    parseDoc = runParser request "<input>" doc
-    request =
-      label "DocumentTypes" $ do
-        spaceAndComments
-        manyTill parseDataType eof
+parseTypes doc = case parseDoc of
+  Right root       -> pure root
+  Left  parseError -> failure (processErrorBundle parseError)
+ where
+  parseDoc = runParser request "<input>" doc
+  request  = label "DocumentTypes" $ do
+    spaceAndComments
+    manyTill parseDataType eof
diff --git a/src/Data/Morpheus/Parsing/Document/TypeSystem.hs b/src/Data/Morpheus/Parsing/Document/TypeSystem.hs
--- a/src/Data/Morpheus/Parsing/Document/TypeSystem.hs
+++ b/src/Data/Morpheus/Parsing/Document/TypeSystem.hs
@@ -3,20 +3,44 @@
 
 module Data.Morpheus.Parsing.Document.TypeSystem
   ( parseDataType
-  ) where
+  )
+where
 
-import           Data.Text                               (Text)
-import           Text.Megaparsec                         (label, sepBy1, (<|>))
+import           Data.Text                      ( Text )
+import           Text.Megaparsec                ( label
+                                                , sepBy1
+                                                , (<|>)
+                                                )
 
 -- MORPHEUS
-import           Data.Morpheus.Parsing.Internal.Create   (createField)
-import           Data.Morpheus.Parsing.Internal.Internal (Parser)
-import           Data.Morpheus.Parsing.Internal.Pattern  (fieldsDefinition, inputValueDefinition, optionalDirectives,
-                                                          typDeclaration)
-import           Data.Morpheus.Parsing.Internal.Terms    (keyword, operator, optDescription, parseName, pipeLiteral,
-                                                          sepByAnd, setOf)
-import           Data.Morpheus.Types.Internal.Data       (DataField, DataFingerprint (..), DataType (..),
-                                                          DataTyCon (..), DataValidator (..), Key, RawDataType (..))
+import           Data.Morpheus.Parsing.Internal.Internal
+                                                ( Parser )
+import           Data.Morpheus.Parsing.Internal.Pattern
+                                                ( fieldsDefinition
+                                                , inputValueDefinition
+                                                , optionalDirectives
+                                                , typDeclaration
+                                                , enumValueDefinition
+                                                )
+import           Data.Morpheus.Parsing.Internal.Terms
+                                                ( keyword
+                                                , operator
+                                                , optDescription
+                                                , parseName
+                                                , pipeLiteral
+                                                , sepByAnd
+                                                , setOf
+                                                )
+import           Data.Morpheus.Types.Internal.AST
+                                                ( DataField
+                                                , DataFingerprint(..)
+                                                , DataTyCon(..)
+                                                , DataType(..)
+                                                , DataValidator(..)
+                                                , Key
+                                                , RawDataType(..)
+                                                , Meta(..)
+                                                )
 
 
 -- Scalars : https://graphql.github.io/graphql-spec/June2018/#sec-Scalars
@@ -25,20 +49,18 @@
 --    Description(opt) scalar Name Directives(Const)(opt)
 --
 scalarTypeDefinition :: Maybe Text -> Parser (Text, DataType)
-scalarTypeDefinition typeDescription =
-  label "ScalarTypeDefinition" $ do
-    typeName <- typDeclaration "scalar"
-    -- TODO: handle directives
-    _ <- optionalDirectives
-    pure (
-          typeName,
-          DataScalar DataTyCon {
-            typeName,
-            typeDescription,
-            typeFingerprint = SystemFingerprint typeName,
-            typeData = DataValidator pure
-          }
-        )
+scalarTypeDefinition metaDescription = label "ScalarTypeDefinition" $ do
+  typeName       <- typDeclaration "scalar"
+  metaDirectives <- optionalDirectives
+  pure
+    ( typeName
+    , DataScalar DataTyCon
+      { typeName
+      , typeMeta        = Just Meta { metaDescription, metaDirectives }
+      , typeFingerprint = SystemFingerprint typeName
+      , typeData        = DataValidator pure
+      }
+    )
 
 -- Objects : https://graphql.github.io/graphql-spec/June2018/#sec-Objects
 --
@@ -56,27 +78,27 @@
 --    Description(opt) Name ArgumentsDefinition(opt) : Type Directives(Const)(opt)
 --
 objectTypeDefinition :: Maybe Text -> Parser (Text, RawDataType)
-objectTypeDefinition typeDescription =
-  label "ObjectTypeDefinition" $ do
-    name <- typDeclaration "type"
-    interfaces <- optionalImplementsInterfaces
-    -- TODO: handle directives
-    _directives <- optionalDirectives
-    fields <- fieldsDefinition
-    --------------------------
-    pure (name,
-         Implements interfaces $ DataTyCon {
-           typeName = name,
-           typeDescription,
-           typeFingerprint = SystemFingerprint name,
-           typeData = fields
-         }
-      )
+objectTypeDefinition metaDescription = label "ObjectTypeDefinition" $ do
+  name           <- typDeclaration "type"
+  interfaces     <- optionalImplementsInterfaces
+  metaDirectives <- optionalDirectives
+  fields         <- fieldsDefinition
+  --------------------------
+  pure
+    ( name
+    , Implements interfaces $ DataTyCon
+      { typeName        = name
+      , typeMeta        = Just Meta { metaDescription, metaDirectives }
+      , typeFingerprint = SystemFingerprint name
+      , typeData        = fields
+      }
+    )
 
 optionalImplementsInterfaces :: Parser [Text]
 optionalImplementsInterfaces = implements <|> pure []
-  where
-    implements = label "ImplementsInterfaces" $ keyword "implements" *> sepByAnd parseName
+ where
+  implements =
+    label "ImplementsInterfaces" $ keyword "implements" *> sepByAnd parseName
 
 -- Interfaces: https://graphql.github.io/graphql-spec/June2018/#sec-Interfaces
 --
@@ -84,21 +106,19 @@
 --    Description(opt) interface Name Directives(Const)(opt) FieldsDefinition(opt)
 --
 interfaceTypeDefinition :: Maybe Text -> Parser (Text, RawDataType)
-interfaceTypeDefinition typeDescription =
-  label "InterfaceTypeDefinition" $ do
-    typeName <- typDeclaration "interface"
-    -- TODO: handle directives
-    _directives <- optionalDirectives
-    fields <- fieldsDefinition
-    pure (
-        typeName,
-        Interface DataTyCon {
-           typeName,
-           typeDescription,
-           typeFingerprint = SystemFingerprint typeName,
-           typeData = fields
-           }
-        )
+interfaceTypeDefinition metaDescription = label "InterfaceTypeDefinition" $ do
+  typeName       <- typDeclaration "interface"
+  metaDirectives <- optionalDirectives
+  fields         <- fieldsDefinition
+  pure
+    ( typeName
+    , Interface DataTyCon
+      { typeName
+      , typeMeta        = Just Meta { metaDescription, metaDirectives }
+      , typeFingerprint = SystemFingerprint typeName
+      , typeData        = fields
+      }
+    )
 
 
 -- Unions : https://graphql.github.io/graphql-spec/June2018/#sec-Unions
@@ -110,25 +130,21 @@
 --    = |(opt) NamedType
 --      UnionMemberTypes | NamedType
 --
-unionTypeDefinition :: Maybe Text ->  Parser (Text, DataType)
-unionTypeDefinition typeDescription =
-  label "UnionTypeDefinition" $ do
-    typeName <- typDeclaration "union"
-    -- TODO: handle directives
-    _directives <- optionalDirectives
-    memberTypes <- unionMemberTypes
-    pure (
-        typeName,
-        DataUnion DataTyCon {
-             typeName,
-             typeDescription,
-             typeFingerprint = SystemFingerprint typeName,
-             typeData = map unionField memberTypes
-           }
-        )
-  where
-    unionField fieldType = createField [] "" ([], fieldType)
-    unionMemberTypes = operator '=' *> parseName `sepBy1` pipeLiteral
+unionTypeDefinition :: Maybe Text -> Parser (Text, DataType)
+unionTypeDefinition metaDescription = label "UnionTypeDefinition" $ do
+  typeName       <- typDeclaration "union"
+  metaDirectives <- optionalDirectives
+  memberTypes    <- unionMemberTypes
+  pure
+    ( typeName
+    , DataUnion DataTyCon
+      { typeName
+      , typeMeta        = Just Meta { metaDescription, metaDirectives }
+      , typeFingerprint = SystemFingerprint typeName
+      , typeData        = memberTypes
+      }
+    )
+  where unionMemberTypes = operator '=' *> parseName `sepBy1` pipeLiteral
 
 -- Enums : https://graphql.github.io/graphql-spec/June2018/#sec-Enums
 --
@@ -142,30 +158,21 @@
 --    Description(opt) EnumValue Directives(Const)(opt)
 --
 enumTypeDefinition :: Maybe Text -> Parser (Text, DataType)
-enumTypeDefinition typeDescription =
-  label "EnumTypeDefinition" $ do
-    typeName <- typDeclaration "enum"
-    -- TODO: handle directives
-    _directives <- optionalDirectives
-    enumValuesDefinition <- setOf enumValueDefinition
-    pure (
-           typeName,
-           DataEnum DataTyCon {
-             typeName,
-             typeDescription,
-             typeFingerprint = SystemFingerprint typeName,
-             typeData = enumValuesDefinition
-           }
-        )
-    where
-        enumValueDefinition = label "EnumValueDefinition" $ do
-            -- TODO: handle Description
-            _fieldDescription <- optDescription
-            enumValueName <- parseName
-            -- TODO: handle directives
-            _directive <- optionalDirectives
-            return enumValueName
+enumTypeDefinition metaDescription = label "EnumTypeDefinition" $ do
+  typeName              <- typDeclaration "enum"
+  metaDirectives        <- optionalDirectives
+  enumValuesDefinitions <- setOf enumValueDefinition
+  pure
+    ( typeName
+    , DataEnum DataTyCon
+      { typeName
+      , typeMeta        = Just Meta { metaDescription, metaDirectives }
+      , typeFingerprint = SystemFingerprint typeName
+      , typeData        = enumValuesDefinitions
+      }
+    )
 
+
 -- Input Objects : https://graphql.github.io/graphql-spec/June2018/#sec-Input-Objects
 --
 --   InputObjectTypeDefinition
@@ -175,43 +182,44 @@
 --     { InputValueDefinition(list) }
 --
 inputObjectTypeDefinition :: Maybe Text -> Parser (Text, DataType)
-inputObjectTypeDefinition typeDescription =
+inputObjectTypeDefinition metaDescription =
   label "InputObjectTypeDefinition" $ do
-    typeName <- typDeclaration "input"
-    -- TODO: handle directives
-    _directives <- optionalDirectives
-    fields <- inputFieldsDefinition
+    typeName       <- typDeclaration "input"
+    metaDirectives <- optionalDirectives
+    fields         <- inputFieldsDefinition
     pure
-       (
-         typeName,
-         DataInputObject DataTyCon {
-           typeName,
-           typeDescription,
-           typeFingerprint = SystemFingerprint typeName,
-           typeData = fields
-         }
-       )
-    where
-      inputFieldsDefinition :: Parser [(Key, DataField)]
-      inputFieldsDefinition = label "InputFieldsDefinition" $ setOf inputValueDefinition
+      ( typeName
+      , DataInputObject DataTyCon
+        { typeName
+        , typeMeta        = Just Meta { metaDescription, metaDirectives }
+        , typeFingerprint = SystemFingerprint typeName
+        , typeData        = fields
+        }
+      )
+ where
+  inputFieldsDefinition :: Parser [(Key, DataField)]
+  inputFieldsDefinition =
+    label "InputFieldsDefinition" $ setOf inputValueDefinition
 
 
 parseFinalDataType :: Maybe Text -> Parser (Text, DataType)
-parseFinalDataType description = label "TypeDefinition" $
-        inputObjectTypeDefinition description
+parseFinalDataType description =
+  label "TypeDefinition"
+    $   inputObjectTypeDefinition description
     <|> unionTypeDefinition description
     <|> enumTypeDefinition description
     <|> scalarTypeDefinition description
 
 parseDataType :: Parser (Text, RawDataType)
 parseDataType = label "TypeDefinition" $ do
-    description <- optDescription
-    types description
-    where
-      types description = interfaceTypeDefinition description <|>
-              objectTypeDefinition description <|>
-              finalDataT
-              where
-                finalDataT = do
-                  (name, datatype) <- parseFinalDataType description
-                  pure (name, FinalDataType datatype)
+  description <- optDescription
+  types description
+ where
+  types description =
+    interfaceTypeDefinition description
+      <|> objectTypeDefinition description
+      <|> finalDataT
+   where
+    finalDataT = do
+      (name, datatype) <- parseFinalDataType description
+      pure (name, FinalDataType datatype)
diff --git a/src/Data/Morpheus/Parsing/Internal/Create.hs b/src/Data/Morpheus/Parsing/Internal/Create.hs
deleted file mode 100644
--- a/src/Data/Morpheus/Parsing/Internal/Create.hs
+++ /dev/null
@@ -1,67 +0,0 @@
-{-# LANGUAGE NamedFieldPuns    #-}
-{-# LANGUAGE OverloadedStrings #-}
-
-module Data.Morpheus.Parsing.Internal.Create
-  ( createField
-  , createArgument
-  , createType
-  , createScalarType
-  , createEnumType
-  , createUnionType
-  , createDataTypeLib
-  ) where
-
-import           Data.Text                               (Text)
-
--- MORPHEUS
-import           Data.Morpheus.Error.Internal            (internalError)
-import           Data.Morpheus.Types.Internal.Data       (DataArguments, DataField (..), DataFingerprint (..),
-                                                          DataTyCon (..), DataType (..), DataTypeLib (..),
-                                                          DataValidator (..), TypeAlias (..), WrapperD, defineType,
-                                                          initTypeLib)
-import           Data.Morpheus.Types.Internal.Validation (Validation)
-
-
-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 -> ([WrapperD], Text) -> (Text, DataField)
-createArgument fieldName x = (fieldName, createField [] fieldName x)
-
-createType :: Text -> a -> DataTyCon a
-createType typeName typeData =
-  DataTyCon {typeName, typeDescription = Nothing, typeFingerprint = SystemFingerprint "", typeData}
-
-createScalarType :: Text -> (Text, DataType)
-createScalarType typeName = (typeName, DataScalar $ createType typeName (DataValidator pure))
-
-createEnumType :: Text -> [Text] -> (Text, DataType)
-createEnumType typeName typeData = (typeName, DataEnum $ createType typeName typeData)
-
-createUnionType :: Text -> [Text] -> (Text, DataType)
-createUnionType typeName typeData = (typeName, DataUnion $ createType typeName $ map unionField typeData)
-  where
-    unionField fieldType = createField [] "" ([], fieldType)
-
-createDataTypeLib :: [(Text, DataType)] -> Validation DataTypeLib
-createDataTypeLib types =
-  case takeByKey "Query" types of
-    (Just query, lib1) ->
-      case takeByKey "Mutation" lib1 of
-        (mutation, lib2) ->
-          case takeByKey "Subscription" lib2 of
-            (subscription, lib3) -> pure ((foldr defineType (initTypeLib query) lib3) {mutation, subscription})
-    _ -> internalError "Query Not Defined"
-  ----------------------------------------------------------------------------
-  where
-    takeByKey key lib =
-      case lookup key lib of
-        Just (DataObject value) -> (Just (key, value), filter ((/= key) . fst) lib)
-        _                       -> (Nothing, lib)
diff --git a/src/Data/Morpheus/Parsing/Internal/Internal.hs b/src/Data/Morpheus/Parsing/Internal/Internal.hs
--- a/src/Data/Morpheus/Parsing/Internal/Internal.hs
+++ b/src/Data/Morpheus/Parsing/Internal/Internal.hs
@@ -5,31 +5,52 @@
   , Position
   , processErrorBundle
   , getLocation
-  ) where
+  )
+where
 
-import qualified Data.List.NonEmpty                      as NonEmpty
-import           Data.Morpheus.Error.Utils               (toLocation)
-import           Data.Morpheus.Types.Internal.Base       (Location)
-import           Data.Morpheus.Types.Internal.Validation (GQLError (..), GQLErrors)
-import           Data.Text                               (Text, pack)
-import           Data.Void                               (Void)
-import           Text.Megaparsec                         (ParseError, ParseErrorBundle (ParseErrorBundle), Parsec,
-                                                          SourcePos, attachSourcePos, bundleErrors, bundlePosState,
-                                                          errorOffset, getSourcePos, parseErrorPretty)
+import qualified Data.List.NonEmpty            as NonEmpty
+import           Data.Morpheus.Error.Utils      ( toLocation )
+import           Data.Morpheus.Types.Internal.AST
+                                                ( Position )
+import           Data.Morpheus.Types.Internal.Resolving
+                                                ( GQLError(..)
+                                                , GQLErrors
+                                                )
+import           Data.Text                      ( Text
+                                                , pack
+                                                )
+import           Data.Void                      ( Void )
+import           Text.Megaparsec                ( ParseError
+                                                , ParseErrorBundle
+                                                  ( ParseErrorBundle
+                                                  )
+                                                , Parsec
+                                                , SourcePos
+                                                , attachSourcePos
+                                                , bundleErrors
+                                                , bundlePosState
+                                                , errorOffset
+                                                , getSourcePos
+                                                , parseErrorPretty
+                                                )
 
-type Position = Location
 
-getLocation :: Parser Location
+getLocation :: Parser Position
 getLocation = fmap toLocation getSourcePos
 
 type Parser = Parsec Void Text
 
 processErrorBundle :: ParseErrorBundle Text Void -> GQLErrors
 processErrorBundle = fmap parseErrorToGQLError . bundleToErrors
-  where
-    parseErrorToGQLError :: (ParseError Text Void, SourcePos) -> GQLError
-    parseErrorToGQLError (err, position) =
-      GQLError {desc = pack (parseErrorPretty err), positions = [toLocation position]}
-    bundleToErrors :: ParseErrorBundle Text Void -> [(ParseError Text Void, SourcePos)]
-    bundleToErrors ParseErrorBundle {bundleErrors, bundlePosState} =
-      NonEmpty.toList $ fst $ attachSourcePos errorOffset bundleErrors bundlePosState
+ where
+  parseErrorToGQLError :: (ParseError Text Void, SourcePos) -> GQLError
+  parseErrorToGQLError (err, position) = GQLError
+    { message   = pack (parseErrorPretty err)
+    , locations = [toLocation position]
+    }
+  bundleToErrors
+    :: ParseErrorBundle Text Void -> [(ParseError Text Void, SourcePos)]
+  bundleToErrors ParseErrorBundle { bundleErrors, bundlePosState } =
+    NonEmpty.toList $ fst $ attachSourcePos errorOffset
+                                            bundleErrors
+                                            bundlePosState
diff --git a/src/Data/Morpheus/Parsing/Internal/Pattern.hs b/src/Data/Morpheus/Parsing/Internal/Pattern.hs
--- a/src/Data/Morpheus/Parsing/Internal/Pattern.hs
+++ b/src/Data/Morpheus/Parsing/Internal/Pattern.hs
@@ -1,38 +1,89 @@
+{-# LANGUAGE NamedFieldPuns #-}
+
 module Data.Morpheus.Parsing.Internal.Pattern
-  ( inputValueDefinition
-  , fieldsDefinition
-  , typDeclaration
-  , optionalDirectives
-  ) where
+    ( inputValueDefinition
+    , fieldsDefinition
+    , typDeclaration
+    , optionalDirectives
+    , enumValueDefinition
+    )
+where
 
 
-import           Text.Megaparsec                         (label, many)
+import           Text.Megaparsec                ( label
+                                                , many
+                                                )
 
 -- MORPHEUS
-import           Data.Morpheus.Parsing.Internal.Create   (createField)
-import           Data.Morpheus.Parsing.Internal.Internal (Parser)
-import           Data.Morpheus.Parsing.Internal.Terms    (keyword, optDescription, litAssignment, operator, parseAssignment,
-                                                          parseMaybeTuple, parseName, parseType, setOf)
-import           Data.Morpheus.Parsing.Internal.Value    (parseDefaultValue, parseValue)
-import           Data.Morpheus.Types.Internal.Data       (DataField, Key, Name)
+import           Data.Morpheus.Parsing.Internal.Internal
+                                                ( Parser )
+import           Data.Morpheus.Parsing.Internal.Terms
+                                                ( keyword
+                                                , litAssignment
+                                                , operator
+                                                , optDescription
+                                                , parseAssignment
+                                                , parseMaybeTuple
+                                                , parseName
+                                                , parseType
+                                                , setOf
+                                                )
+import           Data.Morpheus.Parsing.Internal.Value
+                                                ( parseDefaultValue
+                                                , parseValue
+                                                )
+import           Data.Morpheus.Types.Internal.AST
+                                                ( DataField(..)
+                                                , Directive(..)
+                                                , Key
+                                                , Meta(..)
+                                                , DataEnumValue(..)
+                                                , Name
+                                                , TypeAlias(..)
+                                                )
 
 
+--  EnumValueDefinition: https://graphql.github.io/graphql-spec/June2018/#EnumValueDefinition
+--
+--  EnumValueDefinition
+--    Description(opt) EnumValue Directives(Const)(opt)
+--
+enumValueDefinition :: Parser DataEnumValue
+enumValueDefinition = label "EnumValueDefinition" $ do
+    metaDescription <- optDescription
+    enumName        <- parseName
+    metaDirectives  <- optionalDirectives
+    return $ DataEnumValue
+        { enumName
+        , enumMeta = Just Meta { metaDescription, metaDirectives }
+        }
+
 -- InputValue : https://graphql.github.io/graphql-spec/June2018/#InputValueDefinition
 --
 -- InputValueDefinition
 --   Description(opt) Name : Type DefaultValue(opt) Directives (Const)(opt)
 --
-inputValueDefinition ::  Parser (Key, DataField)
+inputValueDefinition :: Parser (Key, DataField)
 inputValueDefinition = label "InputValueDefinition" $ do
-    -- TODO: handle Description(opt)
-    _description <- optDescription
-    name <- parseName
+    metaDescription <- optDescription
+    fieldName       <- parseName
     litAssignment -- ':'
-    type_ <- parseType
-    -- TODO: handle default value
-    _ <- parseDefaultValue
-    _ <- optionalDirectives
-    pure (name, createField [] name type_)
+    (aliasWrappers, aliasTyCon) <- parseType
+    _                           <- parseDefaultValue
+    metaDirectives              <- optionalDirectives
+    pure
+        ( fieldName
+        , DataField
+            { fieldArgs     = []
+            , fieldArgsType = Nothing
+            , fieldName
+            , fieldType     = TypeAlias { aliasTyCon
+                                        , aliasWrappers
+                                        , aliasArgs     = Nothing
+                                        }
+            , fieldMeta     = Just Meta { metaDescription, metaDirectives }
+            }
+        )
 
 -- Field Arguments: https://graphql.github.io/graphql-spec/June2018/#sec-Field-Arguments
 --
@@ -40,7 +91,8 @@
 --   ( InputValueDefinition(list) )
 --
 argumentsDefinition :: Parser [(Key, DataField)]
-argumentsDefinition = label "ArgumentsDefinition" $  parseMaybeTuple inputValueDefinition
+argumentsDefinition =
+    label "ArgumentsDefinition" $ parseMaybeTuple inputValueDefinition
 
 
 --  FieldsDefinition : https://graphql.github.io/graphql-spec/June2018/#FieldsDefinition
@@ -55,17 +107,27 @@
 --  FieldDefinition
 --    Description(opt) Name ArgumentsDefinition(opt) : Type Directives(Const)(opt)
 --
-fieldDefinition ::  Parser (Key, DataField)
-fieldDefinition  = label "FieldDefinition" $ do
-    -- TODO: handle Description(opt)
-    _description <- optDescription
-    name <- parseName
-    args <- argumentsDefinition
+fieldDefinition :: Parser (Key, DataField)
+fieldDefinition = label "FieldDefinition" $ do
+    metaDescription <- optDescription
+    fieldName       <- parseName
+    fieldArgs       <- argumentsDefinition
     litAssignment -- ':'
-    type_ <- parseType
-    -- TODO: handle directives
-    _ <- optionalDirectives
-    pure (name, createField args name type_)
+    (aliasWrappers, aliasTyCon) <- parseType
+    metaDirectives              <- optionalDirectives
+    pure
+        ( fieldName
+        , DataField
+            { fieldName
+            , fieldArgs
+            , fieldArgsType = Nothing
+            , fieldType     = TypeAlias { aliasTyCon
+                                        , aliasWrappers
+                                        , aliasArgs     = Nothing
+                                        }
+            , fieldMeta     = Just Meta { metaDescription, metaDirectives }
+            }
+        )
 
 -- Directives : https://graphql.github.io/graphql-spec/June2018/#sec-Language.Directives
 --
@@ -74,19 +136,18 @@
 -- Directives[Const]
 -- Directive[Const](list)
 --
-optionalDirectives :: Parser [()]
+optionalDirectives :: Parser [Directive]
 optionalDirectives = label "Directives" $ many directive
 
 -- Directive[Const]
 --
 -- @ Name Arguments[Const](opt)
--- TODO:  returns real DataType
-directive :: Parser ()
+directive :: Parser Directive
 directive = label "Directive" $ do
     operator '@'
-    _name <- parseName
-    _args <- parseMaybeTuple (parseAssignment parseName parseValue)
-    pure ()
+    directiveName <- parseName
+    directiveArgs <- parseMaybeTuple (parseAssignment parseName parseValue)
+    pure Directive { directiveName, directiveArgs }
 
 
 -- typDeclaration : Not in spec ,start part of type definitions
@@ -96,5 +157,5 @@
 --
 typDeclaration :: Name -> Parser Name
 typDeclaration kind = do
-  keyword kind
-  parseName
+    keyword kind
+    parseName
diff --git a/src/Data/Morpheus/Parsing/Internal/Terms.hs b/src/Data/Morpheus/Parsing/Internal/Terms.hs
--- a/src/Data/Morpheus/Parsing/Internal/Terms.hs
+++ b/src/Data/Morpheus/Parsing/Internal/Terms.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE NamedFieldPuns    #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE TupleSections     #-}
 
@@ -27,19 +26,52 @@
   , keyword
   , operator
   , optDescription
-  ) where
+  )
+where
 
-import           Data.Functor                            (($>))
-import           Data.Text                               (Text, pack)
-import           Text.Megaparsec                         (between, label,try, many, manyTill, optional, sepBy, sepEndBy,
-                                                          skipMany, skipManyTill, try, (<?>), (<|>))
-import           Text.Megaparsec.Char                    (char, digitChar, letterChar, newline, printChar, space,
-                                                          space1, string)
+import           Data.Functor                   ( ($>) )
+import           Data.Text                      ( Text
+                                                , pack
+                                                , strip
+                                                )
+import           Text.Megaparsec                ( between
+                                                , label
+                                                , try
+                                                , many
+                                                , manyTill
+                                                , optional
+                                                , sepBy
+                                                , sepEndBy
+                                                , skipMany
+                                                , skipManyTill
+                                                , try
+                                                , (<?>)
+                                                , (<|>)
+                                                )
+import           Text.Megaparsec.Char           ( char
+                                                , digitChar
+                                                , letterChar
+                                                , newline
+                                                , printChar
+                                                , space
+                                                , space1
+                                                , string
+                                                )
 
 -- MORPHEUS
-import           Data.Morpheus.Parsing.Internal.Internal (Parser, Position, getLocation)
-import           Data.Morpheus.Types.Internal.Data       (DataTypeWrapper (..), Key, Description , Name, WrapperD (..), toHSWrappers)
-import           Data.Morpheus.Types.Internal.Value      (convertToHaskellName)
+import           Data.Morpheus.Parsing.Internal.Internal
+                                                ( Parser
+                                                , Position
+                                                , getLocation
+                                                )
+import           Data.Morpheus.Types.Internal.AST
+                                                ( DataTypeWrapper(..)
+                                                , Key
+                                                , Description
+                                                , Name
+                                                , TypeWrapper(..)
+                                                , toHSWrappers
+                                                , convertToHaskellName )
 
 
 -- Name : https://graphql.github.io/graphql-spec/June2018/#sec-Names
@@ -57,7 +89,8 @@
 
 -- LITERALS
 setLiteral :: Parser [a] -> Parser [a]
-setLiteral = between (char '{' *> spaceAndComments) (char '}' *> spaceAndComments)
+setLiteral =
+  between (char '{' *> spaceAndComments) (char '}' *> spaceAndComments)
 
 pipeLiteral :: Parser ()
 pipeLiteral = char '|' *> spaceAndComments
@@ -71,19 +104,17 @@
 -- PRIMITIVE
 ------------------------------------
 token :: Parser Text
-token =
-  label "token" $ do
-    firstChar <- letterChar <|> char '_'
-    restToken <- many $ letterChar <|> char '_' <|> digitChar
-    spaceAndComments
-    return $ convertToHaskellName $ pack $ firstChar : restToken
+token = label "token" $ do
+  firstChar <- letterChar <|> char '_'
+  restToken <- many $ letterChar <|> char '_' <|> digitChar
+  spaceAndComments
+  return $ convertToHaskellName $ pack $ firstChar : restToken
 
 qualifier :: Parser (Text, Position)
-qualifier =
-  label "qualifier" $ do
-    position <- getLocation
-    value <- token
-    return (value, position)
+qualifier = label "qualifier" $ do
+  position <- getLocation
+  value    <- token
+  return (value, position)
 
 
 -- Variable : https://graphql.github.io/graphql-spec/June2018/#Variable
@@ -91,12 +122,11 @@
 -- Variable :  $Name
 --
 variable :: Parser (Text, Position)
-variable =
-  label "variable" $ do
-    position' <- getLocation
-    _ <- char '$'
-    varName' <- token
-    return (varName', position')
+variable = label "variable" $ do
+  position' <- getLocation
+  _         <- char '$'
+  varName'  <- token
+  return (varName', position')
 
 spaceAndComments1 :: Parser ()
 spaceAndComments1 = space1 *> spaceAndComments
@@ -111,15 +141,18 @@
 optDescription = optional parseDescription
 
 parseDescription :: Parser Text
-parseDescription = pack <$> (blockDescription <|> singleLine) <* spaceAndComments
-    where
-      blockDescription = blockQuotes *> manyTill (printChar <|> newline)   blockQuotes <* spaceAndComments
-        where
-         blockQuotes = string "\"\"\""
-      ----------------------------
-      singleLine = stringQuote *> manyTill printChar  stringQuote <* spaceAndComments
-        where
-            stringQuote = char '"'
+parseDescription =
+  strip . pack <$> (blockDescription <|> singleLine) <* spaceAndComments
+ where
+  blockDescription =
+    blockQuotes
+      *> manyTill (printChar <|> newline) blockQuotes
+      <* spaceAndComments
+    where blockQuotes = string "\"\"\""
+  ----------------------------
+  singleLine =
+    stringQuote *> manyTill printChar stringQuote <* spaceAndComments
+    where stringQuote = char '"'
 
 -- Ignored Tokens : https://graphql.github.io/graphql-spec/June2018/#sec-Source-Text.Ignored-Tokens
 --  Ignored:
@@ -133,9 +166,9 @@
 spaceAndComments = ignoredTokens
 
 ignoredTokens :: Parser ()
-ignoredTokens = label "IgnoredTokens" $ space *> skipMany inlineComment *> space
-  where
-    inlineComment = char '#' *> skipManyTill printChar newline *> space
+ignoredTokens =
+  label "IgnoredTokens" $ space *> skipMany inlineComment *> space
+  where inlineComment = char '#' *> skipManyTill printChar newline *> space
     ------------------------------------------------------------------------
 
 -- COMPLEX
@@ -156,20 +189,18 @@
 parseMaybeTuple parser = parseTuple parser <|> pure []
 
 parseTuple :: Parser a -> Parser [a]
-parseTuple parser =
-  label "Tuple" $
-  between
-    (char '(' *> spaceAndComments)
-    (char ')' *> spaceAndComments)
-    (parser `sepBy` (many (char ',') *> spaceAndComments) <?> "empty Tuple value!")
+parseTuple parser = label "Tuple" $ between
+  (char '(' *> spaceAndComments)
+  (char ')' *> spaceAndComments)
+  (parser `sepBy` (many (char ',') *> spaceAndComments) <?> "empty Tuple value!"
+  )
 
 parseAssignment :: (Show a, Show b) => Parser a -> Parser b -> Parser (a, b)
-parseAssignment nameParser valueParser =
-  label "assignment" $ do
-    name' <- nameParser
-    litAssignment
-    value' <- valueParser
-    pure (name', value')
+parseAssignment nameParser valueParser = label "assignment" $ do
+  name' <- nameParser
+  litAssignment
+  value' <- valueParser
+  pure (name', value')
 
 -- Type Conditions: https://graphql.github.io/graphql-spec/June2018/#sec-Type-Conditions
 --
@@ -185,36 +216,36 @@
 spreadLiteral :: Parser Position
 spreadLiteral = do
   index <- getLocation
-  _ <- string "..."
+  _     <- string "..."
   space
   return index
 
 parseWrappedType :: Parser ([DataTypeWrapper], Text)
 parseWrappedType = (unwrapped <|> wrapped) <* spaceAndComments
-  where
-    unwrapped :: Parser ([DataTypeWrapper], Text)
-    unwrapped = ([], ) <$> token <* spaceAndComments
-    ----------------------------------------------
-    wrapped :: Parser ([DataTypeWrapper], Text)
-    wrapped =
-      between
-        (char '[' *> spaceAndComments)
-        (char ']' *> spaceAndComments)
-        (do (wrappers, name) <- unwrapped <|> wrapped
-            nonNull' <- parseNonNull
-            return ((ListType : nonNull') ++ wrappers, name))
+ where
+  unwrapped :: Parser ([DataTypeWrapper], Text)
+  unwrapped = ([], ) <$> token <* spaceAndComments
+  ----------------------------------------------
+  wrapped :: Parser ([DataTypeWrapper], Text)
+  wrapped = between
+    (char '[' *> spaceAndComments)
+    (char ']' *> spaceAndComments)
+    (do
+      (wrappers, name) <- unwrapped <|> wrapped
+      nonNull'         <- parseNonNull
+      return ((ListType : nonNull') ++ wrappers, name)
+    )
 
 -- Field Alias : https://graphql.github.io/graphql-spec/June2018/#sec-Field-Alias
 -- Alias
 --  Name:
 parseAlias :: Parser (Maybe Key)
 parseAlias = try (optional alias) <|> pure Nothing
-    where
-        alias = label "alias" $ token <* char ':' <* spaceAndComments
+  where alias = label "alias" $ token <* char ':' <* spaceAndComments
 
 
-parseType :: Parser ([WrapperD],Key)
+parseType :: Parser ([TypeWrapper], Key)
 parseType = do
-    (wrappers, fieldType) <- parseWrappedType
-    nonNull <- parseNonNull
-    pure (toHSWrappers $ nonNull ++ wrappers, fieldType)
+  (wrappers, fieldType) <- parseWrappedType
+  nonNull               <- parseNonNull
+  pure (toHSWrappers $ nonNull ++ wrappers, fieldType)
diff --git a/src/Data/Morpheus/Parsing/Internal/Value.hs b/src/Data/Morpheus/Parsing/Internal/Value.hs
--- a/src/Data/Morpheus/Parsing/Internal/Value.hs
+++ b/src/Data/Morpheus/Parsing/Internal/Value.hs
@@ -5,49 +5,68 @@
   ( parseValue
   , enumValue
   , parseDefaultValue
-  ) where
+  )
+where
 
-import           Data.Functor                            (($>))
-import           Data.Text                               (pack)
-import           Text.Megaparsec                         (anySingleBut, between, choice, label, many, optional, sepBy,
-                                                          (<|>))
-import           Text.Megaparsec.Char                    (char, string)
-import           Text.Megaparsec.Char.Lexer              (scientific)
+import           Data.Functor                   ( ($>) )
+import           Data.Text                      ( pack )
+import           Text.Megaparsec                ( anySingleBut
+                                                , between
+                                                , choice
+                                                , label
+                                                , many
+                                                , optional
+                                                , sepBy
+                                                , (<|>)
+                                                )
+import           Text.Megaparsec.Char           ( char
+                                                , string
+                                                )
+import           Text.Megaparsec.Char.Lexer     ( scientific )
 
 --
 -- MORPHEUS
-import           Data.Morpheus.Parsing.Internal.Internal (Parser)
-import           Data.Morpheus.Parsing.Internal.Terms    (litEquals, parseAssignment, setOf, spaceAndComments, token)
-import           Data.Morpheus.Types.Internal.Value      (ScalarValue (..), Value (..), decodeScientific)
+import           Data.Morpheus.Parsing.Internal.Internal
+                                                ( Parser )
+import           Data.Morpheus.Parsing.Internal.Terms
+                                                ( litEquals
+                                                , parseAssignment
+                                                , setOf
+                                                , spaceAndComments
+                                                , token
+                                                )
+import           Data.Morpheus.Types.Internal.AST
+                                                ( ScalarValue(..)
+                                                , Value(..)
+                                                , decodeScientific
+                                                )
 
 parseDefaultValue :: Parser (Maybe Value)
-parseDefaultValue =
-  optional $ do
-    litEquals
-    parseValue
+parseDefaultValue = optional $ do
+  litEquals
+  parseValue
 
 parseValue :: Parser Value
-parseValue =
-  label "value" $ do
-    value <- 
-        valueNull 
-        <|> booleanValue 
-        <|> valueNumber 
-        <|> enumValue 
-        <|> stringValue 
-        <|> objectValue 
-        <|> listValue
-    spaceAndComments
-    return value
+parseValue = label "value" $ do
+  value <-
+    valueNull
+    <|> booleanValue
+    <|> valueNumber
+    <|> enumValue
+    <|> stringValue
+    <|> objectValue
+    <|> listValue
+  spaceAndComments
+  return value
 
 valueNull :: Parser Value
 valueNull = string "null" $> Null
 
 booleanValue :: Parser Value
 booleanValue = boolTrue <|> boolFalse
-  where
-    boolTrue = string "true" $> Scalar (Boolean True)
-    boolFalse = string "false" $> Scalar (Boolean False)
+ where
+  boolTrue  = string "true" $> Scalar (Boolean True)
+  boolFalse = string "false" $> Scalar (Boolean False)
 
 valueNumber :: Parser Value
 valueNumber = Scalar . decodeScientific <$> scientific
@@ -59,30 +78,26 @@
   return enum
 
 escaped :: Parser Char
-escaped =
-  label "escaped" $ do
-    x <- anySingleBut '\"'
-    if x == '\\'
-      then choice (zipWith escapeChar codes replacements)
-      else pure x
-  where
-    replacements = ['\b', '\n', '\f', '\r', '\t', '\\', '\"', '/']
-    codes = ['b', 'n', 'f', 'r', 't', '\\', '\"', '/']
-    escapeChar code replacement = char code >> return replacement
+escaped = label "escaped" $ do
+  x <- anySingleBut '\"'
+  if x == '\\' then choice (zipWith escapeChar codes replacements) else pure x
+ where
+  replacements = ['\b', '\n', '\f', '\r', '\t', '\\', '\"', '/']
+  codes        = ['b', 'n', 'f', 'r', 't', '\\', '\"', '/']
+  escapeChar code replacement = char code >> return replacement
 
 stringValue :: Parser Value
-stringValue = label "stringValue" $ Scalar . String . pack <$> between (char '"') (char '"') (many escaped)
+stringValue = label "stringValue" $ Scalar . String . pack <$> between
+  (char '"')
+  (char '"')
+  (many escaped)
 
 listValue :: Parser Value
-listValue =
-  label "listValue" $
-  List <$>
-  between
-    (char '[' *> spaceAndComments)
-    (char ']' *> spaceAndComments)
-    (parseValue `sepBy` (char ',' *> spaceAndComments))
+listValue = label "listValue" $ List <$> between
+  (char '[' *> spaceAndComments)
+  (char ']' *> spaceAndComments)
+  (parseValue `sepBy` (char ',' *> spaceAndComments))
 
 objectValue :: Parser Value
 objectValue = label "objectValue" $ Object <$> setOf entry
-  where
-    entry = parseAssignment token parseValue
+  where entry = parseAssignment token parseValue
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
@@ -6,73 +6,100 @@
 
 module Data.Morpheus.Parsing.JSONSchema.Parse
   ( decodeIntrospection
-  ) where
+  )
+where
 
 import           Data.Aeson
-import           Data.ByteString.Lazy                    (ByteString)
-import           Data.Morpheus.Error.Internal            (internalError)
-import           Data.Morpheus.Parsing.Internal.Create   (createArgument, createDataTypeLib, createEnumType,
-                                                          createField, createScalarType, createType, createUnionType)
-import           Data.Morpheus.Parsing.JSONSchema.Types  (EnumValue (..), Field (..), InputValue (..),
-                                                          Introspection (..), Schema (..), Type (..))
-import           Data.Morpheus.Schema.TypeKind           (TypeKind (..))
-import           Data.Morpheus.Types.Internal.Data       (DataField, DataType (..), 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)
+import           Data.ByteString.Lazy           ( ByteString )
+import           Data.Morpheus.Error.Internal   ( internalError )
+import           Data.Morpheus.Parsing.JSONSchema.Types
+                                                ( EnumValue(..)
+                                                , Field(..)
+                                                , InputValue(..)
+                                                , Introspection(..)
+                                                , Schema(..)
+                                                , Type(..)
+                                                )
+import           Data.Morpheus.Schema.TypeKind  ( TypeKind(..) )
+import           Data.Morpheus.Types.Internal.AST
+                                                ( DataField
+                                                , DataType(..)
+                                                , DataTypeLib
+                                                , DataTypeWrapper(..)
+                                                , Key
+                                                , TypeWrapper
+                                                , createArgument
+                                                , createDataTypeLib
+                                                , createEnumType
+                                                , createField
+                                                , createScalarType
+                                                , createType
+                                                , createUnionType
+                                                , toHSWrappers
+                                                )
+import           Data.Morpheus.Types.Internal.Resolving
+                                                ( Validation )
+import           Data.Morpheus.Types.IO         ( JSONResponse(..) )
+import           Data.Semigroup                 ( (<>) )
+import           Data.Text                      ( Text
+                                                , pack
+                                                )
 
 decodeIntrospection :: ByteString -> Validation DataTypeLib
-decodeIntrospection jsonDoc =
-  case jsonSchema of
-    Left errors -> internalError $ pack errors
-    Right JSONResponse {responseData = Just Introspection {__schema = Schema {types}}} ->
-      traverse parse types >>= createDataTypeLib
-    Right res -> internalError (pack $ show res)
-  where
-    jsonSchema :: Either String (JSONResponse Introspection)
-    jsonSchema = eitherDecode jsonDoc
+decodeIntrospection jsonDoc = case jsonSchema of
+  Left errors -> internalError $ pack errors
+  Right JSONResponse { responseData = Just Introspection { __schema = Schema { types } } }
+    -> traverse parse types >>= createDataTypeLib . concat
+  Right res -> internalError (pack $ show res)
+ where
+  jsonSchema :: Either String (JSONResponse Introspection)
+  jsonSchema = eitherDecode jsonDoc
 
 class ParseJSONSchema a b where
-  parse :: a -> Validation (Key, b)
+  parse :: a -> Validation b
 
-instance ParseJSONSchema Type DataType 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
+instance ParseJSONSchema Type [(Key,DataType)] 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  -> internalError "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, DataInputObject $ createType typeName fields)
-  parse Type {name = Just typeName, kind = OBJECT, fields = Just oFields} = do
-    fields <- traverse parse oFields
-    pure (typeName, DataObject $ createType typeName fields)
-  parse x = internalError $ "Unsuported type" <> pack (show x)
+      Just uni -> pure [createUnionType typeName uni]
+  parse Type { name = Just typeName, kind = INPUT_OBJECT, inputFields = Just iFields }
+    = do
+      fields <- traverse parse iFields
+      pure [(typeName, DataInputObject $ createType typeName fields)]
+  parse Type { name = Just typeName, kind = OBJECT, fields = Just oFields } =
+    do
+      fields <- traverse parse oFields
+      pure [(typeName, DataObject $ createType typeName fields)]
+  parse _ = pure []
 
-instance ParseJSONSchema Field DataField where
-  parse Field {fieldName, fieldArgs, fieldType} = do
+instance ParseJSONSchema Field (Key,DataField) where
+  parse Field { fieldName, fieldArgs, fieldType } = do
     fType <- fieldTypeFromJSON fieldType
-    args <- traverse genArg fieldArgs
+    args  <- traverse genArg fieldArgs
     pure (fieldName, createField args fieldName fType)
-    where
-      genArg InputValue {inputName = argName, inputType = argType} =
-        createArgument argName <$> fieldTypeFromJSON argType
+   where
+    genArg InputValue { inputName = argName, inputType = argType } =
+      createArgument argName <$> fieldTypeFromJSON argType
 
-instance ParseJSONSchema InputValue DataField where
-  parse InputValue {inputName, inputType} = do
+instance ParseJSONSchema InputValue (Key,DataField) where
+  parse InputValue { inputName, inputType } = do
     fieldType <- fieldTypeFromJSON inputType
     pure (inputName, createField [] inputName fieldType)
 
-fieldTypeFromJSON :: Type -> Validation ([WrapperD], Text)
+fieldTypeFromJSON :: Type -> Validation ([TypeWrapper], 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)
+ 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/Request/Arguments.hs b/src/Data/Morpheus/Parsing/Request/Arguments.hs
--- a/src/Data/Morpheus/Parsing/Request/Arguments.hs
+++ b/src/Data/Morpheus/Parsing/Request/Arguments.hs
@@ -2,17 +2,35 @@
 
 module Data.Morpheus.Parsing.Request.Arguments
   ( maybeArguments
-  ) where
+  )
+where
 
-import           Text.Megaparsec                               (label, (<|>))
+import           Text.Megaparsec                ( label
+                                                , (<|>)
+                                                )
 
 -- MORPHEUS
-import           Data.Morpheus.Parsing.Internal.Internal       (Parser, getLocation)
-import           Data.Morpheus.Parsing.Internal.Terms          (parseAssignment, parseMaybeTuple, token, variable)
-import           Data.Morpheus.Parsing.Internal.Value          (enumValue, parseValue)
-import           Data.Morpheus.Types.Internal.AST.RawSelection (Argument (..), RawArgument (..), RawArguments)
-import           Data.Morpheus.Types.Internal.AST.Selection    (ArgumentOrigin (..))
-import           Data.Morpheus.Types.Internal.Base             (Reference (..))
+import           Data.Morpheus.Parsing.Internal.Internal
+                                                ( Parser
+                                                , getLocation
+                                                )
+import           Data.Morpheus.Parsing.Internal.Terms
+                                                ( parseAssignment
+                                                , parseMaybeTuple
+                                                , token
+                                                , variable
+                                                )
+import           Data.Morpheus.Parsing.Internal.Value
+                                                ( enumValue
+                                                , parseValue
+                                                )
+import           Data.Morpheus.Types.Internal.AST
+                                                ( ValueOrigin(..)
+                                                , Argument(..)
+                                                , RawArgument(..)
+                                                , RawArguments
+                                                , Ref(..)
+                                                )
 
 
 -- Arguments : https://graphql.github.io/graphql-spec/June2018/#sec-Language.Arguments
@@ -24,19 +42,19 @@
 --  Name : Value[Const]
 -- TODO: move variable to Value
 valueArgument :: Parser RawArgument
-valueArgument =
-  label "valueArgument" $ do
-    argumentPosition <- getLocation
-    argumentValue <- parseValue <|> enumValue
-    pure $ RawArgument $ Argument {argumentValue, argumentOrigin = INLINE, argumentPosition}
+valueArgument = label "valueArgument" $ do
+  argumentPosition <- getLocation
+  argumentValue    <- parseValue <|> enumValue
+  pure $ RawArgument $ Argument { argumentValue
+                                , argumentOrigin   = INLINE
+                                , argumentPosition
+                                }
 
 variableArgument :: Parser RawArgument
-variableArgument =
-  label "variableArgument" $ do
-    (referenceName, referencePosition) <- variable
-    pure $ VariableReference $ Reference {referenceName, referencePosition}
+variableArgument = label "variableArgument" $ do
+  (refName, refPosition) <- variable
+  pure $ VariableRef $ Ref { refName, refPosition }
 
 maybeArguments :: Parser RawArguments
 maybeArguments = label "maybeArguments" $ parseMaybeTuple argument
-  where
-    argument = parseAssignment token (valueArgument <|> variableArgument)
+  where argument = parseAssignment token (valueArgument <|> variableArgument)
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
@@ -2,24 +2,47 @@
 {-# LANGUAGE OverloadedStrings #-}
 
 module Data.Morpheus.Parsing.Request.Operation
-  (parseOperation
-  ) where
+  ( parseOperation
+  )
+where
 
-import           Data.Functor                               (($>))
-import           Data.Text                                  (Text)
-import           Text.Megaparsec                            (label, optional, (<?>), (<|>))
-import           Text.Megaparsec.Char                       (string)
+import           Data.Functor                   ( ($>) )
+import           Data.Text                      ( Text )
+import           Text.Megaparsec                ( label
+                                                , optional
+                                                , (<?>)
+                                                , (<|>)
+                                                )
+import           Text.Megaparsec.Char           ( string )
 
 --
 -- MORPHEUS
-import           Data.Morpheus.Parsing.Internal.Internal    (Parser, getLocation)
-import           Data.Morpheus.Parsing.Internal.Pattern     (optionalDirectives)
-import           Data.Morpheus.Parsing.Internal.Terms       (operator, parseMaybeTuple, parseName, parseType,
-                                                             spaceAndComments1, variable)
-import           Data.Morpheus.Parsing.Internal.Value       (parseDefaultValue)
-import           Data.Morpheus.Parsing.Request.Selection    (parseSelectionSet)
-import           Data.Morpheus.Types.Internal.AST.Operation (DefaultValue, Operation (..), RawOperation, Variable (..))
-import           Data.Morpheus.Types.Internal.Data          (OperationType (..), isNullable)
+import           Data.Morpheus.Parsing.Internal.Internal
+                                                ( Parser
+                                                , getLocation
+                                                )
+import           Data.Morpheus.Parsing.Internal.Pattern
+                                                ( optionalDirectives )
+import           Data.Morpheus.Parsing.Internal.Terms
+                                                ( operator
+                                                , parseMaybeTuple
+                                                , parseName
+                                                , parseType
+                                                , spaceAndComments1
+                                                , variable
+                                                )
+import           Data.Morpheus.Parsing.Internal.Value
+                                                ( parseDefaultValue )
+import           Data.Morpheus.Parsing.Request.Selection
+                                                ( parseSelectionSet )
+import           Data.Morpheus.Types.Internal.AST
+                                                ( DefaultValue
+                                                , Operation(..)
+                                                , RawOperation
+                                                , Variable(..)
+                                                , OperationType(..)
+                                                , isNullable
+                                                )
 
 
 -- Variables :  https://graphql.github.io/graphql-spec/June2018/#VariableDefinition
@@ -28,21 +51,20 @@
 --    Variable : Type DefaultValue(opt)
 --
 variableDefinition :: Parser (Text, Variable DefaultValue)
-variableDefinition =
-  label "VariableDefinition" $ do
-    (name, variablePosition) <- variable
-    operator ':'
-    (variableTypeWrappers, variableType) <- parseType
-    defaultValue <- parseDefaultValue
-    pure
-      ( name
-      , Variable
-          { variableType
-          , isVariableRequired = not (isNullable variableTypeWrappers)
-          , variableTypeWrappers
-          , variablePosition
-          , variableValue = defaultValue
-          })
+variableDefinition = label "VariableDefinition" $ do
+  (name, variablePosition) <- variable
+  operator ':'
+  (variableTypeWrappers, variableType) <- parseType
+  defaultValue                         <- parseDefaultValue
+  pure
+    ( name
+    , Variable { variableType
+               , isVariableRequired   = not (isNullable variableTypeWrappers)
+               , variableTypeWrappers
+               , variablePosition
+               , variableValue        = defaultValue
+               }
+    )
 
 -- Operations : https://graphql.github.io/graphql-spec/June2018/#sec-Language.Operations
 --
@@ -52,38 +74,45 @@
 --   OperationType: one of
 --     query, mutation,    subscription
 parseOperationDefinition :: Parser RawOperation
-parseOperationDefinition =
-  label "OperationDefinition" $ do
-    operationPosition <- getLocation
-    operationType <- parseOperationType
-    operationName <- optional parseName
-    operationArgs <- parseMaybeTuple variableDefinition
-    -- TODO: handle directives
-    _directives <- optionalDirectives
-    operationSelection <- parseSelectionSet
-    pure (Operation {operationName, operationType, operationArgs, operationSelection, operationPosition})
+parseOperationDefinition = label "OperationDefinition" $ do
+  operationPosition  <- getLocation
+  operationType      <- parseOperationType
+  operationName      <- optional parseName
+  operationArgs      <- parseMaybeTuple variableDefinition
+  -- TODO: handle directives
+  _directives        <- optionalDirectives
+  operationSelection <- parseSelectionSet
+  pure
+    (Operation { operationName
+               , operationType
+               , operationArgs
+               , operationSelection
+               , operationPosition
+               }
+    )
 
 parseOperationType :: Parser OperationType
-parseOperationType =
-  label "OperationType" $ do
-    kind <- (string "query" $> Query) <|> (string "mutation" $> Mutation) <|> (string "subscription" $> Subscription)
-    spaceAndComments1
-    return kind
+parseOperationType = label "OperationType" $ do
+  kind <-
+    (string "query" $> Query)
+    <|> (string "mutation" $> Mutation)
+    <|> (string "subscription" $> Subscription)
+  spaceAndComments1
+  return kind
 
 parseAnonymousQuery :: Parser RawOperation
-parseAnonymousQuery =
-  label "AnonymousQuery" $ do
-    operationPosition <- getLocation
-    operationSelection <- parseSelectionSet
-    pure
-      (Operation
-         { operationName = Nothing
-         , operationType = Query
-         , operationArgs = []
-         , operationSelection
-         , operationPosition
-         }) <?>
-      "can't parse AnonymousQuery"
+parseAnonymousQuery = label "AnonymousQuery" $ do
+  operationPosition  <- getLocation
+  operationSelection <- parseSelectionSet
+  pure
+      (Operation { operationName      = Nothing
+                 , operationType      = Query
+                 , operationArgs      = []
+                 , operationSelection
+                 , operationPosition
+                 }
+      )
+    <?> "can't parse AnonymousQuery"
 
 parseOperation :: Parser RawOperation
 parseOperation = parseAnonymousQuery <|> parseOperationDefinition
diff --git a/src/Data/Morpheus/Parsing/Request/Parser.hs b/src/Data/Morpheus/Parsing/Request/Parser.hs
--- a/src/Data/Morpheus/Parsing/Request/Parser.hs
+++ b/src/Data/Morpheus/Parsing/Request/Parser.hs
@@ -3,44 +3,61 @@
 
 module Data.Morpheus.Parsing.Request.Parser
   ( parseGQL
-  ) where
+  )
+where
 
-import qualified Data.Aeson                              as Aeson (Value (..))
-import           Data.HashMap.Lazy                       (toList)
-import           Data.Text                               (Text)
-import           Data.Void                               (Void)
-import           Text.Megaparsec                         (ParseErrorBundle, eof, label, manyTill, runParser)
+import qualified Data.Aeson                    as Aeson
+                                                ( Value(..) )
+import           Data.HashMap.Lazy              ( toList )
+import           Data.Text                      ( Text )
+import           Data.Void                      ( Void )
+import           Text.Megaparsec                ( ParseErrorBundle
+                                                , eof
+                                                , label
+                                                , manyTill
+                                                , runParser
+                                                )
 
 --
 -- MORPHEUS
-import           Data.Morpheus.Parsing.Internal.Internal (Parser, processErrorBundle)
-import           Data.Morpheus.Parsing.Internal.Terms    (spaceAndComments)
-import           Data.Morpheus.Parsing.Request.Operation (parseOperation)
-import           Data.Morpheus.Parsing.Request.Selection (parseFragmentDefinition)
-import           Data.Morpheus.Types.Internal.Validation (Validation)
-import           Data.Morpheus.Types.Internal.Value      (Value (..), replaceValue)
-import           Data.Morpheus.Types.IO                  (GQLRequest (..))
-import           Data.Morpheus.Types.Types               (GQLQueryRoot (..))
+import           Data.Morpheus.Parsing.Internal.Internal
+                                                ( Parser
+                                                , processErrorBundle
+                                                )
+import           Data.Morpheus.Parsing.Internal.Terms
+                                                ( spaceAndComments )
+import           Data.Morpheus.Parsing.Request.Operation
+                                                ( parseOperation )
+import           Data.Morpheus.Parsing.Request.Selection
+                                                ( parseFragmentDefinition )
+import           Data.Morpheus.Types.Internal.Resolving
+                                                ( Validation
+                                                , Failure(..)
+                                                )
+import           Data.Morpheus.Types.Internal.AST
+                                                ( Value(..)
+                                                , replaceValue
+                                                , GQLQuery(..)
+                                                )
+import           Data.Morpheus.Types.IO         ( GQLRequest(..) )
 
-parseGQLSyntax :: Text -> Either (ParseErrorBundle Text Void) GQLQueryRoot
+
+parseGQLSyntax :: Text -> Either (ParseErrorBundle Text Void) GQLQuery
 parseGQLSyntax = runParser request "<input>"
-  where
-    request :: Parser GQLQueryRoot
-    request =
-      label "GQLQueryRoot" $ do
-        spaceAndComments
-        operation <- parseOperation
-        fragments <- manyTill parseFragmentDefinition eof
-        pure GQLQueryRoot {operation, fragments, inputVariables = []}
+ where
+  request :: Parser GQLQuery
+  request = label "GQLQuery" $ do
+    spaceAndComments
+    operation <- parseOperation
+    fragments <- manyTill parseFragmentDefinition eof
+    pure GQLQuery { operation, fragments, inputVariables = [] }
 
-parseGQL :: GQLRequest -> Validation GQLQueryRoot
-parseGQL GQLRequest {query, variables} =
-  case parseGQLSyntax query of
-    Right root      -> Right $ root {inputVariables = toVariableMap variables}
-    Left parseError -> Left $ processErrorBundle parseError
-  where
-    toVariableMap :: Maybe Aeson.Value -> [(Text, Value)]
-    toVariableMap (Just (Aeson.Object x)) = map toMorpheusValue (toList x)
-      where
-        toMorpheusValue (key, value) = (key, replaceValue value)
-    toVariableMap _ = []
+parseGQL :: GQLRequest -> Validation GQLQuery
+parseGQL GQLRequest { query, variables } = case parseGQLSyntax query of
+  Right root       -> pure $ root { inputVariables = toVariableMap variables }
+  Left  parseError -> failure $ processErrorBundle parseError
+ where
+  toVariableMap :: Maybe Aeson.Value -> [(Text, Value)]
+  toVariableMap (Just (Aeson.Object x)) = map toMorpheusValue (toList x)
+    where toMorpheusValue (key, value) = (key, replaceValue value)
+  toVariableMap _ = []
diff --git a/src/Data/Morpheus/Parsing/Request/Selection.hs b/src/Data/Morpheus/Parsing/Request/Selection.hs
--- a/src/Data/Morpheus/Parsing/Request/Selection.hs
+++ b/src/Data/Morpheus/Parsing/Request/Selection.hs
@@ -4,21 +4,42 @@
 module Data.Morpheus.Parsing.Request.Selection
   ( parseSelectionSet
   , parseFragmentDefinition
-  ) where
+  )
+where
 
-import           Data.Text                                     (Text)
-import           Text.Megaparsec                               (label, try, (<|>))
+import           Data.Text                      ( Text )
+import           Text.Megaparsec                ( label
+                                                , try
+                                                , (<|>)
+                                                )
 
 --
 -- MORPHEUS
-import           Data.Morpheus.Parsing.Internal.Internal       (Parser, getLocation)
-import           Data.Morpheus.Parsing.Internal.Pattern        (optionalDirectives)
-import           Data.Morpheus.Parsing.Internal.Terms          (keyword, parseAlias, parseName, parseTypeCondition,
-                                                                setOf, spreadLiteral, token)
-import           Data.Morpheus.Parsing.Request.Arguments       (maybeArguments)
-import           Data.Morpheus.Types.Internal.AST.RawSelection (Fragment (..), RawArguments, RawSelection (..),
-                                                                RawSelectionSet, Reference (..))
-import           Data.Morpheus.Types.Internal.AST.Selection    (Selection (..))
+import           Data.Morpheus.Parsing.Internal.Internal
+                                                ( Parser
+                                                , getLocation
+                                                )
+import           Data.Morpheus.Parsing.Internal.Pattern
+                                                ( optionalDirectives )
+import           Data.Morpheus.Parsing.Internal.Terms
+                                                ( keyword
+                                                , parseAlias
+                                                , parseName
+                                                , parseTypeCondition
+                                                , setOf
+                                                , spreadLiteral
+                                                , token
+                                                )
+import           Data.Morpheus.Parsing.Request.Arguments
+                                                ( maybeArguments )
+import           Data.Morpheus.Types.Internal.AST
+                                                ( Selection(..)
+                                                , Fragment(..)
+                                                , RawArguments
+                                                , RawSelection(..)
+                                                , RawSelectionSet
+                                                , Ref(..)
+                                                )
 
 
 -- Selection Sets : https://graphql.github.io/graphql-spec/June2018/#sec-Selection-Sets
@@ -33,11 +54,12 @@
 --
 parseSelectionSet :: Parser RawSelectionSet
 parseSelectionSet = label "SelectionSet" $ setOf parseSelection
-  where
-    parseSelection = label "Selection" $
-            try inlineFragment
-        <|> try spread
-        <|> parseSelectionField
+ where
+  parseSelection =
+    label "Selection"
+      $   try inlineFragment
+      <|> try spread
+      <|> parseSelectionField
 
 -- Fields: https://graphql.github.io/graphql-spec/June2018/#sec-Language.Fields
 --
@@ -45,27 +67,37 @@
 -- Alias(opt) Name Arguments(opt) Directives(opt) SelectionSet(opt)
 --
 parseSelectionField :: Parser (Text, RawSelection)
-parseSelectionField =
-  label "SelectionField" $ do
-    position <- getLocation
-    aliasName  <- parseAlias
-    name <- parseName
-    arguments <- maybeArguments
-    -- TODO: handle Directives
-    _directives <- optionalDirectives
-    value <- selSet aliasName arguments <|> buildField aliasName arguments position
-    return (name, value)
-  where
+parseSelectionField = label "SelectionField" $ do
+  position    <- getLocation
+  aliasName   <- parseAlias
+  name        <- parseName
+  arguments   <- maybeArguments
+  -- TODO: handle Directives
+  _directives <- optionalDirectives
+  value       <-
+    selSet aliasName arguments <|> buildField aliasName arguments position
+  return (name, value)
+ where
     ----------------------------------------
-    buildField selectionAlias selectionArguments selectionPosition =
-       pure (RawSelectionField $ Selection { selectionAlias , selectionArguments,  selectionRec = (), selectionPosition})
-    -----------------------------------------
-    selSet :: Maybe Text -> RawArguments -> Parser RawSelection
-    selSet selectionAlias selectionArguments =
-      label "body" $ do
-        selectionPosition <- getLocation
-        selectionRec <- parseSelectionSet
-        return (RawSelectionSet $ Selection {selectionAlias , selectionArguments, selectionRec, selectionPosition})
+  buildField selectionAlias selectionArguments selectionPosition = pure
+    (RawSelectionField $ Selection { selectionAlias
+                                   , selectionArguments
+                                   , selectionRec       = ()
+                                   , selectionPosition
+                                   }
+    )
+  -----------------------------------------
+  selSet :: Maybe Text -> RawArguments -> Parser RawSelection
+  selSet selectionAlias selectionArguments = label "body" $ do
+    selectionPosition <- getLocation
+    selectionRec      <- parseSelectionSet
+    return
+      (RawSelectionSet $ Selection { selectionAlias
+                                   , selectionArguments
+                                   , selectionRec
+                                   , selectionPosition
+                                   }
+      )
 
 
 --
@@ -78,13 +110,12 @@
 --    ...FragmentName Directives(opt)
 --
 spread :: Parser (Text, RawSelection)
-spread =
-  label "FragmentSpread" $ do
-    referencePosition <- spreadLiteral
-    referenceName <- token
-    -- TODO: handle Directives
-    _directives <- optionalDirectives
-    return (referenceName, Spread $ Reference {referenceName, referencePosition})
+spread = label "FragmentSpread" $ do
+  refPosition <- spreadLiteral
+  refName     <- token
+  -- TODO: handle Directives
+  _directives <- optionalDirectives
+  return (refName, Spread $ Ref { refName, refPosition })
 
 -- FragmentDefinition : https://graphql.github.io/graphql-spec/June2018/#FragmentDefinition
 --
@@ -92,16 +123,15 @@
 --   fragment FragmentName TypeCondition Directives(opt) SelectionSet
 --
 parseFragmentDefinition :: Parser (Text, Fragment)
-parseFragmentDefinition =
-  label "FragmentDefinition" $ do
-    keyword "fragment"
-    fragmentPosition <- getLocation
-    name <- parseName
-    fragmentType <- parseTypeCondition
-    -- TODO: handle Directives
-    _directives <- optionalDirectives
-    fragmentSelection <- parseSelectionSet
-    pure (name, Fragment {fragmentType, fragmentSelection, fragmentPosition})
+parseFragmentDefinition = label "FragmentDefinition" $ do
+  keyword "fragment"
+  fragmentPosition  <- getLocation
+  name              <- parseName
+  fragmentType      <- parseTypeCondition
+  -- TODO: handle Directives
+  _directives       <- optionalDirectives
+  fragmentSelection <- parseSelectionSet
+  pure (name, Fragment { fragmentType, fragmentSelection, fragmentPosition })
 
 -- Inline Fragments : https://graphql.github.io/graphql-spec/June2018/#sec-Inline-Fragments
 --
@@ -109,12 +139,15 @@
 --  ... TypeCondition(opt) Directives(opt) SelectionSet
 --
 inlineFragment :: Parser (Text, RawSelection)
-inlineFragment =
-  label "InlineFragment" $ do
-    fragmentPosition <- spreadLiteral
-    -- TODO: optional
-    fragmentType <- parseTypeCondition
-    -- TODO: handle Directives
-    _directives <- optionalDirectives
-    fragmentSelection <- parseSelectionSet
-    pure ("INLINE_FRAGMENT", InlineFragment $ Fragment {fragmentType, fragmentSelection, fragmentPosition})
+inlineFragment = label "InlineFragment" $ do
+  fragmentPosition  <- spreadLiteral
+  -- TODO: optional
+  fragmentType      <- parseTypeCondition
+  -- TODO: handle Directives
+  _directives       <- optionalDirectives
+  fragmentSelection <- parseSelectionSet
+  pure
+    ( "INLINE_FRAGMENT"
+    , InlineFragment
+      $ Fragment { fragmentType, fragmentSelection, fragmentPosition }
+    )
diff --git a/src/Data/Morpheus/Rendering/Haskell/Render.hs b/src/Data/Morpheus/Rendering/Haskell/Render.hs
deleted file mode 100644
--- a/src/Data/Morpheus/Rendering/Haskell/Render.hs
+++ /dev/null
@@ -1,87 +0,0 @@
-{-# LANGUAGE FlexibleContexts  #-}
-{-# LANGUAGE NamedFieldPuns    #-}
-{-# LANGUAGE OverloadedStrings #-}
-
-module Data.Morpheus.Rendering.Haskell.Render
-  ( renderHaskellDocument
-  ) where
-
-import           Data.ByteString.Lazy.Char8             (ByteString)
-import           Data.Semigroup                         ((<>))
-import           Data.Text                              (Text, intercalate, pack)
-import qualified Data.Text                              as T (concat)
-import qualified Data.Text.Lazy                         as LT (fromStrict)
-import           Data.Text.Lazy.Encoding                (encodeUtf8)
-
--- MORPHEUS
-import           Data.Morpheus.Rendering.Haskell.Terms  (Context (..), renderExtension)
-import           Data.Morpheus.Rendering.Haskell.Types  (renderType)
-import           Data.Morpheus.Rendering.Haskell.Values (Scope (..), renderResolver, renderRootResolver)
-import           Data.Morpheus.Types.Internal.Data      (DataTypeLib (..), allDataTypes)
-
-renderHaskellDocument :: String -> DataTypeLib -> ByteString
-renderHaskellDocument modName lib =
-  encodeText $
-  renderLanguageExtensions context <> renderExports context <>
-  renderImports context <>
-  onSub renderApiEvents "" <>
-  renderRootResolver context lib <>
-  types
-  where
-    encodeText = encodeUtf8 . LT.fromStrict
-    onSub onS els =
-      case subscription lib of
-        Nothing -> els
-        _       -> onS
-    renderApiEvents =
-      "data Channel = Channel -- ChannelA | ChannelB" <> "\n\n" <>
-      "data Content = Content -- ContentA Int | ContentB String" <>
-      "\n\n"
-    types = intercalate "\n\n" $ map renderFullType (allDataTypes lib)
-      where
-        renderFullType x = renderType cont x <> "\n\n" <> renderResolver cont x
-          where
-            cont = context {scope = getScope $ fst x}
-            getScope "Mutation"     = Mutation
-            getScope "Subscription" = Subscription
-            getScope _              = Query
-    context =
-      Context
-        { moduleName = pack modName
-        , imports =
-            [ ("GHC.Generics", ["Generic"])
-            , ( "Data.Morpheus.Kind"
-              , ["SCALAR", "ENUM", "INPUT_OBJECT", "OBJECT", "UNION"])
-            , ( "Data.Morpheus.Types"
-              , [ "GQLRootResolver(..)"
-                , "toMutResolver"
-                , "IORes"
-                , "IOMutRes"
-                , "IOSubRes"
-                , "Event(..)"
-                , "SubRootRes"
-                , "GQLType(..)"
-                , "GQLScalar(..)"
-                , "ScalarValue(..)"
-                ])
-            , ("Data.Text", ["Text"])
-            ]
-        , extensions = ["OverloadedStrings", "DeriveGeneric", "TypeFamilies"]
-        , scope = Query
-        , pubSub = onSub ("Channel", "Content") ("()", "()")
-        }
-
-renderLanguageExtensions :: Context -> Text
-renderLanguageExtensions Context {extensions} =
-  T.concat (map renderExtension extensions) <> "\n"
-
-renderExports :: Context -> Text
-renderExports Context {moduleName} =
-  "-- generated by 'Morpheus' CLI\n" <> "module " <> moduleName <>
-  " (rootResolver) where\n\n"
-
-renderImports :: Context -> Text
-renderImports Context {imports} = T.concat (map renderImport imports) <> "\n"
-  where
-    renderImport (src, list) =
-      "import  " <> src <> "  (" <> intercalate ", " list <> ")\n"
diff --git a/src/Data/Morpheus/Rendering/Haskell/Terms.hs b/src/Data/Morpheus/Rendering/Haskell/Terms.hs
deleted file mode 100644
--- a/src/Data/Morpheus/Rendering/Haskell/Terms.hs
+++ /dev/null
@@ -1,85 +0,0 @@
-{-# LANGUAGE OverloadedStrings #-}
-
-module Data.Morpheus.Rendering.Haskell.Terms
-  ( indent
-  , renderReturn
-  , renderData
-  , renderCon
-  , renderMaybe
-  , renderList
-  , renderTuple
-  , renderAssignment
-  , renderExtension
-  , renderWrapped
-  , renderSet
-  , renderUnionCon
-  , renderEqual
-  , Scope(..)
-  , Context(..)
-  ) where
-
-import           Data.Semigroup                    ((<>))
-import           Data.Text                         (Text, intercalate, toUpper)
-
--- MORPHEUS
-import           Data.Morpheus.Types.Internal.Data (WrapperD (..))
-
-indent :: Text
-indent = "  "
-
-renderEqual :: Text -> Text -> Text
-renderEqual key value = key <> " = " <> value
-
-renderReturn :: Text
-renderReturn = "return "
-
-renderData :: Text -> Text
-renderData name = "data " <> name <> " = "
-
-renderCon :: Text -> Text
-renderCon name = name <> " "
-
-renderMaybe :: Text -> Text
-renderMaybe typeName = "Maybe " <> typeName
-
-renderList :: Text -> Text
-renderList typeName = "[" <> typeName <> "]"
-
-renderTuple :: Text -> Text
-renderTuple typeName = "(" <> typeName <> ")"
-
-renderSet :: [Text] -> Text
-renderSet fields = bracket "{ " <> intercalate ("\n  ," <> indent) fields <> bracket "}\n"
-  where
-    bracket x = "\n    " <> x
-
-renderAssignment :: Text -> Text -> Text
-renderAssignment key value = key <> " :: " <> value
-
-renderExtension :: Text -> Text
-renderExtension name = "{-# LANGUAGE " <> name <> " #-}\n"
-
-renderWrapped :: [WrapperD] -> Text -> Text
-renderWrapped (ListD:xs)  = renderList . renderWrapped xs
-renderWrapped (MaybeD:xs) = renderMaybe . renderWrapped xs
-renderWrapped []          = strToText
-
-strToText :: Text -> Text
-strToText "String" = "Text"
-strToText x        = x
-
-renderUnionCon :: Text -> Text -> Text
-renderUnionCon typeName conName = renderCon (typeName <> "_" <> toUpper conName)
-
-data Scope
-  = Mutation
-  | Subscription
-  | Query
-
-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
deleted file mode 100644
--- a/src/Data/Morpheus/Rendering/Haskell/Types.hs
+++ /dev/null
@@ -1,93 +0,0 @@
-{-# LANGUAGE NamedFieldPuns    #-}
-{-# LANGUAGE OverloadedStrings #-}
-
-module Data.Morpheus.Rendering.Haskell.Types
-  ( renderType
-  ) where
-
-import           Data.Maybe                            (catMaybes)
-import           Data.Semigroup                        ((<>))
-import           Data.Text                             (Text, intercalate, pack, toUpper)
-import qualified Data.Text                             as T (head, tail)
-
--- MORPHEUS
-import           Data.Morpheus.Rendering.Haskell.Terms (Context (..), Scope (..), indent, renderAssignment, renderCon,
-                                                        renderData, renderSet, renderTuple, renderUnionCon,
-                                                        renderWrapped)
-import           Data.Morpheus.Types.Internal.Data     (DataArgument, DataField (..), DataType (..), DataTyCon (..),
-                                                        TypeAlias (..), isNullable)
-
-renderType :: Context -> (Text, DataType) -> Text
-renderType context (name, dataType) = typeIntro <> renderData name <> renderT dataType
-  where
-    renderT (DataScalar _) = renderCon name <> "Int Int" <> defineTypeClass "SCALAR" <> renderGQLScalar name
-    renderT (DataEnum DataTyCon {typeData}) = unionType typeData <> defineTypeClass "ENUM"
-    renderT (DataUnion DataTyCon {typeData}) = renderUnion name typeData <> defineTypeClass "UNION"
-    renderT (DataInputObject DataTyCon {typeData}) =
-      renderCon name <> renderObject renderInputField typeData <> defineTypeClass "INPUT_OBJECT"
-    renderT (DataInputUnion _) = "\n -- Error: Input Union Not Supported"
-    renderT (DataObject 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"
-    ----------------------------------------------------------------------------------------------------------
-
-renderTypeInstanceHead :: Text -> Text -> Text
-renderTypeInstanceHead className name = "instance " <> className <> " " <> name <> " where\n"
-
-renderGQLScalar :: Text -> Text
-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 typeName = unionType . map renderElem
-  where
-    renderElem DataField {fieldType = TypeAlias {aliasTyCon}} = renderUnionCon typeName aliasTyCon <> aliasTyCon
-
-unionType :: [Text] -> Text
-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
-  where
-    renderMainType = renderSet fields <> " deriving (Generic)"
-    (fields, types) = unzip (map f list)
-
-renderInputField :: (Text, DataField) -> (Text, Maybe Text)
-renderInputField (key, DataField {fieldType = TypeAlias {aliasTyCon, aliasWrappers}}) =
-  (key `renderAssignment` renderWrapped aliasWrappers aliasTyCon, Nothing)
-
-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 aliasWrappers, argTypes)
-  where
-    renderMonad Subscription = "IOSubRes " <> channel <> " " <> content <> " "
-    renderMonad Mutation =
-      case channel of
-        "()" -> "IORes "
-        _    -> "IOMutRes " <> channel <> " " <> content <> " "
-    renderMonad _ = "IORes "
-    -----------------------------------------------------------------
-    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))
-      where
-        fieldArgTypeName = "Arg" <> camelCase key
-        camelCase :: Text -> Text
-        camelCase ""   = ""
-        camelCase text = toUpper (pack [T.head text]) <> T.tail text
diff --git a/src/Data/Morpheus/Rendering/Haskell/Values.hs b/src/Data/Morpheus/Rendering/Haskell/Values.hs
deleted file mode 100644
--- a/src/Data/Morpheus/Rendering/Haskell/Values.hs
+++ /dev/null
@@ -1,84 +0,0 @@
-{-# LANGUAGE NamedFieldPuns    #-}
-{-# LANGUAGE OverloadedStrings #-}
-
-module Data.Morpheus.Rendering.Haskell.Values
-  ( renderRootResolver
-  , renderResolver
-  , Scope(..)
-  ) where
-
-import           Data.Semigroup                        ((<>))
-import           Data.Text                             (Text)
-
--- MORPHEUS
-import           Data.Morpheus.Rendering.Haskell.Terms (Context (..), Scope (..), renderAssignment, renderCon,
-                                                        renderEqual, renderReturn, renderSet, renderUnionCon)
-import           Data.Morpheus.Types.Internal.Data     (DataField (..), DataType (..), DataTyCon (..),
-                                                        DataTypeLib (..), TypeAlias (..), WrapperD (..))
-
-renderRootResolver :: Context -> DataTypeLib -> Text
-renderRootResolver _ DataTypeLib {mutation, subscription} = renderSignature <> renderBody <> "\n\n"
-  where
-    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 <> " ()"
-        ----------------------
-        maybeOperator (Just (name, _)) = name
-        maybeOperator Nothing          = "()"
-    renderBody = "rootResolver =\n  GQLRootResolver" <> renderResObject fields
-      where
-        fields =
-          [ ("queryResolver", "resolveQuery")
-          , ("mutationResolver", maybeRes mutation)
-          , ("subscriptionResolver", maybeRes subscription)
-          ]
-      ---------------------------------------------
-        maybeRes (Just (name, _)) = "resolve" <> name
-        maybeRes Nothing          = "return ()"
-
-renderResolver :: Context -> (Text, DataType) -> Text
-renderResolver Context {scope, pubSub = (channel, content)} (name, dataType) = renderSig dataType
-  where
-    renderSig DataScalar {} = defFunc <> renderReturn <> "$ " <> renderCon name <> "0 0"
-    renderSig (DataEnum DataTyCon {typeData}) = defFunc <> renderReturn <> renderCon (head typeData)
-    renderSig (DataUnion DataTyCon {typeData}) = defFunc <> renderUnionCon name typeCon <> " <$> " <> "resolve" <> typeCon
-      where
-        typeCon = aliasTyCon $ fieldType $ head typeData
-    renderSig (DataObject DataTyCon {typeData}) = defFunc <> renderReturn <> renderCon name <> renderObjFields
-      where
-        renderObjFields = renderResObject (map renderFieldRes typeData)
-        renderFieldRes (key, DataField {fieldType = TypeAlias {aliasWrappers, aliasTyCon}}) =
-          (key, "const " <> withScope scope (renderValue aliasWrappers aliasTyCon))
-          where
-            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 Mutation x =
-              case (channel, content) of
-                ("()", "()") -> 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"
-    ---------------------------------------------------------------------------------
-    renderMonad "Mutation"     = "IOMutRes " <> channel <> " " <> content <> " Mutation"
-    renderMonad "Subscription" = "SubRootRes IO " <> channel <> " Subscription"
-    renderMonad tName          = "IORes " <> tName
-    ----------------------------------------------------------------------------------------------------------
-    renderFunc = "resolve" <> name <> " = "
-    ---------------------------------------
-
-renderResObject :: [(Text, Text)] -> Text
-renderResObject = renderSet . map renderEntry
-  where
-    renderEntry (key, value) = renderEqual key value
diff --git a/src/Data/Morpheus/Rendering/RenderGQL.hs b/src/Data/Morpheus/Rendering/RenderGQL.hs
--- a/src/Data/Morpheus/Rendering/RenderGQL.hs
+++ b/src/Data/Morpheus/Rendering/RenderGQL.hs
@@ -2,34 +2,51 @@
 {-# LANGUAGE FlexibleInstances    #-}
 {-# LANGUAGE NamedFieldPuns       #-}
 {-# LANGUAGE OverloadedStrings    #-}
-{-# LANGUAGE TypeSynonymInstances #-}
 
 module Data.Morpheus.Rendering.RenderGQL
   ( RenderGQL(..)
   , renderGraphQLDocument
-  ) where
+  )
+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)
+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 (..), DataTyCon (..), DataType (..), DataTypeLib,
-                                                     DataTypeWrapper (..), Key, TypeAlias (..), WrapperD (..),
-                                                     allDataTypes, isDefaultTypeName, toGQLWrapper)
-import           Data.Morpheus.Types.Internal.Value (convertToJSONName)
+import           Data.Morpheus.Types.Internal.AST
+                                                ( DataField(..)
+                                                , DataTyCon(..)
+                                                , DataType(..)
+                                                , DataTypeLib
+                                                , DataTypeWrapper(..)
+                                                , Key
+                                                , TypeAlias(..)
+                                                , TypeWrapper(..)
+                                                , allDataTypes
+                                                , createInputUnionFields
+                                                , fieldVisibility
+                                                , isDefaultTypeName
+                                                , toGQLWrapper
+                                                , DataEnumValue(..)
+                                                , convertToJSONName )
 
+
 renderGraphQLDocument :: DataTypeLib -> ByteString
-renderGraphQLDocument lib = encodeUtf8 $ LT.fromStrict $ intercalate "\n\n" $ map render visibleTypes
-  where
-    visibleTypes = filter (not . isDefaultTypeName . fst) (allDataTypes lib)
+renderGraphQLDocument lib =
+  encodeUtf8 $ LT.fromStrict $ intercalate "\n\n" $ map render visibleTypes
+ where
+  visibleTypes = filter (not . isDefaultTypeName . fst) (allDataTypes lib)
 
 class RenderGQL a where
   render :: a -> Key
-  renderWrapped :: a -> [WrapperD] -> Key
-  default renderWrapped :: a -> [WrapperD] -> Key
+  renderWrapped :: a -> [TypeWrapper] -> Key
+  default renderWrapped :: a -> [TypeWrapper] -> Key
   renderWrapped x wrappers = showGQLWrapper (toGQLWrapper wrappers)
     where
       showGQLWrapper []               = render x
@@ -40,44 +57,56 @@
   render = id
 
 instance RenderGQL TypeAlias where
-  render TypeAlias {aliasTyCon, aliasWrappers} = renderWrapped aliasTyCon aliasWrappers
+  render TypeAlias { aliasTyCon, aliasWrappers } =
+    renderWrapped aliasTyCon aliasWrappers
 
 instance RenderGQL DataType where
-  render (DataScalar x)      = typeName x
-  render (DataEnum x)        = typeName x
-  render (DataUnion x)       = typeName x
+  render (DataScalar      x) = typeName x
+  render (DataEnum        x) = typeName x
+  render (DataUnion       x) = typeName x
   render (DataInputObject x) = typeName x
-  render (DataInputUnion x)  = typeName x
-  render ( DataObject x)     = typeName x
+  render (DataInputUnion  x) = typeName x
+  render (DataObject      x) = typeName x
 
+instance RenderGQL DataEnumValue where
+  render DataEnumValue { enumName } = enumName
+
 instance RenderGQL (Key, DataType) where
-  render (name, DataScalar {}) = "scalar " <> name
-  render (name, DataEnum DataTyCon {typeData}) = "enum " <> name <> renderObject id typeData
-  render (name, DataUnion DataTyCon {typeData}) =
-    "union " <> name <> " =\n    " <> intercalate ("\n" <> renderIndent <> "| ") (map (render . fieldType) typeData)
-  render (name, DataInputObject DataTyCon {typeData}) = "input " <> name <> render typeData
-  render (name, DataInputUnion DataTyCon {typeData}) = "input " <> name <> render (mapKeys typeData)
-  render (name, DataObject DataTyCon {typeData}) = "type " <> name <> render typeData
+  render (name, DataScalar{}) = "scalar " <> name
+  render (name, DataEnum DataTyCon { typeData }) =
+    "enum " <> name <> renderObject render typeData
+  render (name, DataUnion DataTyCon { typeData }) =
+    "union "
+      <> name
+      <> " =\n    "
+      <> intercalate ("\n" <> renderIndent <> "| ") typeData
+  render (name, DataInputObject DataTyCon { typeData }) =
+    "input " <> name <> render typeData
+  render (name, DataInputUnion DataTyCon { typeData }) =
+    "input " <> name <> render fields
+    where fields = createInputUnionFields name typeData
+  render (name, DataObject DataTyCon { typeData }) =
+    "type " <> name <> render typeData
 
-mapKeys :: [DataField] -> [(Text, DataField)]
-mapKeys = map (\x -> (fieldName x, x))
 
+
 -- OBJECT
 instance RenderGQL [(Text, DataField)] where
   render = renderObject renderField . ignoreHidden
-    where
-      renderField :: (Text, DataField) -> Text
-      renderField (key, DataField {fieldType, fieldArgs}) =
-        convertToJSONName key <> renderArgs fieldArgs <> ": " <> render fieldType
-        where
-          renderArgs []   = ""
-          renderArgs list = "(" <> intercalate ", " (map renderField list) <> ")"
-      -----------------------------------------------------------
-      ignoreHidden :: [(Text, DataField)] -> [(Text, DataField)]
-      ignoreHidden = filter (not . fieldHidden . snd)
+   where
+    renderField :: (Text, DataField) -> Text
+    renderField (key, DataField { fieldType, fieldArgs }) =
+      convertToJSONName key <> renderArgs fieldArgs <> ": " <> render fieldType
+     where
+      renderArgs []   = ""
+      renderArgs list = "(" <> intercalate ", " (map renderField list) <> ")"
+    -----------------------------------------------------------
+    ignoreHidden :: [(Text, DataField)] -> [(Text, DataField)]
+    ignoreHidden = filter fieldVisibility
 
 renderIndent :: Text
 renderIndent = "  "
 
 renderObject :: (a -> Text) -> [a] -> Text
-renderObject f list = " { \n  " <> intercalate ("\n" <> renderIndent) (map f list) <> "\n}"
+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
--- a/src/Data/Morpheus/Rendering/RenderIntrospection.hs
+++ b/src/Data/Morpheus/Rendering/RenderIntrospection.hs
@@ -2,24 +2,43 @@
 {-# LANGUAGE NamedFieldPuns        #-}
 {-# LANGUAGE OverloadedStrings     #-}
 {-# LANGUAGE TypeOperators         #-}
+{-# LANGUAGE FlexibleContexts      #-}
 
 module Data.Morpheus.Rendering.RenderIntrospection
   ( render
   , createObjectType
-  ) where
+  )
+where
 
-import           Control.Monad.Fail                 (MonadFail)
-import           Data.Semigroup                     ((<>))
-import           Data.Text                          (Text, unpack)
+import           Data.Semigroup                 ( (<>) )
+import           Data.Text                      ( Text )
+import           Data.Maybe                     ( isJust )
 
-import           Data.Morpheus.Schema.Schema
 
 -- Morpheus
-import           Data.Morpheus.Schema.TypeKind      (TypeKind (..))
-import           Data.Morpheus.Types.Internal.Data  (DataField (..), DataObject, DataTyCon (..), DataType (..),
-                                                     DataTypeKind (..), DataTypeLib, DataTypeWrapper (..), DataUnion,
-                                                     TypeAlias (..), kindOf, lookupDataType, toGQLWrapper)
-import           Data.Morpheus.Types.Internal.Value (convertToJSONName)
+import           Data.Morpheus.Schema.Schema
+import           Data.Morpheus.Schema.TypeKind  ( TypeKind(..) )
+import           Data.Morpheus.Types.Internal.AST
+                                                ( DataField(..)
+                                                , DataTyCon(..)
+                                                , DataType(..)
+                                                , DataTypeKind(..)
+                                                , DataTypeLib
+                                                , DataTypeWrapper(..)
+                                                , DataUnion
+                                                , Meta(..)
+                                                , TypeAlias(..)
+                                                , createInputUnionFields
+                                                , fieldVisibility
+                                                , kindOf
+                                                , lookupDataType
+                                                , toGQLWrapper
+                                                , DataEnumValue(..)
+                                                , lookupDeprecated
+                                                , lookupDeprecatedReason
+                                                , convertToJSONName )
+import           Data.Morpheus.Types.Internal.Resolving
+                                                ( Failure(..) )
 
 constRes :: Applicative m => a -> b -> m a
 constRes = const . pure
@@ -27,27 +46,54 @@
 type Result m a = DataTypeLib -> m a
 
 class RenderSchema a b where
-  render :: (Monad m, MonadFail m) => (Text, a) -> DataTypeLib -> m (b m)
+  render :: (Monad m, Failure Text m) => (Text, a) -> DataTypeLib -> m (b m)
 
 instance RenderSchema DataType S__Type where
-  render (key, DataScalar DataTyCon {typeDescription})  =
-    constRes $ createLeafType SCALAR key typeDescription Nothing
-  render (key, DataEnum DataTyCon {typeDescription, typeData})  =
-    constRes $ createLeafType ENUM key typeDescription (Just $ map createEnumValue typeData)
-  render (name, DataInputObject iObject) = renderInputObject (name, iObject)
+  render (key, DataScalar DataTyCon { typeMeta }) =
+    constRes $ createLeafType SCALAR key typeMeta Nothing
+  render (key, DataEnum DataTyCon { typeMeta, typeData }) =
+    constRes
+      $ createLeafType ENUM key typeMeta (Just $ map createEnumValue typeData)
+  render (name, DataInputObject DataTyCon { typeData, typeMeta }) =
+    renderInputObject
+   where
+    renderInputObject lib = do
+      fields <- traverse (`renderinputValue` lib) typeData
+      pure $ createInputObject name typeMeta fields
   render (name, DataObject 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, DataUnion union') = const $ pure $ typeFromUnion (name, union')
+   where
+    typeFromObject (key, DataTyCon { typeData, typeMeta }) lib =
+      createObjectType key (typeMeta >>= metaDescription)
+        <$> (Just <$> traverse (`render` lib) (filter fieldVisibility typeData))
+  render (name, DataUnion union) = constRes $ typeFromUnion (name, union)
   render (name, DataInputUnion inpUnion') = renderInputUnion (name, inpUnion')
 
+createEnumValue :: Monad m => DataEnumValue -> S__EnumValue m
+createEnumValue DataEnumValue { enumName, enumMeta } = S__EnumValue
+  { s__EnumValueName              = constRes enumName
+  , s__EnumValueDescription       = constRes (enumMeta >>= metaDescription)
+  , s__EnumValueIsDeprecated      = constRes (isJust deprecated)
+  , s__EnumValueDeprecationReason = constRes
+                                      (deprecated >>= lookupDeprecatedReason)
+  }
+  where deprecated = enumMeta >>= lookupDeprecated
+
 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
+  render (name, field@DataField { fieldType = TypeAlias { aliasTyCon }, fieldArgs, fieldMeta }) lib
+    = do
+      kind <- renderTypeKind <$> lookupKind aliasTyCon lib
+      args <- traverse (`renderinputValue` lib) fieldArgs
+      pure S__Field
+        { s__FieldName              = constRes (convertToJSONName name)
+        , s__FieldDescription       = constRes (fieldMeta >>= metaDescription)
+        , s__FieldArgs              = constRes args
+        , s__FieldType'             =
+          constRes (wrap field $ createType kind aliasTyCon Nothing $ Just [])
+        , s__FieldIsDeprecated      = constRes (isJust deprecated)
+        , s__FieldDeprecationReason = constRes
+                                        (deprecated >>= lookupDeprecatedReason)
+        }
+    where deprecated = fieldMeta >>= lookupDeprecated
 
 renderTypeKind :: DataTypeKind -> TypeKind
 renderTypeKind KindScalar      = SCALAR
@@ -60,147 +106,140 @@
 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)
+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, MonadFail 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)
+lookupKind :: (Monad m, Failure Text m) => Text -> Result m DataTypeKind
+lookupKind name lib = case lookupDataType name lib of
+  Nothing    -> failure $ "Kind Not Found: " <> name
+  Just value -> pure (kindOf value)
 
-inputValueFromArg :: (Monad m,MonadFail m) => (Text, DataField) -> Result m (S__InputValue m)
-inputValueFromArg (key, input) = fmap (createInputValueWith key) . createInputObjectType input
+renderinputValue
+  :: (Monad m, Failure Text m)
+  => (Text, DataField)
+  -> Result m (S__InputValue m)
+renderinputValue (key, input) =
+  fmap (createInputValueWith key (fieldMeta input))
+    . createInputObjectType input
 
-createInputObjectType :: (Monad m, MonadFail 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 []
+createInputObjectType
+  :: (Monad m, Failure Text 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, MonadFail 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, MonadFail 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
+renderInputUnion
+  :: (Monad m, Failure Text m) => (Text, DataUnion) -> Result m (S__Type m)
+renderInputUnion (key, DataTyCon { typeData, typeMeta }) lib =
+  createInputObject key typeMeta
+    <$> traverse createField (createInputUnionFields key typeData)
+ where
+  createField (name, field) =
+    createInputValueWith name Nothing <$> 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
-    }
+createLeafType
+  :: Monad m
+  => TypeKind
+  -> Text
+  -> Maybe Meta
+  -> Maybe [S__EnumValue m]
+  -> S__Type m
+createLeafType kind name meta enums = S__Type
+  { s__TypeKind          = constRes kind
+  , s__TypeName          = constRes $ Just name
+  , s__TypeDescription   = constRes (meta >>= metaDescription)
+  , 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
-    }
+typeFromUnion (name, DataTyCon { typeData, typeMeta }) = S__Type
+  { s__TypeKind          = constRes UNION
+  , s__TypeName          = constRes $ Just name
+  , s__TypeDescription   = constRes (typeMeta >>= metaDescription)
+  , s__TypeFields        = constRes Nothing
+  , s__TypeOfType        = constRes Nothing
+  , s__TypeInterfaces    = constRes Nothing
+  , s__TypePossibleTypes =
+    constRes $ Just (map (\x -> createObjectType 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
-    }
+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
-    }
+createInputObject
+  :: Monad m => Text -> Maybe Meta -> [S__InputValue m] -> S__Type m
+createInputObject name meta fields = S__Type
+  { s__TypeKind          = constRes INPUT_OBJECT
+  , s__TypeName          = constRes $ Just name
+  , s__TypeDescription   = constRes (meta >>= metaDescription)
+  , 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
-    }
+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 (convertToJSONName name)
-    , s__InputValueDescription = constRes Nothing
-    , s__InputValueType' = constRes ivType
-    , s__InputValueDefaultValue = constRes Nothing
-    }
+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
+                                  }
 
-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
-    }
+createInputValueWith
+  :: Monad m => Text -> Maybe Meta -> S__Type m -> S__InputValue m
+createInputValueWith name meta ivType = S__InputValue
+  { s__InputValueName         = constRes (convertToJSONName name)
+  , s__InputValueDescription  = constRes (meta >>= metaDescription)
+  , s__InputValueType'        = constRes ivType
+  , s__InputValueDefaultValue = constRes Nothing
+  }
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
@@ -8,8 +8,9 @@
 {-# LANGUAGE TemplateHaskell       #-}
 {-# LANGUAGE TypeFamilies          #-}
 {-# LANGUAGE TypeOperators         #-}
-{-# LANGUAGE TypeSynonymInstances , FlexibleContexts  #-}
+{-# LANGUAGE FlexibleContexts      #-}
 
+
 module Data.Morpheus.Schema.Schema
   ( Root(..)
   , Root__typeArgs(..)
@@ -18,13 +19,15 @@
   , S__Field(..)
   , S__EnumValue(..)
   , S__InputValue(..)
-  ) where
+  )
+where
 
-import           Data.Text                                (Text)
+import           Data.Text                      ( Text )
 
 -- MORPHEUS
-import           Data.Morpheus.Execution.Document.Compile (gqlDocumentNamespace)
-import           Data.Morpheus.Schema.TypeKind            (TypeKind)
+import           Data.Morpheus.Execution.Document.Compile
+                                                ( gqlDocumentNamespace )
+import           Data.Morpheus.Schema.TypeKind  ( TypeKind )
 
 type S__TypeKind = TypeKind
 
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
@@ -7,66 +7,93 @@
   ( hiddenRootFields
   , defaultTypes
   , schemaAPI
-  ) where
+  )
+where
 
 import           Data.Proxy
-import           Data.Text                                     (Text)
+import           Data.Text                      ( Text )
 
 -- MORPHEUS
-import           Data.Morpheus.Execution.Internal.GraphScanner (resolveUpdates)
-import           Data.Morpheus.Execution.Server.Introspect     (ObjectFields (..), TypeUpdater, introspect)
-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 (..), QUERY,
-                                                                allDataTypes)
-import           Data.Morpheus.Types.Internal.Resolver         (Resolver (..))
+import           Data.Morpheus.Execution.Server.Introspect
+                                                ( ObjectFields(..)
+                                                , TypeUpdater
+                                                , introspect
+                                                )
+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.AST
+                                                ( DataField(..)
+                                                , DataObject
+                                                , DataTypeLib(..)
+                                                , QUERY
+                                                , allDataTypes
+                                                , lookupDataType
+                                                )
+import           Data.Morpheus.Types.Internal.Resolving
+                                                ( Resolver(..)
+                                                , resolveUpdates
+                                                )
 
-convertTypes :: Monad m => DataTypeLib -> Resolver QUERY m e [S__Type (Resolver QUERY m e )]
+
+convertTypes
+  :: Monad m => DataTypeLib -> Resolver QUERY e m [S__Type (Resolver QUERY e m)]
 convertTypes lib = traverse (`render` lib) (allDataTypes lib)
 
-buildSchemaLinkType :: Monad m => (Text, DataObject) -> S__Type (Resolver QUERY m e )
+buildSchemaLinkType
+  :: Monad m => (Text, DataObject) -> S__Type (Resolver QUERY e m)
 buildSchemaLinkType (key', _) = createObjectType key' Nothing $ Just []
 
-findType :: Monad m => Text -> DataTypeLib -> Resolver QUERY m e (Maybe (S__Type (Resolver QUERY m e )))
-findType name lib = renderT (lookup name (allDataTypes lib))
-  where
-    renderT (Just datatype) = Just <$> render (name,datatype) lib
-    renderT Nothing         = pure Nothing
-
-initSchema :: Monad m => DataTypeLib -> Resolver QUERY m e (S__Schema (Resolver QUERY m e ))
-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 []
-      }
+findType
+  :: Monad m
+  => Text
+  -> DataTypeLib
+  -> Resolver QUERY e m (Maybe (S__Type (Resolver QUERY e m)))
+findType name lib = renderT (lookupDataType name lib)
+ where
+  renderT (Just datatype) = Just <$> render (name, datatype) lib
+  renderT Nothing         = pure Nothing
 
-hideFields :: (Text, DataField) -> (Text, DataField)
-hideFields (key', field) = (key', field {fieldHidden = True})
+initSchema
+  :: Monad m
+  => DataTypeLib
+  -> Resolver QUERY e m (S__Schema (Resolver QUERY e 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 []
+  }
 
 hiddenRootFields :: [(Text, DataField)]
-hiddenRootFields = map hideFields $ fst $ objectFields (Proxy :: Proxy (CUSTOM (Root Maybe))) (Proxy @(Root Maybe))
+hiddenRootFields = fst
+  $ objectFields (Proxy :: Proxy (CUSTOM (Root Maybe))) (Proxy @(Root Maybe))
 
 defaultTypes :: TypeUpdater
-defaultTypes =
-  flip
-    resolveUpdates
-    [ introspect (Proxy @Bool)
-    , introspect (Proxy @Int)
-    , introspect (Proxy @Float)
-    , introspect (Proxy @Text)
-    , introspect (Proxy @ID)
-    , introspect (Proxy @(S__Schema Maybe))
-    ]
+defaultTypes = flip
+  resolveUpdates
+  [ introspect (Proxy @Bool)
+  , introspect (Proxy @Int)
+  , introspect (Proxy @Float)
+  , introspect (Proxy @Text)
+  , introspect (Proxy @ID)
+  , introspect (Proxy @(S__Schema Maybe))
+  ]
 
-schemaAPI :: Monad m => DataTypeLib -> Root (Resolver QUERY m e)
-schemaAPI lib = Root {root__type, root__schema}
-  where
-    root__type (Root__typeArgs name) = findType name lib
-    root__schema _ = initSchema lib
+schemaAPI :: Monad m => DataTypeLib -> Root (Resolver QUERY e m)
+schemaAPI lib = 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/TypeKind.hs b/src/Data/Morpheus/Schema/TypeKind.hs
--- a/src/Data/Morpheus/Schema/TypeKind.hs
+++ b/src/Data/Morpheus/Schema/TypeKind.hs
@@ -5,11 +5,12 @@
 
 module Data.Morpheus.Schema.TypeKind
   ( TypeKind(..)
-  ) where
+  )
+where
 
-import           Data.Aeson                  (FromJSON (..))
-import           Data.Morpheus.Kind          (ENUM)
-import           Data.Morpheus.Types.GQLType (GQLType (KIND, __typeName))
+import           Data.Aeson                     ( FromJSON(..) )
+import           Data.Morpheus.Kind             ( ENUM )
+import           Data.Morpheus.Types.GQLType    ( GQLType(KIND, __typeName) )
 import           GHC.Generics
 
 instance GQLType TypeKind where
diff --git a/src/Data/Morpheus/Server.hs b/src/Data/Morpheus/Server.hs
--- a/src/Data/Morpheus/Server.hs
+++ b/src/Data/Morpheus/Server.hs
@@ -9,67 +9,93 @@
   ( gqlSocketApp
   , initGQLState
   , GQLState
-  ) where
+  )
+where
 
-import           Control.Exception                                   (finally)
-import           Control.Monad                                       (forever)
-import           Data.Text                                           (Text)
-import           Network.WebSockets                                  (ServerApp, acceptRequestWith, forkPingThread,
-                                                                      pendingRequest, receiveData, sendTextData)
+import           Control.Exception              ( finally )
+import           Control.Monad                  ( forever )
+import           Data.Text                      ( Text )
+import           Network.WebSockets             ( ServerApp
+                                                , acceptRequestWith
+                                                , forkPingThread
+                                                , pendingRequest
+                                                , receiveData
+                                                , sendTextData
+                                                )
 
 -- MORPHEUS
-import           Data.Morpheus.Execution.Server.Resolve              (RootResCon, streamResolver)
-import           Data.Morpheus.Execution.Subscription.Apollo         (SubAction (..), acceptApolloSubProtocol,
-                                                                      apolloFormat, toApolloResponse)
-import           Data.Morpheus.Execution.Subscription.ClientRegister (GQLState, addClientSubscription, connectClient,
-                                                                      disconnectClient, initGQLState, publishUpdates,
-                                                                      removeClientSubscription)
-import           Data.Morpheus.Types.Internal.Resolver               (GQLRootResolver (..))
-import           Data.Morpheus.Types.Internal.Stream                 (GQLChannel (..), ResponseEvent (..),
-                                                                      ResponseStream, closeStream)
-import           Data.Morpheus.Types.Internal.WebSocket              (GQLClient (..))
-import           Data.Morpheus.Types.IO                              (GQLResponse (..))
+import           Data.Morpheus.Execution.Server.Resolve
+                                                ( RootResCon
+                                                , coreResolver
+                                                )
+import           Data.Morpheus.Execution.Subscription.Apollo
+                                                ( SubAction(..)
+                                                , acceptApolloSubProtocol
+                                                , apolloFormat
+                                                , toApolloResponse
+                                                )
+import           Data.Morpheus.Execution.Subscription.ClientRegister
+                                                ( GQLState
+                                                , addClientSubscription
+                                                , connectClient
+                                                , disconnectClient
+                                                , initGQLState
+                                                , publishUpdates
+                                                , removeClientSubscription
+                                                )
+import           Data.Morpheus.Types.Internal.Resolving
+                                                ( GQLRootResolver(..)
+                                                , GQLChannel(..)
+                                                , ResponseEvent(..)
+                                                , ResponseStream
+                                                , runResultT
+                                                , Result(..)
+                                                )
+import           Data.Morpheus.Types.Internal.WebSocket
+                                                ( GQLClient(..) )
+import           Data.Morpheus.Types.IO         ( GQLResponse(..) )
+import           Data.Morpheus.Types.Internal.AST
+                                                ( Value )
 
-handleSubscription :: (Eq (StreamChannel e), GQLChannel e) => GQLClient IO e
+handleSubscription
+  :: (Eq (StreamChannel e), GQLChannel e)
+  => GQLClient IO e
   -> GQLState IO e
   -> Text
-  -> ResponseStream IO e  GQLResponse
+  -> ResponseStream e IO Value
   -> IO ()
-handleSubscription GQLClient {clientConnection, clientID} state sessionId stream = do
-  (actions, response) <- closeStream stream
-  case response of
-    Data _ -> mapM_ execute actions
-    Errors _ ->
-      sendTextData clientConnection (toApolloResponse sessionId response)
-  where
-    execute (Publish pub)   = publishUpdates state pub
-    execute (Subscribe sub) = addClientSubscription clientID sub sessionId state
+handleSubscription GQLClient { clientConnection, clientID } state sessionId stream
+  = do
+    response <- runResultT stream
+    case response of
+      Success { events } -> mapM_ execute events
+      Failure errors     -> sendTextData
+        clientConnection
+        (toApolloResponse sessionId $ Errors errors)
+ where
+  execute (Publish   pub) = publishUpdates state pub
+  execute (Subscribe sub) = addClientSubscription clientID sub sessionId state
 
 -- | Wai WebSocket Server App for GraphQL subscriptions
-gqlSocketApp ::
-     RootResCon IO e  que mut sub
-  => GQLRootResolver IO e  que mut sub
+gqlSocketApp
+  :: RootResCon IO e que mut sub
+  => GQLRootResolver IO e que mut sub
   -> GQLState IO e
   -> ServerApp
 gqlSocketApp gqlRoot state pending = do
-  connection <-
-    acceptRequestWith pending $ acceptApolloSubProtocol (pendingRequest pending)
+  connection <- acceptRequestWith pending
+    $ acceptApolloSubProtocol (pendingRequest pending)
   forkPingThread connection 30
   client <- connectClient connection state
   finally (queryHandler client) (disconnectClient client state)
-  where
-    queryHandler client = forever handleRequest
-      where
-        handleRequest =
-          receiveData (clientConnection client) >>=
-          resolveMessage . apolloFormat
-          where
-            resolveMessage (SubError x) = print x
-            resolveMessage (AddSub sessionId request) =
-              handleSubscription
-                client
-                state
-                sessionId
-                (streamResolver gqlRoot request)
-            resolveMessage (RemoveSub sessionId) =
-              removeClientSubscription (clientID client) sessionId state
+ where
+  queryHandler client = forever handleRequest
+   where
+    handleRequest =
+      receiveData (clientConnection client) >>= resolveMessage . apolloFormat
+     where
+      resolveMessage (SubError x) = print x
+      resolveMessage (AddSub sessionId request) =
+        handleSubscription client state sessionId (coreResolver gqlRoot request)
+      resolveMessage (RemoveSub sessionId) =
+        removeClientSubscription (clientID client) sessionId state
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
@@ -1,11 +1,11 @@
-{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE DataKinds  #-}
 -- | GQL Types
 module Data.Morpheus.Types
   ( Event(..)
   -- Type Classes
   , GQLType(KIND, description)
   , GQLScalar(parseValue, serialize)
-  -- Values
   , GQLRequest(..)
   , GQLResponse(..)
   , ID(..)
@@ -24,31 +24,55 @@
   , QUERY
   , MUTATION
   , SUBSCRIPTION
-  , liftEitherM
-  , liftM
-  ) where
+  , liftEither
+  , lift
+  , ResolveQ
+  , ResolveM
+  , ResolveS
+  )
+where
 
-import           Data.Morpheus.Types.GQLScalar         (GQLScalar (parseValue, serialize))
-import           Data.Morpheus.Types.GQLType           (GQLType (KIND, description))
-import           Data.Morpheus.Types.ID                (ID (..))
-import           Data.Morpheus.Types.Internal.Data     (MUTATION, QUERY, SUBSCRIPTION)
-import           Data.Morpheus.Types.Internal.Resolver (Event (..), GQLRootResolver (..), PureOperation, Resolver (..),
-                                                        liftEitherM, liftM)
-import           Data.Morpheus.Types.Internal.Value    (ScalarValue (..))
-import           Data.Morpheus.Types.IO                (GQLRequest (..), GQLResponse (..))
-import           Data.Morpheus.Types.Types             (Undefined (..))
+import           Data.Morpheus.Types.GQLScalar  ( GQLScalar
+                                                  ( parseValue
+                                                  , serialize
+                                                  )
+                                                )
+import           Data.Morpheus.Types.GQLType    ( GQLType(KIND, description) )
+import           Data.Morpheus.Types.ID         ( ID(..) )
+import           Data.Morpheus.Types.Internal.AST
+                                                ( MUTATION
+                                                , QUERY
+                                                , SUBSCRIPTION
+                                                , ScalarValue(..)
+                                                )
+import           Data.Morpheus.Types.Internal.Resolving
+                                                ( Event(..)
+                                                , GQLRootResolver(..)
+                                                , Resolver(..)
+                                                , LiftEither(..)
+                                                , lift
+                                                )
+import           Data.Morpheus.Types.IO         ( GQLRequest(..)
+                                                , GQLResponse(..)
+                                                )
+import           Data.Morpheus.Types.Types      ( Undefined(..) )
 
 type Res = Resolver QUERY
 type MutRes = Resolver MUTATION
 type SubRes = Resolver SUBSCRIPTION
 
-type IORes = Res IO
-type IOMutRes = MutRes IO
-type IOSubRes = SubRes IO
+type IORes e = Res e IO
+type IOMutRes e = MutRes e IO
+type IOSubRes e = SubRes e IO
 
+-- Recursive Resolvers
+type ResolveQ e m a = Res e m (a (Res e m))
+type ResolveM e m a = MutRes e m (a (MutRes e m))
+type ResolveS e m a = SubRes e m (a (Res e m))
+
 -- resolves constant value on any argument
-constRes :: (PureOperation o ,Monad m) => b -> a -> Resolver o m e b
+constRes :: (LiftEither o Resolver, Monad m) => b -> a -> Resolver o e m b
 constRes = const . pure
 
-constMutRes :: Monad m =>  [e] -> a -> args -> MutRes m e a
-constMutRes list value = const $ MutResolver list $ pure value
+constMutRes :: Monad m => [e] -> a -> args -> MutRes e m a
+constMutRes events value = const $ MutResolver $ pure (events, value)
diff --git a/src/Data/Morpheus/Types/Custom.hs b/src/Data/Morpheus/Types/Custom.hs
deleted file mode 100644
--- a/src/Data/Morpheus/Types/Custom.hs
+++ /dev/null
@@ -1,44 +0,0 @@
-{-# LANGUAGE DeriveGeneric       #-}
-{-# LANGUAGE RankNTypes          #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE TypeFamilies        #-}
-{-# LANGUAGE TypeOperators       #-}
-
-module Data.Morpheus.Types.Custom
-  ( Pair(..)
-  , MapKind(..)
-  , MapArgs(..)
-  , mapKindFromList
-  ) where
-
-import           GHC.Generics (Generic)
-
-data Pair k v =
-  Pair
-    { key   :: k
-    , value :: v
-    }
-  deriving (Generic)
-
-newtype MapArgs k =
-  MapArgs
-    { oneOf :: Maybe [k]
-    }
-  deriving (Generic)
-
-data MapKind k v m =
-  MapKind
-    { size  :: Int
-    , pairs :: MapArgs k -> m [Pair k v]
-    }
-  deriving (Generic)
-
-mapKindFromList :: (Eq k, Applicative m) => [(k, v)] -> MapKind k v m
-mapKindFromList inputPairs =
-  MapKind {size = length inputPairs, pairs = resolvePairs}
-  where
-    filterBy MapArgs {oneOf = Just list} =
-      filter ((`elem` list) . fst) inputPairs
-    filterBy _ = inputPairs
-    resolvePairs = pure . (map toGQLTuple . filterBy)
-    toGQLTuple (x, y) = Pair x y
diff --git a/src/Data/Morpheus/Types/GQLScalar.hs b/src/Data/Morpheus/Types/GQLScalar.hs
--- a/src/Data/Morpheus/Types/GQLScalar.hs
+++ b/src/Data/Morpheus/Types/GQLScalar.hs
@@ -5,12 +5,17 @@
 module Data.Morpheus.Types.GQLScalar
   ( GQLScalar(..)
   , toScalar
-  ) where
+  )
+where
 
-import           Data.Morpheus.Types.Internal.Data  (DataValidator (..))
-import           Data.Morpheus.Types.Internal.Value (ScalarValue (..), Value (..))
-import           Data.Proxy                         (Proxy (..))
-import           Data.Text                          (Text)
+import           Data.Morpheus.Types.Internal.AST.Data
+                                                ( DataValidator(..) )
+import           Data.Morpheus.Types.Internal.AST.Value
+                                                ( ScalarValue(..)
+                                                , Value(..)
+                                                )
+import           Data.Proxy                     ( Proxy(..) )
+import           Data.Text                      ( Text )
 
 toScalar :: Value -> Either Text ScalarValue
 toScalar (Scalar x) = pure x
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
@@ -2,55 +2,69 @@
 {-# LANGUAGE DefaultSignatures    #-}
 {-# LANGUAGE FlexibleContexts     #-}
 {-# LANGUAGE FlexibleInstances    #-}
-{-# LANGUAGE NamedFieldPuns       #-}
 {-# LANGUAGE OverloadedStrings    #-}
 {-# LANGUAGE ScopedTypeVariables  #-}
 {-# LANGUAGE TypeApplications     #-}
 {-# LANGUAGE TypeFamilies         #-}
 {-# LANGUAGE TypeOperators        #-}
-{-# LANGUAGE TypeSynonymInstances #-}
 
 module Data.Morpheus.Types.GQLType
   ( GQLType(..)
   , TRUE
   , FALSE
-  ) where
+  )
+where
 
-import           Data.Map                              (Map)
-import           Data.Proxy                            (Proxy (..))
-import           Data.Set                              (Set)
-import           Data.Text                             (Text, intercalate, pack)
-import           Data.Typeable                         (TyCon, TypeRep, Typeable, splitTyConApp, tyConFingerprint,
-                                                        tyConName, typeRep, typeRepTyCon)
+import           Data.Map                       ( Map )
+import           Data.Proxy                     ( Proxy(..) )
+import           Data.Set                       ( Set )
+import           Data.Text                      ( Text
+                                                , intercalate
+                                                , pack
+                                                )
+import           Data.Typeable                  ( TyCon
+                                                , TypeRep
+                                                , Typeable
+                                                , splitTyConApp
+                                                , tyConFingerprint
+                                                , tyConName
+                                                , typeRep
+                                                , typeRepTyCon
+                                                )
 
 -- MORPHEUS
 import           Data.Morpheus.Kind
-import           Data.Morpheus.Types.Custom            (MapKind, Pair)
-import           Data.Morpheus.Types.Internal.Data     (DataFingerprint (..), QUERY)
-import           Data.Morpheus.Types.Internal.Resolver (Resolver (..))
-import           Data.Morpheus.Types.Types             (Undefined (..))
+import           Data.Morpheus.Types.Types      ( MapKind
+                                                , Pair
+                                                , Undefined(..)
+                                                )
+import           Data.Morpheus.Types.Internal.AST.Data
+                                                ( DataFingerprint(..)
+                                                , QUERY
+                                                )
+import           Data.Morpheus.Types.Internal.Resolving
+                                                ( Resolver(..) )
 
 type TRUE = 'True
 
 type FALSE = 'False
 
 resolverCon :: TyCon
-resolverCon = typeRepTyCon $ typeRep $ Proxy @(Resolver QUERY Maybe)
+resolverCon = typeRepTyCon $ typeRep $ Proxy @(Resolver QUERY () Maybe)
 
 -- | replaces typeName (A,B) with Pair_A_B
 replacePairCon :: TyCon -> TyCon
-replacePairCon x
-  | hsPair == x = gqlPair
-  where
-    hsPair = typeRepTyCon $ typeRep $ Proxy @(Int, Int)
-    gqlPair = typeRepTyCon $ typeRep $ Proxy @(Pair Int Int)
+replacePairCon x | hsPair == x = gqlPair
+ where
+  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
+ignoreResolver (con, _) | con == resolverCon = []
+ignoreResolver (con, args) =
+  con : concatMap (ignoreResolver . splitTyConApp) args
 
 -- | GraphQL type, every graphQL type should have an instance of 'GHC.Generics.Generic' and 'GQLType'.
 --
@@ -82,7 +96,7 @@
   __typeFingerprint :: Proxy a -> DataFingerprint
   default __typeFingerprint :: (Typeable a) =>
     Proxy a -> DataFingerprint
-  __typeFingerprint _ = TypeableFingerprint $ conFingerprints (Proxy @a)
+  __typeFingerprint _ = TypeableFingerprint $ map show $ conFingerprints (Proxy @a)
     where
       conFingerprints = fmap (map tyConFingerprint) (ignoreResolver . splitTyConApp . typeRep)
 
@@ -144,10 +158,10 @@
   __typeName _ = __typeName (Proxy @a)
   __typeFingerprint _ = __typeFingerprint (Proxy @a)
 
-instance GQLType a => GQLType (Resolver o m e a) where
-      type KIND (Resolver o m e a) = WRAPPER
-      __typeName _ = __typeName (Proxy @a)
-      __typeFingerprint _ = __typeFingerprint (Proxy @a)
+instance GQLType a => GQLType (Resolver o e m a) where
+  type KIND (Resolver o e m a) = WRAPPER
+  __typeName _ = __typeName (Proxy @a)
+  __typeFingerprint _ = __typeFingerprint (Proxy @a)
 
 instance GQLType b => GQLType (a -> b) where
   type KIND (a -> b) = WRAPPER
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
@@ -4,14 +4,18 @@
 
 module Data.Morpheus.Types.ID
   ( ID(..)
-  ) where
+  )
+where
 
-import           Data.Morpheus.Kind                 (SCALAR)
-import           Data.Morpheus.Types.GQLScalar      (GQLScalar (..))
-import           Data.Morpheus.Types.GQLType        (GQLType (KIND))
-import           Data.Morpheus.Types.Internal.Value (ScalarValue (..))
-import           Data.Text                          (Text, pack)
-import           GHC.Generics                       (Generic)
+import           Data.Morpheus.Kind             ( SCALAR )
+import           Data.Morpheus.Types.GQLScalar  ( GQLScalar(..) )
+import           Data.Morpheus.Types.GQLType    ( GQLType(KIND) )
+import           Data.Morpheus.Types.Internal.AST.Value
+                                                ( ScalarValue(..) )
+import           Data.Text                      ( Text
+                                                , pack
+                                                )
+import           GHC.Generics                   ( Generic )
 
 -- | default GraphQL type,
 -- parses only 'String' and 'Int' values,
@@ -24,7 +28,7 @@
   type KIND ID = SCALAR
 
 instance GQLScalar ID where
-  parseValue (Int x)    = return (ID $ pack $ show x)
+  parseValue (Int    x) = return (ID $ pack $ show x)
   parseValue (String x) = return (ID x)
   parseValue _          = Left ""
   serialize (ID x) = String x
diff --git a/src/Data/Morpheus/Types/IO.hs b/src/Data/Morpheus/Types/IO.hs
--- a/src/Data/Morpheus/Types/IO.hs
+++ b/src/Data/Morpheus/Types/IO.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE NamedFieldPuns    #-}
 {-# LANGUAGE DeriveAnyClass    #-}
 {-# LANGUAGE DeriveGeneric     #-}
 {-# LANGUAGE OverloadedStrings #-}
@@ -7,31 +8,44 @@
   , GQLResponse(..)
   , JSONResponse(..)
   , renderResponse
-  ) where
+  )
+where
 
-import           Data.Aeson                              (FromJSON (..), ToJSON (..), pairs, withObject, (.:?), (.=))
-import qualified Data.Aeson                              as Aeson (Value (..))
-import qualified Data.HashMap.Lazy                       as LH (toList)
-import           GHC.Generics                            (Generic)
+import           Data.Aeson                     ( FromJSON(..)
+                                                , ToJSON(..)
+                                                , pairs
+                                                , withObject
+                                                , (.:?)
+                                                , (.=)
+                                                )
+import qualified Data.Aeson                    as Aeson
+                                                ( Value(..) )
+import qualified Data.HashMap.Lazy             as LH
+                                                ( toList )
+import           GHC.Generics                   ( Generic )
 
 -- MORPHEUS
-import           Data.Morpheus.Types.Internal.Base       (Key)
-import           Data.Morpheus.Types.Internal.Validation (JSONError (..),Validation)
-import           Data.Morpheus.Types.Internal.Value      (Value)
-import           Data.Morpheus.Error.Utils               ( renderErrors)
+import           Data.Morpheus.Types.Internal.AST.Base
+                                                ( Key )
+import           Data.Morpheus.Types.Internal.Resolving.Core
+                                                ( GQLError(..)
+                                                , Result(..)
+                                                )
+import           Data.Morpheus.Types.Internal.AST.Value
+                                                ( Value )
 
-renderResponse :: Validation Value -> GQLResponse 
-renderResponse (Left errors) = Errors $ renderErrors errors
-renderResponse (Right value) = Data value
 
+renderResponse :: Result e GQLError con Value -> GQLResponse
+renderResponse (Failure errors)   = Errors errors
+renderResponse Success { result } = Data result
+
 instance FromJSON a => FromJSON (JSONResponse a) where
   parseJSON = withObject "JSONResponse" objectParser
-    where
-      objectParser o = JSONResponse <$> o .:? "data" <*> o .:? "errors"
+    where objectParser o = JSONResponse <$> o .:? "data" <*> o .:? "errors"
 
 data JSONResponse a = JSONResponse
   { responseData   :: Maybe a
-  , responseErrors :: Maybe [JSONError]
+  , responseErrors :: Maybe [GQLError]
   } deriving (Generic, Show, ToJSON)
 
 -- | GraphQL HTTP Request Body
@@ -44,17 +58,16 @@
 -- | GraphQL Response
 data GQLResponse
   = Data Value
-  | Errors [JSONError]
+  | Errors [GQLError]
   deriving (Show, Generic)
 
 instance FromJSON GQLResponse where
-  parseJSON (Aeson.Object hm) =
-    case LH.toList hm of
-      [("data", value)]   -> Data <$> parseJSON value
-      [("errors", value)] -> Errors <$> parseJSON value
-      _                   -> fail "Invalid GraphQL Response"
+  parseJSON (Aeson.Object hm) = case LH.toList hm of
+    [("data"  , value)] -> Data <$> parseJSON value
+    [("errors", value)] -> Errors <$> parseJSON value
+    _                   -> fail "Invalid GraphQL Response"
   parseJSON _ = fail "Invalid GraphQL Response"
 
 instance ToJSON GQLResponse where
-  toEncoding (Data _data)     = pairs $ "data" .= _data
+  toEncoding (Data   _data  ) = pairs $ "data" .= _data
   toEncoding (Errors _errors) = pairs $ "errors" .= _errors
diff --git a/src/Data/Morpheus/Types/Internal/AST.hs b/src/Data/Morpheus/Types/Internal/AST.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Morpheus/Types/Internal/AST.hs
@@ -0,0 +1,162 @@
+{-# LANGUAGE DeriveLift       #-}
+
+module Data.Morpheus.Types.Internal.AST
+  (
+    -- BASE
+    Key
+  , Collection
+  , Ref(..)
+  , Position(..)
+  , Message
+  , anonymousRef
+  , Name
+  , Description
+
+  -- VALUE
+  , Value(..)
+  , ScalarValue(..)
+  , Object
+  , GQLValue(..)
+  , replaceValue
+  , decodeScientific
+  , convertToJSONName
+  , convertToHaskellName
+
+  -- Selection
+  , Argument(..)
+  , Arguments
+  , SelectionSet
+  , SelectionRec(..)
+  , ValueOrigin(..)
+  , ValidSelection
+  , Selection(..)
+  , RawSelection'
+  , FragmentLib
+  , RawArguments
+  , RawSelectionSet
+  , Fragment(..)
+  , RawArgument(..)
+  , RawSelection(..)
+
+  -- OPERATION
+  , Operation(..)
+  , Variable(..)
+  , ValidOperation
+  , RawOperation
+  , VariableDefinitions
+  , ValidVariables
+  , DefaultValue
+  , getOperationName
+  , getOperationDataType
+
+
+  -- DSL
+  , DataScalar
+  , DataEnum
+  , DataObject
+  , DataArgument
+  , DataUnion
+  , DataArguments
+  , DataField(..)
+  , DataTyCon(..)
+  , DataType(..)
+  , DataTypeLib(..)
+  , DataTypeWrapper(..)
+  , DataValidator(..)
+  , DataTypeKind(..)
+  , DataFingerprint(..)
+  , RawDataType(..)
+  , ResolverKind(..)
+  , TypeWrapper(..)
+  , TypeAlias(..)
+  , ArgsType(..)
+  , DataEnumValue(..)
+  , isTypeDefined
+  , initTypeLib
+  , defineType
+  , isFieldNullable
+  , allDataTypes
+  , lookupDataType
+  , kindOf
+  , toNullableField
+  , toListField
+  , isObject
+  , isInput
+  , toHSWrappers
+  , isNullable
+  , toGQLWrapper
+  , isWeaker
+  , isSubscription
+  , isOutputObject
+  , sysTypes
+  , isDefaultTypeName
+  , isSchemaTypeName
+  , isPrimitiveTypeName
+  , OperationType(..)
+  , QUERY
+  , MUTATION
+  , SUBSCRIPTION
+  , isEntNode
+  , lookupInputType
+  , coerceDataObject
+  , getDataType
+  , lookupDataObject
+  , lookupDataUnion
+  , lookupType
+  , lookupField
+  , lookupUnionTypes
+  , lookupSelectionField
+  , lookupFieldAsSelectionSet
+  , createField
+  , createArgument
+  , createDataTypeLib
+  , createEnumType
+  , createScalarType
+  , createType
+  , createUnionType
+  , createAlias
+  , createInputUnionFields
+  , fieldVisibility
+  , Meta(..)
+  , Directive(..)
+  , createEnumValue
+  , fromDataType
+  , insertType
+  , TypeUpdater
+  , lookupDeprecated
+  , lookupDeprecatedReason
+  , TypeD(..)
+  , ConsD(..)
+  , ClientQuery(..)
+  , GQLTypeD(..)
+  , ClientType(..)
+  -- LOCAL
+  , GQLQuery(..)
+  , Variables
+  )
+where
+
+import           Data.Map                       ( Map )
+import           Language.Haskell.TH.Syntax     ( Lift )
+import           Instances.TH.Lift              ( )
+
+-- Morpheus
+import           Data.Morpheus.Types.Internal.AST.Data
+
+
+import           Data.Morpheus.Types.Internal.AST.Operation
+
+import           Data.Morpheus.Types.Internal.AST.Selection
+
+import           Data.Morpheus.Types.Internal.AST.Base
+
+import           Data.Morpheus.Types.Internal.AST.Value
+
+
+type Variables = Map Key Value
+
+data GQLQuery = GQLQuery
+  { fragments      :: FragmentLib
+  , operation      :: RawOperation
+  , inputVariables :: [(Key, Value)]
+  } deriving (Show,Lift)
diff --git a/src/Data/Morpheus/Types/Internal/AST/Base.hs b/src/Data/Morpheus/Types/Internal/AST/Base.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Morpheus/Types/Internal/AST/Base.hs
@@ -0,0 +1,55 @@
+{-# LANGUAGE DeriveAnyClass  #-}
+{-# LANGUAGE DeriveGeneric   #-}
+{-# LANGUAGE DeriveLift      #-}
+{-# LANGUAGE NamedFieldPuns  #-}
+
+module Data.Morpheus.Types.Internal.AST.Base
+  ( Key
+  , Collection
+  , Ref(..)
+  , Position(..)
+  , Message
+  , anonymousRef
+  , Name
+  , Description
+  )
+where
+
+import           Data.Aeson                     ( FromJSON
+                                                , ToJSON
+                                                )
+import           Data.Text                      ( Text )
+import           GHC.Generics                   ( Generic )
+import           Language.Haskell.TH.Syntax     ( Lift )
+import           Instances.TH.Lift              ( )
+
+
+type Key = Text
+type Message = Text
+type Name = Key
+type Description = Key
+
+type Collection a = [(Key, a)]
+
+data Position = Position
+  { line   :: Int
+  , column :: Int
+  } deriving (Show, Generic, FromJSON, ToJSON, Lift)
+
+-- Refference with Position information  
+--
+-- includes position for debugging, where Ref "a" 1 === Ref "a" 3
+--
+data Ref = Ref
+  { refName     :: Key
+  , refPosition :: Position
+  } deriving (Show,Lift)
+
+instance Eq Ref where
+  (Ref id1 _) == (Ref id2 _) = id1 == id2
+
+instance Ord Ref where
+  compare (Ref x _) (Ref y _) = compare x y
+
+anonymousRef :: Key -> Ref
+anonymousRef refName = Ref { refName, refPosition = Position 0 0 }
diff --git a/src/Data/Morpheus/Types/Internal/AST/Data.hs b/src/Data/Morpheus/Types/Internal/AST/Data.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Morpheus/Types/Internal/AST/Data.hs
@@ -0,0 +1,659 @@
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE DataKinds             #-}
+{-# LANGUAGE DeriveLift            #-}
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE GADTs                 #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE NamedFieldPuns        #-}
+{-# LANGUAGE OverloadedStrings     #-}
+{-# LANGUAGE PolyKinds             #-}
+{-# LANGUAGE RankNTypes            #-}
+
+module Data.Morpheus.Types.Internal.AST.Data
+  ( 
+    DataScalar
+  , DataEnum
+  , DataObject
+  , DataArgument
+  , DataUnion
+  , DataArguments
+  , DataField(..)
+  , DataTyCon(..)
+  , DataType(..)
+  , DataTypeLib(..)
+  , DataTypeWrapper(..)
+  , DataValidator(..)
+  , DataTypeKind(..)
+  , DataFingerprint(..)
+  , RawDataType(..)
+  , ResolverKind(..)
+  , TypeWrapper(..)
+  , TypeAlias(..)
+  , ArgsType(..)
+  , DataEnumValue(..)
+  , isTypeDefined
+  , initTypeLib
+  , defineType
+  , isFieldNullable
+  , allDataTypes
+  , lookupDataType
+  , kindOf
+  , toNullableField
+  , toListField
+  , isObject
+  , isInput
+  , toHSWrappers
+  , isNullable
+  , toGQLWrapper
+  , isWeaker
+  , isSubscription
+  , isOutputObject
+  , sysTypes
+  , isDefaultTypeName
+  , isSchemaTypeName
+  , isPrimitiveTypeName
+  , OperationType(..)
+  , QUERY
+  , MUTATION
+  , SUBSCRIPTION
+  , isEntNode
+  , lookupInputType
+  , coerceDataObject
+  , getDataType
+  , lookupDataObject
+  , lookupDataUnion
+  , lookupType
+  , lookupField
+  , lookupUnionTypes
+  , lookupSelectionField
+  , lookupFieldAsSelectionSet
+  , createField
+  , createArgument
+  , createDataTypeLib
+  , createEnumType
+  , createScalarType
+  , createType
+  , createUnionType
+  , createAlias
+  , createInputUnionFields
+  , fieldVisibility
+  , Meta(..)
+  , Directive(..)
+  , createEnumValue
+  , fromDataType
+  , insertType
+  , TypeUpdater
+  , lookupDeprecated
+  , lookupDeprecatedReason
+  , TypeD(..)
+  , ConsD(..)
+  , ClientQuery(..)
+  , GQLTypeD(..)
+  , ClientType(..)
+  )
+where
+
+import           Data.HashMap.Lazy              ( HashMap
+                                                , empty
+                                                , fromList
+                                                , insert
+                                                , toList
+                                                , union
+                                                )
+import qualified Data.HashMap.Lazy             as HM
+                                                ( lookup )
+import           Data.Semigroup                 ( (<>) )
+import           Language.Haskell.TH.Syntax     ( Lift )
+import           Instances.TH.Lift              ( )
+import           Data.List                      ( find )
+
+-- MORPHEUS
+import           Data.Morpheus.Error.Internal   ( internalError )
+import           Data.Morpheus.Error.Selection  ( cannotQueryField
+                                                , hasNoSubfields
+                                                )
+import           Data.Morpheus.Types.Internal.AST.Base
+                                                ( Key
+                                                , Position
+                                                , Name
+                                                , Description
+                                                )
+import           Data.Morpheus.Types.Internal.Resolving.Core
+                                                ( Validation
+                                                , Failure(..)
+                                                , GQLErrors
+                                                , LibUpdater
+                                                , resolveUpdates
+                                                )
+import           Data.Morpheus.Types.Internal.AST.Value
+                                                ( Value(..)
+                                                , ScalarValue(..)
+                                                )
+import           Data.Morpheus.Error.Schema     ( nameCollisionError )
+
+type QUERY = 'Query
+type MUTATION = 'Mutation
+type SUBSCRIPTION = 'Subscription
+
+isDefaultTypeName :: Key -> Bool
+isDefaultTypeName x = isSchemaTypeName x || isPrimitiveTypeName x
+
+isSchemaTypeName :: Key -> Bool
+isSchemaTypeName = (`elem` sysTypes)
+
+isPrimitiveTypeName :: Key -> Bool
+isPrimitiveTypeName = (`elem` ["String", "Float", "Int", "Boolean", "ID"])
+
+sysTypes :: [Key]
+sysTypes =
+  [ "__Schema"
+  , "__Type"
+  , "__Directive"
+  , "__TypeKind"
+  , "__Field"
+  , "__DirectiveLocation"
+  , "__InputValue"
+  , "__EnumValue"
+  ]
+
+data OperationType
+  = 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 (Maybe OperationType)
+  | KindUnion
+  | KindEnum
+  | KindInputObject
+  | KindList
+  | KindNonNull
+  | KindInputUnion
+  deriving (Eq, Show, Lift)
+
+data ResolverKind
+  = PlainResolver
+  | TypeVarResolver
+  | ExternalResolver
+  deriving (Show, Eq, Lift)
+
+data TypeWrapper
+  = TypeList
+  | TypeMaybe
+  deriving (Show, Lift)
+
+isFieldNullable :: DataField -> Bool
+isFieldNullable = isNullable . aliasWrappers . fieldType
+
+isNullable :: [TypeWrapper] -> Bool
+isNullable (TypeMaybe : _) = True
+isNullable _               = False
+
+isWeaker :: [TypeWrapper] -> [TypeWrapper] -> Bool
+isWeaker (TypeMaybe : xs1) (TypeMaybe : xs2) = isWeaker xs1 xs2
+isWeaker (TypeMaybe : _  ) _                 = True
+isWeaker (_         : xs1) (_ : xs2)         = isWeaker xs1 xs2
+isWeaker _                 _                 = False
+
+toGQLWrapper :: [TypeWrapper] -> [DataTypeWrapper]
+toGQLWrapper (TypeMaybe : (TypeMaybe : tw)) = toGQLWrapper (TypeMaybe : tw)
+toGQLWrapper (TypeMaybe : (TypeList  : tw)) = ListType : toGQLWrapper tw
+toGQLWrapper (TypeList : tw) = [NonNullType, ListType] <> toGQLWrapper tw
+toGQLWrapper [TypeMaybe                   ] = []
+toGQLWrapper []                             = [NonNullType]
+
+toHSWrappers :: [DataTypeWrapper] -> [TypeWrapper]
+toHSWrappers (NonNullType : (NonNullType : xs)) =
+  toHSWrappers (NonNullType : xs)
+toHSWrappers (NonNullType : (ListType : xs)) = TypeList : toHSWrappers xs
+toHSWrappers (ListType : xs) = [TypeMaybe, TypeList] <> toHSWrappers xs
+toHSWrappers []                              = [TypeMaybe]
+toHSWrappers [NonNullType]                   = []
+
+data DataFingerprint = SystemFingerprint Key | TypeableFingerprint [String]
+  deriving (Show, Eq, Ord, Lift)
+
+
+newtype DataValidator = DataValidator
+  { validateValue :: Value -> Either Key Value
+  }
+
+instance Show DataValidator where
+  show _ = "DataValidator"
+
+type DataScalar = DataTyCon DataValidator
+
+type DataEnum = DataTyCon [DataEnumValue]
+
+type DataObject = DataTyCon [(Key, DataField)]
+
+type DataArgument = DataField
+
+type DataUnion = DataTyCon [Key]
+
+type DataArguments = [(Key, DataArgument)]
+
+data DataTypeWrapper
+  = ListType
+  | NonNullType
+  deriving (Show, Lift)
+
+data TypeAlias = TypeAlias
+  { aliasTyCon    :: Key
+  , aliasArgs     :: Maybe Key
+  , aliasWrappers :: [TypeWrapper]
+  } deriving (Show,Lift)
+
+data ArgsType = ArgsType
+  { argsTypeName :: Key
+  , resKind      :: ResolverKind
+  } deriving (Show,Lift)
+
+data Directive = Directive {
+  directiveName :: Name,
+  directiveArgs :: [(Name,Value)]
+} deriving (Show,Lift)
+
+-- META
+data Meta = Meta {
+    metaDescription:: Maybe Description,
+    metaDirectives  :: [Directive]
+} deriving (Show,Lift)
+
+lookupDeprecated :: Meta -> Maybe Directive
+lookupDeprecated Meta { metaDirectives } = find isDeprecation metaDirectives
+ where
+  isDeprecation Directive { directiveName = "deprecated" } = True
+  isDeprecation _ = False
+
+lookupDeprecatedReason :: Directive -> Maybe Key
+lookupDeprecatedReason Directive { directiveArgs } =
+  maybeString . snd <$> find isReason directiveArgs
+ where
+  maybeString (Scalar (String x)) = x
+  maybeString _                   = "can't read deprecated Reason Value"
+  isReason ("reason", _) = True
+  isReason _             = False
+
+-- ENUM VALUE
+data DataEnumValue = DataEnumValue{
+    enumName :: Name,
+    enumMeta :: Maybe Meta
+} deriving (Show, Lift)
+
+--------------------------------------------------------------------------------------------------
+data DataField = DataField
+  { fieldName     :: Key
+  , fieldArgs     :: [(Key, DataArgument)]
+  , fieldArgsType :: Maybe ArgsType
+  , fieldType     :: TypeAlias
+  , fieldMeta     :: Maybe Meta
+  } deriving (Show,Lift)
+
+fieldVisibility :: (Key, DataField) -> Bool
+fieldVisibility ("__typename", _) = False
+fieldVisibility ("__schema"  , _) = False
+fieldVisibility ("__type"    , _) = False
+fieldVisibility _                 = True
+
+createField :: DataArguments -> Key -> ([TypeWrapper], Key) -> DataField
+createField fieldArgs fieldName (aliasWrappers, aliasTyCon) = DataField
+  { fieldArgs
+  , fieldArgsType = Nothing
+  , fieldName
+  , fieldType     = TypeAlias { aliasTyCon, aliasWrappers, aliasArgs = Nothing }
+  , fieldMeta     = Nothing
+  }
+
+createArgument :: Key -> ([TypeWrapper], Key) -> (Key, DataField)
+createArgument fieldName x = (fieldName, createField [] fieldName x)
+
+
+toNullableField :: DataField -> DataField
+toNullableField dataField
+  | isNullable (aliasWrappers $ fieldType dataField) = dataField
+  | otherwise = dataField { fieldType = nullable (fieldType dataField) }
+ where
+  nullable alias@TypeAlias { aliasWrappers } =
+    alias { aliasWrappers = TypeMaybe : aliasWrappers }
+
+toListField :: DataField -> DataField
+toListField dataField = dataField { fieldType = listW (fieldType dataField) }
+ where
+  listW alias@TypeAlias { aliasWrappers } =
+    alias { aliasWrappers = TypeList : aliasWrappers }
+
+lookupField :: Failure error m => Key -> [(Key, field)] -> error -> m field
+lookupField key fields gqlError = case lookup key fields of
+  Nothing    -> failure gqlError
+  Just field -> pure field
+
+lookupSelectionField
+  :: Failure GQLErrors Validation
+  => Position
+  -> Key
+  -> DataObject
+  -> Validation DataField
+lookupSelectionField position fieldName DataTyCon { typeData, typeName } =
+  lookupField fieldName typeData gqlError
+  where gqlError = cannotQueryField fieldName typeName position
+
+--
+-- TYPE CONSTRUCTOR
+--------------------------------------------------------------------------------------------------
+data DataTyCon a = DataTyCon
+  { typeName        :: Key
+  , typeFingerprint :: DataFingerprint
+  , typeMeta :: Maybe Meta
+  , typeData        :: a
+  } deriving (Show, Lift)
+
+
+data RawDataType
+  = FinalDataType DataType
+  | Interface DataObject
+  | Implements { implementsInterfaces :: [Key]
+               , unImplements         :: DataObject }
+  deriving (Show)
+
+--
+-- DATA TYPE
+--------------------------------------------------------------------------------------------------
+data DataType
+  = DataScalar DataScalar
+  | DataEnum DataEnum
+  | DataInputObject DataObject
+  | DataObject DataObject
+  | DataUnion DataUnion
+  | DataInputUnion DataUnion
+  deriving (Show)
+
+createType :: Key -> a -> DataTyCon a
+createType typeName typeData = DataTyCon
+  { typeName
+  , typeMeta        = Nothing
+  , typeFingerprint = SystemFingerprint ""
+  , typeData
+  }
+
+createScalarType :: Key -> (Key, DataType)
+createScalarType typeName =
+  (typeName, DataScalar $ createType typeName (DataValidator pure))
+
+createEnumType :: Key -> [Key] -> (Key, DataType)
+createEnumType typeName typeData =
+  (typeName, DataEnum $ createType typeName enumValues)
+  where enumValues = map createEnumValue typeData
+
+createEnumValue :: Key -> DataEnumValue
+createEnumValue enumName = DataEnumValue { enumName, enumMeta = Nothing }
+
+createUnionType :: Key -> [Key] -> (Key, DataType)
+createUnionType typeName typeData =
+  (typeName, DataUnion $ createType typeName typeData)
+
+
+isEntNode :: DataType -> Bool
+isEntNode DataScalar{} = True
+isEntNode DataEnum{}   = True
+isEntNode _            = False
+
+isInputDataType :: DataType -> Bool
+isInputDataType DataScalar{}      = True
+isInputDataType DataEnum{}        = True
+isInputDataType DataInputObject{} = True
+isInputDataType DataInputUnion{}  = True
+isInputDataType _                 = False
+
+coerceDataObject :: Failure error m => error -> DataType -> m DataObject
+coerceDataObject _        (DataObject object) = pure object
+coerceDataObject gqlError _                   = failure gqlError
+
+coerceDataUnion :: Failure error m => error -> DataType -> m DataUnion
+coerceDataUnion _        (DataUnion object) = pure object
+coerceDataUnion gqlError _                  = failure gqlError
+
+kindOf :: DataType -> DataTypeKind
+kindOf (DataScalar      _) = KindScalar
+kindOf (DataEnum        _) = KindEnum
+kindOf (DataInputObject _) = KindInputObject
+kindOf (DataObject      _) = KindObject Nothing
+kindOf (DataUnion       _) = KindUnion
+kindOf (DataInputUnion  _) = KindInputUnion
+
+fromDataType :: (DataTyCon () -> v) -> DataType -> v
+fromDataType f (DataScalar      dt) = f dt { typeData = () }
+fromDataType f (DataEnum        dt) = f dt { typeData = () }
+fromDataType f (DataUnion       dt) = f dt { typeData = () }
+fromDataType f (DataInputObject dt) = f dt { typeData = () }
+fromDataType f (DataInputUnion  dt) = f dt { typeData = () }
+fromDataType f (DataObject      dt) = f dt { typeData = () }
+
+--
+-- Type Register
+--------------------------------------------------------------------------------------------------
+data DataTypeLib = DataTypeLib
+  { types        :: HashMap Key DataType
+  , query        :: (Key,  DataObject)
+  , mutation     :: Maybe (Key, DataObject)
+  , subscription :: Maybe (Key, DataObject)
+  } deriving (Show)
+
+type TypeRegister = HashMap Key DataType
+
+initTypeLib :: (Key, DataObject) -> DataTypeLib
+initTypeLib query = DataTypeLib { types        = empty
+                                , query        = query
+                                , mutation     = Nothing
+                                , subscription = Nothing
+                                }
+
+allDataTypes :: DataTypeLib -> [(Key, DataType)]
+allDataTypes DataTypeLib { types, query, mutation, subscription } =
+  concatMap fromOperation [Just query, mutation, subscription] <> toList types
+
+typeRegister :: DataTypeLib -> TypeRegister
+typeRegister DataTypeLib { types, query, mutation, subscription } =
+  types `union` fromList
+    (concatMap fromOperation [Just query, mutation, subscription])
+
+fromOperation :: Maybe (Key, DataObject) -> [(Key, DataType)]
+fromOperation (Just (key', dataType')) = [(key', DataObject dataType')]
+fromOperation Nothing                  = []
+
+lookupDataType :: Key -> DataTypeLib -> Maybe DataType
+lookupDataType name lib = name `HM.lookup` typeRegister lib
+
+getDataType :: Failure error m => Key -> DataTypeLib -> error -> m DataType
+getDataType name lib gqlError = case lookupDataType name lib of
+  Just x -> pure x
+  _      -> failure gqlError
+
+lookupDataObject
+  :: (Monad m, Failure e m) => e -> Key -> DataTypeLib -> m DataObject
+lookupDataObject validationError name lib =
+  getDataType name lib validationError >>= coerceDataObject validationError
+
+lookupDataUnion
+  :: (Monad m, Failure e m) => e -> Key -> DataTypeLib -> m DataUnion
+lookupDataUnion validationError name lib =
+  getDataType name lib validationError >>= coerceDataUnion validationError
+
+lookupUnionTypes
+  :: (Monad m, Failure GQLErrors m)
+  => Position
+  -> Key
+  -> DataTypeLib
+  -> DataField
+  -> m [DataObject]
+lookupUnionTypes position key lib DataField { fieldType = TypeAlias { aliasTyCon = typeName } }
+  = lookupDataUnion gqlError typeName lib
+    >>= mapM (flip (lookupDataObject gqlError) lib)
+    .   typeData
+  where gqlError = hasNoSubfields key typeName position
+
+lookupFieldAsSelectionSet
+  :: (Monad m, Failure GQLErrors m)
+  => Position
+  -> Key
+  -> DataTypeLib
+  -> DataField
+  -> m DataObject
+lookupFieldAsSelectionSet position key lib DataField { fieldType = TypeAlias { aliasTyCon } }
+  = lookupDataObject gqlError aliasTyCon lib
+  where gqlError = hasNoSubfields key aliasTyCon position
+
+lookupInputType :: Failure e m => Key -> DataTypeLib -> e -> m DataType
+lookupInputType name lib errors = case lookupDataType name lib of
+  Just x | isInputDataType x -> pure x
+  _                          -> failure errors
+
+isTypeDefined :: Key -> DataTypeLib -> Maybe DataFingerprint
+isTypeDefined name lib =
+  fromDataType typeFingerprint <$> lookupDataType name lib
+
+defineType :: (Key, DataType) -> DataTypeLib -> DataTypeLib
+defineType (key, datatype@(DataInputUnion DataTyCon { typeName, typeData = enumKeys, typeFingerprint })) lib
+  = lib { types = insert name unionTags (insert key datatype (types lib)) }
+ where
+  name      = typeName <> "Tags"
+  unionTags = DataEnum DataTyCon { typeName        = name
+                                 , typeFingerprint
+                                 , typeMeta        = Nothing
+                                 , typeData = map createEnumValue enumKeys
+                                 }
+defineType (key, datatype) lib =
+  lib { types = insert key datatype (types lib) }
+
+lookupType :: Failure e m => e -> [(Key, a)] -> Key -> m a
+lookupType err lib typeName = case lookup typeName lib of
+  Nothing -> failure err
+  Just x  -> pure x
+
+createDataTypeLib :: [(Key, DataType)] -> Validation DataTypeLib
+createDataTypeLib types = case takeByKey "Query" types of
+  (Just query, lib1) -> case takeByKey "Mutation" lib1 of
+    (mutation, lib2) -> case takeByKey "Subscription" lib2 of
+      (subscription, lib3) ->
+        pure
+          ((foldr defineType (initTypeLib query) lib3) { mutation
+                                                       , subscription
+                                                       }
+          )
+  _ -> internalError "Query Not Defined"
+  ----------------------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ where
+  takeByKey key lib = case lookup key lib of
+    Just (DataObject value) -> (Just (key, value), filter ((/= key) . fst) lib)
+    _                       -> (Nothing, lib)
+
+
+createInputUnionFields :: Key -> [Key] -> [(Key, DataField)]
+createInputUnionFields name members = fieldTag : map unionField members
+ where
+  fieldTag =
+    ( "tag"
+    , DataField { fieldName     = "tag"
+                , fieldArgs     = []
+                , fieldArgsType = Nothing
+                , fieldType     = createAlias (name <> "Tags")
+                , fieldMeta     = Nothing
+                }
+    )
+  unionField memberName =
+    ( memberName
+    , DataField
+      { fieldArgs     = []
+      , fieldArgsType = Nothing
+      , fieldName     = memberName
+      , fieldType     = TypeAlias { aliasTyCon    = memberName
+                                  , aliasWrappers = [TypeMaybe]
+                                  , aliasArgs     = Nothing
+                                  }
+      , fieldMeta     = Nothing
+      }
+    )
+
+createAlias :: Key -> TypeAlias
+createAlias aliasTyCon =
+  TypeAlias { aliasTyCon, aliasWrappers = [], aliasArgs = Nothing }
+
+
+type TypeUpdater = LibUpdater DataTypeLib
+
+insertType :: (Key, DataType) -> TypeUpdater
+insertType nextType@(name, datatype) lib = case isTypeDefined name lib of
+  Nothing -> resolveUpdates (defineType nextType lib) []
+  Just fingerprint
+    | fingerprint == fromDataType typeFingerprint datatype -> return lib
+    |
+      -- throw error if 2 different types has same name
+      otherwise -> failure $ nameCollisionError name
+
+
+-- TEMPLATE HASKELL DATA TYPES
+
+-- CLIENT                                                
+data ClientQuery = ClientQuery
+  { queryText     :: String
+  , queryTypes    :: [ClientType]
+  , queryArgsType :: Maybe TypeD
+  } deriving (Show)
+
+data ClientType = ClientType {
+  clientType :: TypeD,
+  clientKind :: DataTypeKind
+} deriving (Show)
+
+-- Document
+data GQLTypeD = GQLTypeD
+  { typeD     :: TypeD
+  , typeKindD :: DataTypeKind
+  , typeArgD  :: [TypeD]
+  , typeOriginal:: (Name,DataType)
+  } deriving (Show)
+
+data TypeD = TypeD
+  { tName      :: String
+  , tNamespace :: [String]
+  , tCons      :: [ConsD]
+  , tMeta      :: Maybe Meta
+  } deriving (Show)
+
+data ConsD = ConsD
+  { cName   :: String
+  , cFields :: [DataField]
+  } deriving (Show)
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
@@ -1,7 +1,7 @@
-{-# LANGUAGE DeriveLift        #-}
-{-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE TemplateHaskell   #-}
+{-# LANGUAGE DeriveLift         #-}
+{-# LANGUAGE NamedFieldPuns     #-}
+{-# LANGUAGE FlexibleInstances  #-}
+{-# LANGUAGE OverloadedStrings  #-}
 
 module Data.Morpheus.Types.Internal.AST.Operation
   ( Operation(..)
@@ -12,19 +12,39 @@
   , ValidVariables
   , DefaultValue
   , getOperationName
-  ) where
+  , getOperationDataType
+  )
+where
 
-import           Data.Maybe                                    (fromMaybe)
-import           Language.Haskell.TH.Syntax                    (Lift (..))
+import           Data.Maybe                     ( fromMaybe )
+import           Language.Haskell.TH.Syntax     ( Lift(..) )
 
 -- MORPHEUS
-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             (OperationType, WrapperD)
-import           Data.Morpheus.Types.Internal.TH               (apply, liftMaybeText, liftText, liftTextMap)
-import           Data.Morpheus.Types.Internal.Value            (Value)
+import           Data.Morpheus.Error.Mutation   ( mutationIsNotDefined )
+import           Data.Morpheus.Error.Subscription
+                                                ( subscriptionIsNotDefined )
+import           Data.Morpheus.Types.Internal.AST.Selection
+                                                ( Arguments
+                                                , SelectionSet
+                                                , RawSelectionSet
+                                                )
 
+import           Data.Morpheus.Types.Internal.Resolving.Core
+                                                ( Validation ,Failure(..) )
+import           Data.Morpheus.Types.Internal.AST.Base
+                                                ( Collection
+                                                , Key
+                                                , Position
+                                                )
+import           Data.Morpheus.Types.Internal.AST.Data
+                                                ( OperationType(..)
+                                                , TypeWrapper
+                                                , DataTypeLib(..)
+                                                , DataObject
+                                                )
+import           Data.Morpheus.Types.Internal.AST.Value
+                                                ( Value )
+
 type DefaultValue = Maybe Value
 
 type VariableDefinitions = Collection (Variable DefaultValue)
@@ -44,19 +64,25 @@
   , operationArgs      :: args
   , operationSelection :: sel
   , operationPosition  :: Position
-  } deriving (Show)
-
-instance Lift (Operation VariableDefinitions RawSelectionSet) where
-  lift (Operation name kind args sel pos) =
-    apply 'Operation [liftMaybeText name, lift kind, liftTextMap args, liftTextMap sel, lift pos]
+  } deriving (Show,Lift)
 
 data Variable a = Variable
   { variableType         :: Key
   , isVariableRequired   :: Bool
-  , variableTypeWrappers :: [WrapperD]
+  , variableTypeWrappers :: [TypeWrapper]
   , variablePosition     :: Position
   , variableValue        :: a
-  } deriving (Show)
+  } deriving (Show,Lift)
 
-instance Lift a => Lift (Variable a) where
-  lift (Variable t ir w p v) = apply 'Variable [liftText t, lift ir, lift w, lift p, lift v]
+getOperationDataType :: Operation a b -> DataTypeLib -> Validation DataObject
+getOperationDataType Operation { operationType = Query } lib =
+  pure $ snd $ query lib
+getOperationDataType Operation { operationType = Mutation, operationPosition } lib
+  = case mutation lib of
+    Just (_, mutation') -> pure mutation'
+    Nothing             -> failure $ mutationIsNotDefined operationPosition
+getOperationDataType Operation { operationType = Subscription, operationPosition } lib
+  = case subscription lib of
+    Just (_, subscription') -> pure subscription'
+    Nothing                 -> failure $ subscriptionIsNotDefined operationPosition
+
diff --git a/src/Data/Morpheus/Types/Internal/AST/RawSelection.hs b/src/Data/Morpheus/Types/Internal/AST/RawSelection.hs
deleted file mode 100644
--- a/src/Data/Morpheus/Types/Internal/AST/RawSelection.hs
+++ /dev/null
@@ -1,61 +0,0 @@
-{-# LANGUAGE DeriveLift        #-}
-{-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE TemplateHaskell   #-}
-
-module Data.Morpheus.Types.Internal.AST.RawSelection
-  ( Reference(..)
-  , Argument(..)
-  , RawArgument(..)
-  , RawSelection(..)
-  , Fragment(..)
-  , FragmentLib
-  , RawArguments
-  , RawSelectionSet
-  , Selection (..)
-  ) where
-
-import           Language.Haskell.TH.Syntax                 (Lift (..))
-
--- MORPHEUS
-import           Data.Morpheus.Types.Internal.AST.Selection (Argument (..), Selection (..))
-import           Data.Morpheus.Types.Internal.Base          (Collection, Key, Position, Reference (..))
-import           Data.Morpheus.Types.Internal.TH            (apply, liftMaybeText, liftText, liftTextMap)
-
-data Fragment = Fragment
-  { fragmentType      :: Key
-  , fragmentPosition  :: Position
-  , fragmentSelection :: RawSelectionSet
-  } deriving (Show)
-
-instance Lift Fragment where
-  lift (Fragment t p sel) = apply 'Fragment [liftText t, lift p, liftTextMap sel]
-
-type RawSelection' a = Selection RawArguments a
-
-instance Lift a => Lift (RawSelection' a) where
-  lift (Selection t p alias sel) = apply 'Selection [liftTextMap t, lift p, liftMaybeText alias , lift sel]
-
-type FragmentLib = [(Key, Fragment)]
-
-data RawArgument
-  = VariableReference Reference
-  | RawArgument Argument
-  deriving (Show, Lift)
-
-type RawArguments = Collection RawArgument
-
-type RawSelectionSet = Collection RawSelection
-
-instance Lift RawSelection where
-  lift (RawSelectionSet (Selection t p alias sel)) =
-    apply 'RawSelectionSet [apply 'Selection [liftTextMap t, lift p, liftMaybeText alias,liftTextMap sel]]
-  lift (RawSelectionField p) = apply 'RawSelectionField [lift p]
-  lift (InlineFragment f) = apply 'InlineFragment [lift f]
-  lift (Spread f) = apply 'Spread [lift f]
-
-data RawSelection
-  = RawSelectionSet (RawSelection' RawSelectionSet)
-  | RawSelectionField (RawSelection' ())
-  | InlineFragment Fragment
-  | Spread Reference
-  deriving (Show)
diff --git a/src/Data/Morpheus/Types/Internal/AST/Selection.hs b/src/Data/Morpheus/Types/Internal/AST/Selection.hs
--- a/src/Data/Morpheus/Types/Internal/AST/Selection.hs
+++ b/src/Data/Morpheus/Types/Internal/AST/Selection.hs
@@ -5,26 +5,63 @@
   , Arguments
   , SelectionSet
   , SelectionRec(..)
-  , ArgumentOrigin(..)
+  , ValueOrigin(..)
   , ValidSelection
   , Selection(..)
-  ) where
+  , RawSelection'
+  , FragmentLib
+  , RawArguments
+  , RawSelectionSet
+  , Fragment(..)
+  , RawArgument(..)
+  , RawSelection(..)
+  )
+where
 
-import           Data.Morpheus.Types.Internal.Base  (Collection, Key, Position)
-import           Data.Morpheus.Types.Internal.Value (Value)
-import           Language.Haskell.TH.Syntax         (Lift (..))
+import           Language.Haskell.TH.Syntax     ( Lift )
 
-data ArgumentOrigin
-  = VARIABLE
-  | INLINE
-  deriving (Show, Lift)
 
-data Argument = Argument
-  { argumentValue    :: Value
-  , argumentOrigin   :: ArgumentOrigin
-  , argumentPosition :: Position
+-- MORPHEUS
+import           Data.Morpheus.Types.Internal.AST.Base
+                                                ( Collection
+                                                , Key
+                                                , Position
+                                                , Ref(..)
+                                                )
+
+import           Data.Morpheus.Types.Internal.AST.Value
+                                                ( Value )
+
+
+-- RAW SELECTION
+
+type RawSelection' a = Selection RawArguments a
+
+type FragmentLib = [(Key, Fragment)]
+
+type RawArguments = Collection RawArgument
+
+type RawSelectionSet = Collection RawSelection
+
+data Fragment = Fragment
+  { fragmentType      :: Key
+  , fragmentPosition  :: Position
+  , fragmentSelection :: RawSelectionSet
   } deriving (Show, Lift)
 
+data RawArgument
+  = VariableRef Ref
+  | RawArgument Argument
+  deriving (Show, Lift)
+
+data RawSelection
+  = RawSelectionSet (RawSelection' RawSelectionSet)
+  | RawSelectionField (RawSelection' ())
+  | InlineFragment Fragment
+  | Spread Ref
+  deriving (Show,Lift)
+
+-- VALID SELECTION 
 type Arguments = Collection Argument
 
 type SelectionSet = Collection ValidSelection
@@ -33,12 +70,23 @@
 
 type UnionSelection = Collection SelectionSet
 
+data ValueOrigin
+  = VARIABLE
+  | INLINE
+  deriving (Show, Lift)
+
+data Argument = Argument
+  { argumentValue    :: Value
+  , argumentOrigin   :: ValueOrigin
+  , argumentPosition :: Position
+  } deriving (Show, Lift)
+
 data Selection args rec = Selection
   { selectionArguments :: args
   , selectionPosition  :: Position
   , selectionAlias     :: Maybe Key
   , selectionRec       :: rec
-  } deriving (Show)
+  } deriving (Show,Lift)
 
 data SelectionRec
   = SelectionSet SelectionSet
diff --git a/src/Data/Morpheus/Types/Internal/AST/Value.hs b/src/Data/Morpheus/Types/Internal/AST/Value.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Morpheus/Types/Internal/AST/Value.hs
@@ -0,0 +1,156 @@
+{-# LANGUAGE DeriveGeneric       #-}
+{-# LANGUAGE DeriveLift          #-}
+{-# LANGUAGE FlexibleInstances   #-}
+{-# LANGUAGE OverloadedStrings   #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+module Data.Morpheus.Types.Internal.AST.Value
+  ( Value(..)
+  , ScalarValue(..)
+  , Object
+  , GQLValue(..)
+  , replaceValue
+  , decodeScientific
+  , convertToJSONName
+  , convertToHaskellName
+  )
+where
+
+import qualified Data.Aeson                    as A
+                                                ( FromJSON(..)
+                                                , ToJSON(..)
+                                                , Value(..)
+                                                , object
+                                                , pairs
+                                                , (.=)
+                                                )
+import qualified Data.HashMap.Strict           as M
+                                                ( toList )
+import           Data.Scientific                ( Scientific
+                                                , floatingOrInteger
+                                                )
+import           Data.Semigroup                 ( (<>) )
+import           Data.Text                      ( Text )
+import qualified Data.Text                     as T
+import qualified Data.Vector                   as V
+                                                ( toList )
+import           GHC.Generics                   ( Generic )
+import           Instances.TH.Lift              ( )
+import           Language.Haskell.TH.Syntax     ( Lift )
+
+
+isReserved :: Text -> Bool
+isReserved "case"     = True
+isReserved "class"    = True
+isReserved "data"     = True
+isReserved "default"  = True
+isReserved "deriving" = True
+isReserved "do"       = True
+isReserved "else"     = True
+isReserved "foreign"  = True
+isReserved "if"       = True
+isReserved "import"   = True
+isReserved "in"       = True
+isReserved "infix"    = True
+isReserved "infixl"   = True
+isReserved "infixr"   = True
+isReserved "instance" = True
+isReserved "let"      = True
+isReserved "module"   = True
+isReserved "newtype"  = True
+isReserved "of"       = True
+isReserved "then"     = True
+isReserved "type"     = True
+isReserved "where"    = True
+isReserved "_"        = True
+isReserved _          = False
+
+{-# INLINE isReserved #-}
+convertToJSONName :: Text -> Text
+convertToJSONName hsName
+  | not (T.null hsName) && isReserved name && (T.last hsName == '\'') = name
+  | otherwise = hsName
+  where name = T.init hsName
+
+convertToHaskellName :: Text -> Text
+convertToHaskellName name | isReserved name = name <> "'"
+                          | otherwise       = name
+
+-- | Primitive Values for GQLScalar: 'Int', 'Float', 'String', 'Boolean'.
+-- for performance reason type 'Text' represents GraphQl 'String' value
+data ScalarValue
+  = Int Int
+  | Float Float
+  | String Text
+  | Boolean Bool
+  deriving (Show, Generic,Lift)
+
+
+instance A.ToJSON ScalarValue where
+  toJSON (Float   x) = A.toJSON x
+  toJSON (Int     x) = A.toJSON x
+  toJSON (Boolean x) = A.toJSON x
+  toJSON (String  x) = A.toJSON x
+
+instance A.FromJSON ScalarValue where
+  parseJSON (A.Bool   v) = pure $ Boolean v
+  parseJSON (A.Number v) = pure $ decodeScientific v
+  parseJSON (A.String v) = pure $ String v
+  parseJSON notScalar    = fail $ "Expected Scalar got :" <> show notScalar
+
+
+type Object = [(Text, Value)]
+
+data Value
+  = Object Object
+  | List [Value]
+  | Enum Text
+  | Scalar ScalarValue
+  | Null
+  deriving (Show, Generic,Lift)
+
+instance A.ToJSON Value where
+  toEncoding Null        = A.toEncoding A.Null
+  toEncoding (Enum   x ) = A.toEncoding x
+  toEncoding (List   x ) = A.toEncoding x
+  toEncoding (Scalar x ) = A.toEncoding x
+  toEncoding (Object []) = A.toEncoding $ A.object []
+  toEncoding (Object x ) = A.pairs $ foldl1 (<>) $ map encodeField x
+    where encodeField (key, value) = convertToJSONName key A..= value
+
+decodeScientific :: Scientific -> ScalarValue
+decodeScientific v = case floatingOrInteger v of
+  Left  float -> Float float
+  Right int   -> Int int
+
+replaceValue :: A.Value -> Value
+replaceValue (A.Bool   v) = gqlBoolean v
+replaceValue (A.Number v) = Scalar $ decodeScientific v
+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
diff --git a/src/Data/Morpheus/Types/Internal/Base.hs b/src/Data/Morpheus/Types/Internal/Base.hs
deleted file mode 100644
--- a/src/Data/Morpheus/Types/Internal/Base.hs
+++ /dev/null
@@ -1,58 +0,0 @@
-{-# LANGUAGE DeriveAnyClass  #-}
-{-# LANGUAGE DeriveGeneric   #-}
-{-# LANGUAGE DeriveLift      #-}
-{-# LANGUAGE TemplateHaskell #-}
-
-module Data.Morpheus.Types.Internal.Base
-  ( Key
-  , Collection
-  , Reference (..)
-  , Position
-  , EnhancedKey(..)
-  , Location(..)
-  , Message
-  , enhanceKeyWithNull
-  ) where
-
-import           Data.Aeson                      (FromJSON, ToJSON)
-import           Data.Text                       (Text)
-import           GHC.Generics                    (Generic)
-import           Language.Haskell.TH.Syntax      (Lift (..))
-
--- MORPHEUS
-import           Data.Morpheus.Types.Internal.TH (apply, liftText)
-
-type Position = Location
-
-data Location = Location
-  { line   :: Int
-  , column :: Int
-  } deriving (Show, Generic, FromJSON, ToJSON, Lift)
-
-type Key = Text
-type Message = Text
-
-type Collection a = [(Key, a)]
-
-data Reference = Reference
-  { referenceName     :: Key
-  , referencePosition :: Position
-  } deriving (Show)
-
-instance Lift Reference where
-  lift (Reference name pos) = apply 'Reference [liftText name, lift pos]
-
--- Text value that includes position for debugging, where EnhancedKey "a" 1 === EnhancedKey "a" 3
-data EnhancedKey = EnhancedKey
-  { uid      :: Text
-  , location :: Position
-  } deriving (Show)
-
-instance Eq EnhancedKey where
-  (EnhancedKey id1 _) == (EnhancedKey id2 _) = id1 == id2
-
-instance Ord EnhancedKey where
-  compare (EnhancedKey x _) (EnhancedKey y _) = compare x y
-
-enhanceKeyWithNull :: Key -> EnhancedKey
-enhanceKeyWithNull text = EnhancedKey {uid = text, location = Location 0 0}
diff --git a/src/Data/Morpheus/Types/Internal/Data.hs b/src/Data/Morpheus/Types/Internal/Data.hs
deleted file mode 100644
--- a/src/Data/Morpheus/Types/Internal/Data.hs
+++ /dev/null
@@ -1,338 +0,0 @@
-{-# 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
-  , DataArgument
-  , DataUnion
-  , DataArguments
-  , DataField(..)
-  , DataTyCon(..)
-  , DataType(..)
-  , DataTypeLib(..)
-  , DataTypeWrapper(..)
-  , DataValidator(..)
-  , DataTypeKind(..)
-  , DataFingerprint(..)
-  , RawDataType(..)
-  , ResolverKind(..)
-  , WrapperD(..)
-  , TypeAlias(..)
-  , ArgsType(..)
-  , isTypeDefined
-  , initTypeLib
-  , defineType
-  , isFieldNullable
-  , allDataTypes
-  , lookupDataType
-  , kindOf
-  , toNullableField
-  , toListField
-  , isObject
-  , isInput
-  , toHSWrappers
-  , isNullable
-  , toGQLWrapper
-  , isWeaker
-  , isSubscription
-  , isOutputObject
-  , sysTypes
-  , isDefaultTypeName
-  , isSchemaTypeName
-  , isPrimitiveTypeName
-  , OperationType(..)
-  , QUERY
-  , MUTATION
-  , SUBSCRIPTION
-  , Name
-  , Description
-  , isEntNode
-  ) where
-
-import           Data.Semigroup                     ((<>))
-import qualified Data.Text                          as T (pack, unpack)
-import           GHC.Fingerprint.Type               (Fingerprint)
-import           Language.Haskell.TH.Syntax         (Lift (..))
-
--- MORPHEUS
-import           Data.Morpheus.Types.Internal.Base  (Key)
-import           Data.Morpheus.Types.Internal.TH    (apply, liftText, liftTextMap)
-import           Data.Morpheus.Types.Internal.Value (Value (..))
-
-type Name = Key
-type Description = Key
-
-type QUERY = 'Query
-type MUTATION = 'Mutation
-type SUBSCRIPTION = 'Subscription
-
-isDefaultTypeName :: Key -> Bool
-isDefaultTypeName x = isSchemaTypeName x || isPrimitiveTypeName x
-
-isSchemaTypeName :: Key -> Bool
-isSchemaTypeName = (`elem` sysTypes)
-
-isPrimitiveTypeName :: Key -> Bool
-isPrimitiveTypeName = (`elem` ["String", "Float", "Int", "Boolean", "ID"])
-
-sysTypes :: [Key]
-sysTypes =
-  ["__Schema", "__Type", "__Directive", "__TypeKind", "__Field", "__DirectiveLocation", "__InputValue", "__EnumValue"]
-
-data OperationType
-  = 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 (Maybe OperationType)
-  | KindUnion
-  | KindEnum
-  | KindInputObject
-  | KindList
-  | KindNonNull
-  | 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 Key
-  | TypeableFingerprint [Fingerprint]
-  deriving (Show, Eq, Ord)
-
-newtype DataValidator = DataValidator
-  { validateValue :: Value -> Either Key Value
-  }
-
-instance Show DataValidator where
-  show _ = "DataValidator"
-
-type DataScalar = DataTyCon DataValidator
-
-type DataEnum = DataTyCon [Key]
-
-type DataObject = DataTyCon [(Key, DataField)]
-
-type DataArgument = DataField
-
-type DataUnion = DataTyCon [DataField]
-
-type DataArguments = [(Key, DataArgument)]
-
-data DataTypeWrapper
-  = ListType
-  | NonNullType
-  deriving (Show, Lift)
-
-data TypeAlias = TypeAlias
-  { aliasTyCon    :: Key
-  , aliasArgs     :: Maybe Key
-  , aliasWrappers :: [WrapperD]
-  } deriving (Show)
-
-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 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 :: Maybe Key
-  , typeData        :: a
-  } deriving (Show)
-
-data RawDataType
-  = FinalDataType DataType
-  | Interface DataObject
-  | Implements { implementsInterfaces :: [Key]
-               , unImplements         :: DataObject }
-  deriving (Show)
-
-isEntNode :: DataType -> Bool
-isEntNode DataScalar {} = True
-isEntNode DataEnum {}   = True
-isEntNode _             = False
-
-data DataType
-  = DataScalar DataScalar
-  | DataEnum DataEnum
-  | DataInputObject DataObject
-  | DataObject DataObject
-  | DataUnion DataUnion
-  | DataInputUnion DataUnion
-  deriving (Show)
-
-data DataTypeLib = DataTypeLib
-  { scalar       :: [(Key, DataScalar)]
-  , enum         :: [(Key, DataEnum)]
-  , 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)
-
-initTypeLib :: (Key, DataObject) -> DataTypeLib
-initTypeLib query =
-  DataTypeLib
-    { scalar = []
-    , enum = []
-    , inputObject = []
-    , query = query
-    , object = []
-    , union = []
-    , inputUnion = []
-    , mutation = Nothing
-    , subscription = Nothing
-    }
-
-allDataTypes :: DataTypeLib -> [(Key, DataType)]
-allDataTypes DataTypeLib { scalar, enum , inputObject, object, union, inputUnion, query, mutation, subscription } =
-  packType DataObject query :
-  fromMaybeType mutation ++
-  fromMaybeType subscription ++
-  map (packType DataScalar) scalar ++
-  map (packType DataEnum) enum ++
-  map (packType DataInputObject) inputObject ++
-  map (packType DataInputUnion) inputUnion ++ map (packType DataObject) object ++ map (packType DataUnion) union
-  where
-    packType f (x, y) = (x, f y)
-    fromMaybeType :: Maybe (Key, DataObject) -> [(Key, DataType)]
-    fromMaybeType (Just (key', dataType')) = [(key', DataObject dataType')]
-    fromMaybeType Nothing                  = []
-
-lookupDataType :: Key -> DataTypeLib -> Maybe DataType
-lookupDataType name lib = name `lookup` allDataTypes lib
-
-kindOf :: DataType -> DataTypeKind
-kindOf (DataScalar _)      = KindScalar
-kindOf (DataEnum _)        = KindEnum
-kindOf (DataInputObject _) = KindInputObject
-kindOf (DataObject _)      = KindObject Nothing
-kindOf (DataUnion _)       = KindUnion
-kindOf (DataInputUnion _)  = KindInputUnion
-
-fromDataType :: (DataTyCon () -> v) -> DataType -> v
-fromDataType f (DataScalar dt)      = f dt {typeData = ()}
-fromDataType f (DataEnum dt)        = f dt {typeData = ()}
-fromDataType f (DataUnion dt)       = f dt {typeData = ()}
-fromDataType f (DataInputObject dt) = f dt {typeData = ()}
-fromDataType f (DataInputUnion dt)  = f dt {typeData = ()}
-fromDataType f (DataObject dt)      = f dt {typeData = ()}
-
-isTypeDefined :: Key -> DataTypeLib -> Maybe DataFingerprint
-isTypeDefined name lib = fromDataType typeFingerprint <$> lookupDataType name lib
-
-defineType :: (Key, DataType) -> DataTypeLib -> DataTypeLib
-defineType (key', DataScalar type') lib      = lib {scalar = (key', type') : scalar lib}
-defineType (key', DataEnum type') lib        = lib {enum = (key', type') : enum lib}
-defineType (key', DataInputObject type') lib = lib {inputObject = (key', type') : inputObject lib}
-defineType (key', DataObject type') lib      = lib {object = (key', type') : object lib}
-defineType (key', DataUnion type') lib       = lib {union = (key', type') : union lib}
-defineType (key', DataInputUnion 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
deleted file mode 100644
--- a/src/Data/Morpheus/Types/Internal/DataD.hs
+++ /dev/null
@@ -1,37 +0,0 @@
-{-# LANGUAGE DeriveLift #-}
-
-module Data.Morpheus.Types.Internal.DataD
-  ( TypeD(..)
-  , ConsD(..)
-  , QueryD(..)
-  , GQLTypeD(..)
-  ) where
-
-import           Language.Haskell.TH.Syntax        (Lift (..))
-
---
--- MORPHEUS
-import           Data.Morpheus.Types.Internal.Data (DataField, DataTypeKind)
-
-data QueryD = QueryD
-  { queryText     :: String
-  , queryTypes    :: [GQLTypeD]
-  , queryArgsType :: Maybe TypeD
-  } deriving (Show, Lift)
-
-data GQLTypeD = GQLTypeD
-  { typeD     :: TypeD
-  , typeKindD :: DataTypeKind
-  , typeArgD  :: [TypeD]
-  } deriving (Show, Lift)
-
-data TypeD = TypeD
-  { tName      :: String
-  , tNamespace :: [String]
-  , tCons      :: [ConsD]
-  } deriving (Show, Lift)
-
-data ConsD = ConsD
-  { cName   :: String
-  , cFields :: [DataField]
-  } deriving (Show, Lift)
diff --git a/src/Data/Morpheus/Types/Internal/Resolver.hs b/src/Data/Morpheus/Types/Internal/Resolver.hs
deleted file mode 100644
--- a/src/Data/Morpheus/Types/Internal/Resolver.hs
+++ /dev/null
@@ -1,263 +0,0 @@
-{-# LANGUAGE DataKinds             #-}
-{-# LANGUAGE FlexibleContexts      #-}
-{-# LANGUAGE FlexibleInstances     #-}
-{-# LANGUAGE GADTs                 #-}
-{-# LANGUAGE InstanceSigs          #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE NamedFieldPuns        #-}
-{-# LANGUAGE OverloadedStrings     #-}
-{-# LANGUAGE PolyKinds             #-}
-{-# LANGUAGE ScopedTypeVariables   #-}
-{-# LANGUAGE TupleSections         #-}
-{-# LANGUAGE TypeFamilies          #-}
-{-# LANGUAGE TypeOperators         #-}
-
-module Data.Morpheus.Types.Internal.Resolver
-  ( ResolveT
-  , Event(..)
-  , GQLRootResolver(..)
-  , UnSubResolver
-  , ResponseT
-  , Resolver(..)
-  , ResolvingStrategy(..)
-  , MapGraphQLT(..)
-  , PureOperation(..)
-  , resolveObject
-  , toResponseRes
-  , withObject
-  , Resolving(..)
-  , liftM
-  , liftEitherM
-  ) where
-
-import           Control.Monad.Fail                         (MonadFail (..))
-import           Control.Monad.Trans.Except                 (ExceptT (..), runExceptT, withExceptT)
-import           Data.Maybe                                 (fromMaybe)
-import           Data.Semigroup                             ((<>))
-
--- MORPHEUS
-import           Data.Morpheus.Error.Selection              (resolverError, subfieldsNotSelected)
-import           Data.Morpheus.Types.Internal.AST.Selection (Selection (..), SelectionRec (..), SelectionSet,
-                                                             ValidSelection)
-import           Data.Morpheus.Types.Internal.Data          (Key, MUTATION, OperationType, QUERY, SUBSCRIPTION)
-import           Data.Morpheus.Types.Internal.Stream        (Channel (..), Event (..), ResponseEvent (..),
-                                                             ResponseStream, StreamChannel, StreamState (..),
-                                                             StreamT (..), closeStream, injectEvents, mapS, pushEvents)
-import           Data.Morpheus.Types.Internal.Validation    (GQLErrors, Validation)
-import           Data.Morpheus.Types.Internal.Value         (GQLValue (..), Value)
-import           Data.Morpheus.Types.IO                     (renderResponse)
-
-withObject :: ( SelectionSet -> ResolvingStrategy o m e value) -> (Key,ValidSelection)  -> ResolvingStrategy o m e value
-withObject f (_, Selection {selectionRec = SelectionSet selection}) = f selection
-withObject _ (key, Selection {selectionPosition}) = Fail $ subfieldsNotSelected key "" selectionPosition
-
-liftM :: (PureOperation o, Monad m) => m a -> Resolver o m e a
-liftM = liftEither . fmap pure
-
-liftEitherM :: (PureOperation o, Monad m) => m (Either String a) -> Resolver o m e a
-liftEitherM = liftEither
-----------------------------------------------------------------------------------------
-type ResolveT = ExceptT GQLErrors
-type ResponseT m e  = ResolveT (ResponseStream m e)
-
-instance Monad m => MonadFail (Resolver QUERY m e) where
-  fail = FailedResolver
-
---
--- Recursive Resolver
-newtype RecResolver m a b = RecResolver {
-  unRecResolver :: a -> ResolveT m b
-}
-
-instance Functor m => Functor (RecResolver m a) where
-  fmap f (RecResolver x) = RecResolver eventFmap
-    where
-      eventFmap  event = fmap f (x event)
-
-instance Monad m => Applicative (RecResolver m a) where
-  pure = RecResolver . const . pure
-  (RecResolver f) <*> (RecResolver res) = RecResolver recX
-    where
-      recX event = f event <*>  res event
-
-instance Monad m => Monad (RecResolver m a) where
-  (RecResolver x) >>= next = RecResolver recX
-    where
-        recX event = x event >>= (\v-> v event) . unRecResolver . next
-------------------------------------------------------------
---
---- GraphQLT
-
-data ResolvingStrategy  (o::OperationType) (m:: * -> *) event value where
-    QueryResolving :: { unQueryT :: ResolveT m value } -> ResolvingStrategy QUERY m event value
-    MutationResolving :: { unMutationT :: ResolveT (StreamT m event) value } -> ResolvingStrategy MUTATION m event value
-    SubscriptionResolving :: { unSubscriptionT :: ResolveT (StreamT m (Channel event)) (RecResolver m event value) } -> ResolvingStrategy SUBSCRIPTION m event value
-    -- SubscriptionRecT :: RecResolver m event value -> GraphQLT SUBSCRIPTION m event value
-    Fail :: GQLErrors -> ResolvingStrategy o m event  value
-
--- GraphQLT Functor
-instance Monad m => Functor (ResolvingStrategy o m e) where
-    fmap _ (Fail mErrors)                    = Fail mErrors
-    fmap f (QueryResolving mResolver)        = QueryResolving $ f <$> mResolver
-    fmap f (MutationResolving mResolver)     = MutationResolving $  f <$> mResolver
-    fmap f (SubscriptionResolving mResolver) = SubscriptionResolving $ fmap f <$> mResolver
-
--- GraphQLT Applicative
-instance (PureOperation o, Monad m) => Applicative (ResolvingStrategy o m e) where
-    pure = pureGraphQLT
-    -------------------------------------
-    _ <*> (Fail mErrors) = Fail mErrors
-    (Fail mErrors) <*> _ = Fail mErrors
-    -------------------------------------
-    (QueryResolving f) <*> (QueryResolving res) = QueryResolving (f <*> res)
-    ------------------------------------------------------------------------
-    (MutationResolving f) <*> (MutationResolving res) = MutationResolving (f <*> res)
-    --------------------------------------------------------------
-    (SubscriptionResolving f) <*> (SubscriptionResolving res) = SubscriptionResolving $ do
-                       f1 <- f
-                       res1 <- res
-                       pure (f1 <*> res1)
-
--- GADTResolver
----------------------------------------------------------------
-data Resolver (o::OperationType) (m :: * -> * ) event value where
-    FailedResolver :: { unFailedResolver :: String } -> Resolver o m event value
-    QueryResolver:: { unQueryResolver :: ExceptT String m value } -> Resolver QUERY m  event value
-    MutResolver :: {
-            mutEvents :: [event] ,
-            mutResolver :: ExceptT String m value
-        } -> Resolver MUTATION m event value
-    SubResolver :: {
-            subChannels :: [StreamChannel event] ,
-            subResolver :: event -> Resolver QUERY m  event value
-        } -> Resolver SUBSCRIPTION m event value
-
--- GADTResolver Functor
-instance Functor m => Functor (Resolver o m e) where
-    fmap _ (FailedResolver mErrors) = FailedResolver mErrors
-    fmap f (QueryResolver mResolver) = QueryResolver $ fmap f mResolver
-    fmap f (MutResolver events mResolver) = MutResolver events $ fmap f mResolver
-    fmap f (SubResolver events mResolver) = SubResolver events (eventFmap mResolver)
-            where
-                eventFmap res event = fmap f (res event)
-
--- GADTResolver Applicative
-instance (PureOperation o ,Monad m) => Applicative (Resolver o m e) where
-    pure = liftEither . pure . pure
-    -------------------------------------
-    _ <*> (FailedResolver mErrors) = FailedResolver mErrors
-    (FailedResolver mErrors) <*> _ = FailedResolver mErrors
-    -------------------------------------
-    (QueryResolver f) <*> (QueryResolver res) = QueryResolver (f <*> res)
-    ---------------------------------------------------------------------
-    (MutResolver events1 f) <*> (MutResolver events2 res) = MutResolver (events1 <> events2) (f <*> res)
-    --------------------------------------------------------------
-    (SubResolver e1 f) <*> (SubResolver e2 res) = SubResolver (e1<>e2) $
-                       \event -> f event <*>  res event
-
-instance (Monad m) => Monad (Resolver QUERY m e) where
-    return = pure
-    -------------------------------------
-    (FailedResolver mErrors) >>= _ = FailedResolver mErrors
-    -------------------------------------
-    (QueryResolver f) >>= nextM = QueryResolver (f >>= unQueryResolver. nextM)
-
--- Pure Operation
-class PureOperation (o::OperationType) where
-    liftEither :: Monad m => m (Either String a) -> Resolver o m event a
-    pureGraphQLT :: Monad m => a -> ResolvingStrategy o m event a
-    eitherGraphQLT :: Monad m => Validation a -> ResolvingStrategy o m event a
-
-instance PureOperation QUERY where
-   liftEither = QueryResolver . ExceptT
-   pureGraphQLT = QueryResolving . pure
-   eitherGraphQLT = QueryResolving . ExceptT . pure
-
-instance PureOperation MUTATION where
-   liftEither = MutResolver [] . ExceptT
-   pureGraphQLT = MutationResolving . pure
-   eitherGraphQLT = MutationResolving . ExceptT . pure
-
-instance PureOperation SUBSCRIPTION where
-   liftEither = SubResolver [] . const . liftEither
-   pureGraphQLT = SubscriptionResolving . pure . pure
-   eitherGraphQLT = SubscriptionResolving . fmap pure  . ExceptT . pure
-
-
-resolveObject :: (Monad m , PureOperation o ) => SelectionSet -> [FieldRes o m e] -> ResolvingStrategy o m e Value
-resolveObject selectionSet fieldResolvers = gqlObject <$> traverse selectResolver selectionSet
-  where
-    selectResolver (key, selection@Selection { selectionAlias }) = (fromMaybe key selectionAlias,) <$> lookupRes selection
-      where
-        lookupRes  sel =  (fromMaybe (const $ pure  gqlNull) $ lookup key fieldResolvers) (key, sel)
-
-class Resolving o m e where
-     getArgs :: Validation args ->  (args -> Resolver o m e value) -> Resolver o m e value
-     resolving :: Monad m => (value -> (Key,ValidSelection) -> ResolvingStrategy o m e Value) -> Resolver o m e value ->  (Key, ValidSelection) -> ResolvingStrategy o m e Value
-
-type FieldRes o m e = (Key, (Key, ValidSelection) -> ResolvingStrategy o m e Value)
-
-instance Resolving o m e where
-   getArgs (Right x) f = f x
-   getArgs (Left _) _  = FailedResolver ""
-   ---------------------------------------------------------------------------------------------------------------------------------------
-   resolving encode gResolver selection@(fieldName,Selection { selectionPosition }) = __resolving gResolver
-        where
-          __resolving (FailedResolver message) = Fail $ resolverError selectionPosition fieldName message
-          __resolving (QueryResolver res) =
-            QueryResolving $ withExceptT (resolverError selectionPosition fieldName) res >>= unQueryT . (`encode` selection)
-   ---------------------------------------------------------------------------------------------------------------------------------------
-          __resolving (MutResolver events res)  =
-            MutationResolving $ pushEvents events $ withExceptT (resolverError selectionPosition fieldName) (injectEvents [] res)  >>= unMutationT . (`encode` selection)
-   --------------------------------------------------------------------------------------------------------------------------------
-          __resolving (SubResolver subChannels res) =
-               SubscriptionResolving $ ExceptT $ StreamT $ pure $ StreamState { streamEvents , streamValue }
-                              where
-                                streamValue  = pure $ RecResolver $ \event -> withExceptT (resolverError selectionPosition fieldName) ( unQueryResolver $ res event)  >>= unPub event . (`encode` selection)
-                                streamEvents :: [Channel e]
-                                streamEvents = map Channel subChannels
-
-unPub :: Monad m => event -> ResolvingStrategy SUBSCRIPTION m event a -> ResolveT m a
-unPub event x = do
-    func <- unPureSub x
-    func event
-
-unPureSub :: Monad m => ResolvingStrategy SUBSCRIPTION m event a -> ResolveT m (event -> ResolveT m a)
-unPureSub = ExceptT . fmap (fmap unRecResolver . streamValue) . runStreamT . runExceptT . unSubscriptionT
-
-class MapGraphQLT (fromO :: OperationType) (toO :: OperationType) where
-   mapGraphQLT :: Monad m => ResolvingStrategy fromO m e a -> ResolvingStrategy toO m e a
-
-instance MapGraphQLT fromO fromO where
-    mapGraphQLT = id
-
-instance MapGraphQLT QUERY SUBSCRIPTION where
-    mapGraphQLT (QueryResolving x) = SubscriptionResolving $ injectEvents [] (fmap pure x)
-    mapGraphQLT (Fail x)           = Fail x
-
-toResponseRes :: Monad m =>  ResolvingStrategy o m event Value -> ResponseT m event Value
-toResponseRes (Fail errors) = ExceptT $ StreamT $ pure $ StreamState [] $ Left errors
-toResponseRes (QueryResolving resT) =  ExceptT $ StreamT $ StreamState [] <$> runExceptT resT
-toResponseRes (MutationResolving resT) = ExceptT $ mapS Publish (runExceptT resT)
-toResponseRes (SubscriptionResolving resT)  =
-      ExceptT $ StreamT $ handleActions <$> closeStream (runExceptT resT)
-      where
-        handleActions (_, Left gqlError) = StreamState [] (Left gqlError)
-        handleActions (channels, Right subResolver) =
-          StreamState [Subscribe $ Event channels handleRes] (Right  gqlNull)
-          where
-            handleRes event = renderResponse <$> runExceptT (unRecResolver subResolver event)
-
-type family UnSubResolver (a :: * -> *) :: (* -> *)
-
-type instance UnSubResolver (Resolver SUBSCRIPTION m e) = Resolver QUERY m e
-
--------------------------------------------------------------------
--- | GraphQL Root resolver, also the interpreter generates a GQL schema from it.
---  '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 :: * -> *) event (query :: (* -> *) -> * ) (mut :: (* -> *) -> * )  (sub :: (* -> *) -> * )  = GQLRootResolver
-  { queryResolver        :: query (Resolver QUERY m  event)
-  , mutationResolver     :: mut (Resolver MUTATION m event)
-  , subscriptionResolver :: sub (Resolver SUBSCRIPTION  m event)
-  }
diff --git a/src/Data/Morpheus/Types/Internal/Resolving.hs b/src/Data/Morpheus/Types/Internal/Resolving.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Morpheus/Types/Internal/Resolving.hs
@@ -0,0 +1,34 @@
+module Data.Morpheus.Types.Internal.Resolving
+    ( Event(..)
+    , GQLRootResolver(..)
+    , UnSubResolver
+    , Resolver(..)
+    , ResolvingStrategy(..)
+    , MapStrategy(..)
+    , LiftEither(..)
+    , resolveObject
+    , toResponseRes
+    , withObject
+    , resolving
+    , toResolver
+    , lift
+    , SubEvent
+    , Validation
+    , Failure(..)
+    , GQLChannel(..)
+    , ResponseEvent(..)
+    , ResponseStream
+    , cleanEvents
+    , Result(..)
+    , ResultT(..)
+    , unpackEvents
+    , LibUpdater
+    , resolveUpdates
+    , GQLErrors
+    , GQLError(..)
+    , Position
+    )
+where
+
+import           Data.Morpheus.Types.Internal.Resolving.Resolver
+import           Data.Morpheus.Types.Internal.Resolving.Core
diff --git a/src/Data/Morpheus/Types/Internal/Resolving/Core.hs b/src/Data/Morpheus/Types/Internal/Resolving/Core.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Morpheus/Types/Internal/Resolving/Core.hs
@@ -0,0 +1,160 @@
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE DeriveFunctor      #-}
+{-# LANGUAGE DeriveAnyClass     #-}
+{-# LANGUAGE DeriveGeneric      #-}
+{-# LANGUAGE DataKinds          #-}
+{-# LANGUAGE PolyKinds          #-}
+{-# LANGUAGE NamedFieldPuns     #-}
+
+module Data.Morpheus.Types.Internal.Resolving.Core
+  ( GQLError(..)
+  , Position(..)
+  , GQLErrors
+  , Validation
+  , Result(..)
+  , Failure(..)
+  , ResultT(..)
+  , fromEither
+  , fromEitherSingle
+  , unpackEvents
+  , LibUpdater
+  , resolveUpdates
+  , mapEvent
+  , mapFailure
+  , cleanEvents
+  , StatelessResT
+  )
+where
+
+import           Control.Monad                  ( foldM )
+import           Data.Function                  ( (&) )
+import           Control.Monad.Trans.Class      ( MonadTrans(..) )
+import           Control.Applicative            ( liftA2 )
+import           Data.Aeson                     ( FromJSON
+                                                , ToJSON
+                                                )
+import           Data.Morpheus.Types.Internal.AST.Base
+                                                ( Position(..) )
+import           Data.Text                      ( Text
+                                                , pack
+                                                )
+import           GHC.Generics                   ( Generic )
+import           Data.Semigroup                 ( (<>) )
+
+
+class Applicative f => Failure error (f :: * -> *) where
+  failure :: error -> f v
+
+instance Failure error (Either error) where
+  failure = Left
+
+data GQLError = GQLError
+  { message      :: Text
+  , locations :: [Position]
+  } deriving (Show, Generic, FromJSON, ToJSON)
+
+type GQLErrors = [GQLError]
+
+type StatelessResT = ResultT () GQLError 'True
+type Validation = Result () GQLError 'True
+
+--
+-- Result
+--
+--
+data Result events error (concurency :: Bool)  a =
+  Success { result :: a , warnings :: [error] , events:: [events] }
+  | Failure [error] deriving (Functor)
+
+instance Applicative (Result e cocnurency  error) where
+  pure x = Success x [] []
+  Success f w1 e1 <*> Success x w2 e2 = Success (f x) (w1 <> w2) (e1 <> e2)
+  Failure e1      <*> Failure e2      = Failure (e1 <> e2)
+  Failure e       <*> Success _ w _   = Failure (e <> w)
+  Success _ w _   <*> Failure e       = Failure (e <> w)
+
+instance Monad (Result e  cocnurency error)  where
+  return = pure
+  Success v w1 e1 >>= fm = case fm v of
+    (Success x w2 e2) -> Success x (w1 <> w2) (e1 <> e2)
+    (Failure e      ) -> Failure (e <> w1)
+  Failure e >>= _ = Failure e
+
+instance Failure [error] (Result ev error con) where
+  failure = Failure
+
+unpackEvents :: Result event c e a -> [event]
+unpackEvents Success { events } = events
+unpackEvents _                  = []
+
+fromEither :: Either [er] a -> Result ev er co a
+fromEither (Left  e) = Failure e
+fromEither (Right a) = Success a [] []
+
+fromEitherSingle :: Either er a -> Result ev er co a
+fromEitherSingle (Left  e) = Failure [e]
+fromEitherSingle (Right a) = Success a [] []
+
+-- ResultT
+newtype ResultT event error (concurency :: Bool)  (m :: * -> * ) a = ResultT { runResultT :: m (Result event error concurency a )  }
+  deriving (Functor)
+
+instance Applicative m => Applicative (ResultT event error concurency m) where
+  pure = ResultT . pure . pure
+  ResultT app1 <*> ResultT app2 = ResultT $ liftA2 (<*>) app1 app2
+
+instance Monad m => Monad (ResultT event error concurency m) where
+  return = pure
+  (ResultT m1) >>= mFunc = ResultT $ do
+    result1 <- m1
+    case result1 of
+      Failure errors       -> pure $ Failure errors
+      Success value1 w1 e1 -> do
+        result2 <- runResultT (mFunc value1)
+        case result2 of
+          Failure errors   -> pure $ Failure (errors <> w1)
+          Success v2 w2 e2 -> return $ Success v2 (w1 <> w2) (e1 <> e2)
+
+instance MonadTrans (ResultT event error concurency) where
+  lift = ResultT . fmap pure
+
+instance Applicative m => Failure String (ResultT ev GQLError con m) where
+  failure x =
+    ResultT $ pure $ Failure [GQLError { message = pack x, locations = [] }]
+
+cleanEvents
+  :: Functor m
+  => ResultT e1 error concurency m a
+  -> ResultT e2 error concurency m a
+cleanEvents resT = ResultT $ replace <$> runResultT resT
+ where
+  replace (Success v w _) = Success v w []
+  replace (Failure e    ) = Failure e
+
+mapEvent
+  :: Monad m
+  => (ea -> eb)
+  -> ResultT ea er con m value
+  -> ResultT eb er con m value
+mapEvent func (ResultT ma) = ResultT $ do
+  state <- ma
+  return $ state { events = map func (events state) }
+
+mapFailure
+  :: Monad m
+  => (er1 -> er2)
+  -> ResultT ev er1 con m value
+  -> ResultT ev er2 con m value
+mapFailure f (ResultT ma) = ResultT $ do
+  state <- ma
+  case state of
+    Failure x     -> pure $ Failure (map f x)
+    Success x w e -> pure $ Success x (map f w) e
+
+
+-- Helper Functions
+type LibUpdater lib = lib -> Validation lib
+
+resolveUpdates :: lib -> [LibUpdater lib] -> Validation lib
+resolveUpdates = foldM (&)
diff --git a/src/Data/Morpheus/Types/Internal/Resolving/Resolver.hs b/src/Data/Morpheus/Types/Internal/Resolving/Resolver.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Morpheus/Types/Internal/Resolving/Resolver.hs
@@ -0,0 +1,382 @@
+{-# LANGUAGE DataKinds             #-}
+{-# LANGUAGE FlexibleContexts      #-}
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE GADTs                 #-}
+{-# LANGUAGE InstanceSigs          #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE NamedFieldPuns        #-}
+{-# LANGUAGE OverloadedStrings     #-}
+{-# LANGUAGE PolyKinds             #-}
+{-# LANGUAGE ScopedTypeVariables   #-}
+{-# LANGUAGE TupleSections         #-}
+{-# LANGUAGE TypeFamilies          #-}
+{-# LANGUAGE TypeOperators         #-}
+{-# LANGUAGE UndecidableInstances  #-}
+
+module Data.Morpheus.Types.Internal.Resolving.Resolver
+  ( 
+    Event(..)
+  , GQLRootResolver(..)
+  , UnSubResolver
+  , Resolver(..)
+  , ResolvingStrategy(..)
+  , MapStrategy(..)
+  , LiftEither(..)
+  , resolveObject
+  , toResponseRes
+  , withObject
+  , resolving
+  , toResolver
+  , lift
+  , SubEvent
+  , GQLChannel(..)
+  , ResponseEvent(..)
+  , ResponseStream
+  )
+where
+
+import           Control.Monad.Trans.Class      ( MonadTrans(..) )
+import           Data.Maybe                     ( fromMaybe )
+import           Data.Semigroup                 ( (<>) )
+import           Data.Text                      ( unpack
+                                                , pack
+                                                )
+
+-- MORPHEUS
+import           Data.Morpheus.Error.Selection  ( resolvingFailedError
+                                                , subfieldsNotSelected
+                                                )
+import           Data.Morpheus.Types.Internal.AST.Selection
+                                                ( Selection(..)
+                                                , SelectionRec(..)
+                                                , SelectionSet
+                                                , ValidSelection
+                                                )
+import           Data.Morpheus.Types.Internal.AST.Base
+                                                ( Message , Key )
+import           Data.Morpheus.Types.Internal.AST.Data
+                                                ( 
+                                                  MUTATION
+                                                , OperationType
+                                                , QUERY
+                                                , SUBSCRIPTION
+                                                )
+import           Data.Morpheus.Types.Internal.Resolving.Core
+                                                ( GQLErrors
+                                                , GQLError
+                                                , Validation
+                                                , Result(..)
+                                                , Failure(..)
+                                                , ResultT(..)
+                                                , fromEither
+                                                , fromEitherSingle
+                                                , cleanEvents
+                                                , mapFailure
+                                                , mapEvent
+                                                , StatelessResT
+                                                )
+import           Data.Morpheus.Types.Internal.AST.Value
+                                                ( GQLValue(..)
+                                                , Value
+                                                )
+import           Data.Morpheus.Types.IO         (renderResponse, GQLResponse)
+-- MORPHEUS
+
+class LiftEither (o::OperationType) res where
+  type ResError res :: *
+  liftEither :: Monad m => m (Either (ResError res) a) -> res o event m  a
+
+type ResponseStream event m = ResultT (ResponseEvent m event) GQLError 'True m
+
+data ResponseEvent m event
+  = Publish event
+  | Subscribe (SubEvent m event)
+
+type SubEvent m event = Event (Channel event) (event -> m GQLResponse)
+
+----------------------------------------------------------------------------------------
+-- Recursive Resolver
+newtype RecResolver m a b = RecResolver {
+  unRecResolver :: a -> StatelessResT m b
+}
+
+instance Functor m => Functor (RecResolver m a) where
+  fmap f (RecResolver x) = RecResolver recX where recX event = f <$> x event
+
+instance Monad m => Applicative (RecResolver m a) where
+  pure = RecResolver . const . pure
+  (RecResolver f) <*> (RecResolver res) = RecResolver recX
+    where recX event = f event <*> res event
+
+instance Monad m => Monad (RecResolver m a) where
+  (RecResolver x) >>= next = RecResolver recX
+    where recX event = x event >>= (\v -> v event) . unRecResolver . next
+------------------------------------------------------------
+
+--- GraphQLT
+data ResolvingStrategy  (o::OperationType) event (m:: * -> *) value where
+  ResolveQ ::{ unResolveQ :: ResultT () GQLError 'True m value } -> ResolvingStrategy QUERY event m  value
+  ResolveM ::{ unResolveM :: ResultT event GQLError 'True m value } -> ResolvingStrategy MUTATION event m  value
+  ResolveS ::{ unResolveS :: ResultT (Channel event) GQLError 'True m (RecResolver m event value) } -> ResolvingStrategy SUBSCRIPTION event m value
+
+-- Functor
+instance Monad m => Functor (ResolvingStrategy o e m) where
+  fmap f (ResolveQ res) = ResolveQ $ f <$> res
+  fmap f (ResolveM res) = ResolveM $ f <$> res
+  fmap f (ResolveS res) = ResolveS $ (<$>) f <$> res
+
+-- Applicative
+instance (LiftEither o ResolvingStrategy, Monad m) => Applicative (ResolvingStrategy o e m) where
+  pure = liftEither . pure . pure
+  -------------------------------------
+  (ResolveQ f) <*> (ResolveQ res) = ResolveQ (f <*> res)
+  ------------------------------------------------------------------------
+  (ResolveM f) <*> (ResolveM res) = ResolveM (f <*> res)
+  --------------------------------------------------------------
+  (ResolveS f) <*> (ResolveS res) = ResolveS $ (<*>) <$> f <*> res
+
+-- LiftEither
+instance LiftEither QUERY ResolvingStrategy where
+  type ResError ResolvingStrategy = GQLErrors
+  liftEither = ResolveQ . ResultT . fmap fromEither
+
+instance LiftEither MUTATION ResolvingStrategy where
+  type ResError ResolvingStrategy = GQLErrors
+  liftEither = ResolveM . ResultT . fmap fromEither
+
+instance LiftEither SUBSCRIPTION ResolvingStrategy where
+  type ResError ResolvingStrategy = GQLErrors
+  liftEither = ResolveS . ResultT . fmap (fromEither . fmap pure)
+
+ -- Failure
+instance (LiftEither o ResolvingStrategy, Monad m) => Failure GQLErrors (ResolvingStrategy o e m) where
+  failure = liftEither . pure . Left
+
+-- helper functins
+withObject
+  :: (LiftEither o ResolvingStrategy, Monad m)
+  => (SelectionSet -> ResolvingStrategy o e m value)
+  -> (Key, ValidSelection)
+  -> ResolvingStrategy o e m value
+withObject f (_, Selection { selectionRec = SelectionSet selection }) =
+  f selection
+withObject _ (key, Selection { selectionPosition }) =
+  failure (subfieldsNotSelected key "" selectionPosition)
+
+resolveObject
+  :: (Monad m, LiftEither o ResolvingStrategy)
+  => SelectionSet
+  -> [FieldRes o e m]
+  -> ResolvingStrategy o e m Value
+resolveObject selectionSet fieldResolvers =
+  gqlObject <$> traverse selectResolver selectionSet
+ where
+  selectResolver (key, selection@Selection { selectionAlias }) =
+    (fromMaybe key selectionAlias, ) <$> lookupRes selection
+   where
+    lookupRes sel =
+      (fromMaybe (const $ pure gqlNull) $ lookup key fieldResolvers) (key, sel)
+
+toResponseRes
+  :: Monad m
+  => ResolvingStrategy o event m Value
+  -> ResponseStream event m Value
+toResponseRes (ResolveQ resT) = cleanEvents resT
+toResponseRes (ResolveM resT) = mapEvent Publish resT
+toResponseRes (ResolveS resT) = ResultT $ handleActions <$> runResultT resT
+ where
+  handleActions (Failure gqlError                ) = Failure gqlError
+  handleActions (Success subRes warnings channels) = Success
+    { result   = gqlNull
+    , warnings
+    , events   = [Subscribe $ Event channels eventResolver]
+    }
+   where
+    eventResolver event = renderResponse <$> runResultT  (unRecResolver subRes event) 
+
+--
+--     
+-- GraphQL Field Resolver
+--
+--
+--ResultT  GQLError 'True m (RecResolver m event value)
+---------------------------------------------------------------
+data Resolver (o::OperationType) event (m :: * -> * )  value where
+    QueryResolver::{ unQueryResolver :: ResultT () String 'True m value } -> Resolver QUERY   event m value
+    MutResolver ::{ unMutResolver :: ResultT event String 'True m ([event],value) } -> Resolver MUTATION event m  value
+    SubResolver ::{
+            subChannels :: [StreamChannel event] ,
+            subResolver :: event -> Resolver QUERY event m value
+        } -> Resolver SUBSCRIPTION event m  value
+
+-- Functor
+instance Functor m => Functor (Resolver o e m) where
+  fmap f (QueryResolver res) = QueryResolver $ fmap f res
+  fmap f (MutResolver   res) = MutResolver $ tupleMap <$> res
+    where tupleMap (e, v) = (e, f v)
+  fmap f (SubResolver events mResolver) = SubResolver events
+                                                      (eventFmap mResolver)
+    where eventFmap res event = fmap f (res event)
+
+-- Applicative
+instance (LiftEither o Resolver ,Monad m) => Applicative (Resolver o e m) where
+  pure = liftEither . pure . pure
+  -------------------------------------
+  (QueryResolver f) <*> (QueryResolver res) = QueryResolver (f <*> res)
+  ---------------------------------------------------------------------
+  MutResolver res1 <*> MutResolver res2 = MutResolver $ join <$> res1 <*> res2
+    where join (e1, f) (e2, v) = (e1 <> e2, f v)
+  --------------------------------------------------------------
+  (SubResolver e1 f) <*> (SubResolver e2 res) = SubResolver (e1 <> e2) subRes
+    where subRes event = f event <*> res event
+
+-- Monad 
+instance (Monad m) => Monad (Resolver QUERY e m) where
+  return = pure
+  -----------------------------------------------------
+  (QueryResolver f) >>= nextM = QueryResolver (f >>= unQueryResolver . nextM)
+
+instance (Monad m) => Monad (Resolver MUTATION e m) where
+  return = pure
+  -----------------------------------------------------
+  (MutResolver m1) >>= mFunc = MutResolver $ do
+    (e1, v1) <- m1
+    (e2, v2) <- unMutResolver $ mFunc v1
+    pure (e1 <> e2, v2)
+
+-- Monad Transformers    
+instance MonadTrans (Resolver QUERY e) where
+  lift = liftEither . fmap pure
+
+instance MonadTrans (Resolver MUTATION e) where
+  lift = liftEither . fmap pure
+
+-- LiftEither
+instance LiftEither QUERY Resolver where
+  type ResError Resolver = String
+  liftEither = QueryResolver . ResultT . fmap fromEitherSingle
+
+instance LiftEither MUTATION Resolver where
+  type ResError Resolver = String
+  liftEither = MutResolver . ResultT . fmap (fromEitherSingle . fmap ([], ))
+
+instance LiftEither SUBSCRIPTION Resolver where
+  type ResError Resolver = String
+  liftEither = SubResolver [] . const . liftEither
+
+-- Failure
+instance (LiftEither o Resolver, Monad m) => Failure Message (Resolver o e m) where
+  failure = liftEither . pure . Left . unpack
+
+-- Type Helpers  
+type family UnSubResolver (a :: * -> *) :: (* -> *)
+
+type instance UnSubResolver (Resolver SUBSCRIPTION m e) = Resolver QUERY m e
+
+
+-- RESOLVING
+type FieldRes o e m
+  = (Key, (Key, ValidSelection) -> ResolvingStrategy o e m Value)
+
+toResolver
+  :: (LiftEither o Resolver, Monad m)
+  => Validation a
+  -> (a -> Resolver o e m b)
+  -> Resolver o e m b
+toResolver Success { result } f = f result
+toResolver (Failure errors) _ =
+  failure ("TODO: errors" <> pack (show errors) :: Message)
+
+resolving
+  :: forall o e m value
+   . Monad m
+  => (value -> (Key, ValidSelection) -> ResolvingStrategy o e m Value)
+  -> Resolver o e m value
+  -> (Key, ValidSelection)
+  -> ResolvingStrategy o e m Value
+resolving encode gResolver selection@(fieldName, Selection { selectionPosition })
+  = _resolve gResolver
+ where
+  convert :: Monad m => ResultT ev String con m a -> ResultT ev GQLError con m a
+  convert =
+    mapFailure (resolvingFailedError selectionPosition fieldName . pack)
+  ------------------------------
+  _encode = (`encode` selection)
+  -------------------------------------------------------------------
+  _resolve (QueryResolver res) =
+    ResolveQ $ convert res >>= unResolveQ . _encode
+  ---------------------------------------------------------------------------------------------------------------------------------------
+  _resolve (MutResolver res) =
+    ResolveM $ replace (convert res) >>= unResolveM . _encode
+   where
+    replace (ResultT mx) = ResultT $ do
+      value <- mx
+      pure $ case value of
+        Success { warnings, events, result = (events2, result) } ->
+          Success { result, warnings, events = events <> events2 }
+        Failure x -> Failure x
+  --------------------------------------------------------------------------------------------------------------------------------
+  _resolve (SubResolver subChannels res) = ResolveS $ ResultT $ pure $ Success
+    { events   = map Channel subChannels
+    , result   = RecResolver eventResolver
+    , warnings = []
+    }
+   where
+    eventResolver :: e -> StatelessResT m Value
+    eventResolver event =
+      convert (unQueryResolver $ res event) >>= unPureSub . _encode
+     where
+      unPureSub
+        :: Monad m
+        => ResolvingStrategy SUBSCRIPTION e m Value
+        -> StatelessResT m Value
+      unPureSub (ResolveS x) = cleanEvents x >>= passEvent
+       where
+          passEvent (RecResolver f) = f event
+
+-- map Resolving strategies 
+class MapStrategy (from :: OperationType) (to :: OperationType) where
+   mapStrategy :: Monad m => ResolvingStrategy from e m a -> ResolvingStrategy to e m a
+
+instance MapStrategy o o where
+  mapStrategy = id
+
+instance MapStrategy QUERY SUBSCRIPTION where
+  mapStrategy (ResolveQ x) = ResolveS $ pure <$> cleanEvents x
+
+-------------------------------------------------------------------
+-- | GraphQL Root resolver, also the interpreter generates a GQL schema from it.
+--  '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 :: * -> *) event (query :: (* -> *) -> * ) (mut :: (* -> *) -> * )  (sub :: (* -> *) -> * )  = GQLRootResolver
+  { queryResolver        :: query (Resolver QUERY event m)
+  , mutationResolver     :: mut (Resolver MUTATION event m)
+  , subscriptionResolver :: sub (Resolver SUBSCRIPTION  event m)
+  }
+
+ -- EVENTS
+
+
+-- Channel
+
+newtype Channel event = Channel {
+  unChannel :: StreamChannel event
+}
+
+instance (Eq (StreamChannel event)) => Eq (Channel event) where
+  Channel x == Channel y = x == y
+
+class GQLChannel a where
+  type StreamChannel a :: *
+  streamChannels :: a -> [Channel a]
+
+instance GQLChannel () where
+  type StreamChannel () = ()
+  streamChannels _ = []
+
+instance GQLChannel (Event channel content)  where
+  type StreamChannel (Event channel content) = channel
+  streamChannels Event { channels } = map Channel channels
+
+data Event e c = Event
+  { channels :: [e], content  :: c}
diff --git a/src/Data/Morpheus/Types/Internal/Stream.hs b/src/Data/Morpheus/Types/Internal/Stream.hs
deleted file mode 100644
--- a/src/Data/Morpheus/Types/Internal/Stream.hs
+++ /dev/null
@@ -1,117 +0,0 @@
-{-# LANGUAGE DataKinds            #-}
-{-# LANGUAGE DeriveFunctor        #-}
-{-# LANGUAGE FlexibleContexts     #-}
-{-# LANGUAGE FlexibleInstances    #-}
-{-# LANGUAGE GADTs                #-}
-{-# LANGUAGE NamedFieldPuns       #-}
-{-# LANGUAGE TypeFamilies         #-}
-{-# LANGUAGE UndecidableInstances #-}
-
-module Data.Morpheus.Types.Internal.Stream
-  ( StreamState(..)
-  , ResponseEvent(..)
-  , SubEvent
-  , Event(..)
-  -- STREAMS
-  , StreamT(..)
-  , ResponseStream
-  , closeStream
-  , mapS
-  , injectEvents
-  , initExceptStream
-  , pushEvents
- -- , GQLMonad(..)
-  , GQLChannel(..)
-  , Channel(..)
-  ) where
-
-import           Control.Monad.Trans.Except (ExceptT (..), runExceptT)
-import           Data.Semigroup ((<>))
-
--- MORPHEUS
-import           Data.Morpheus.Types.IO     (GQLResponse)
-
--- EVENTS
-data ResponseEvent m event
-  = Publish event
-  | Subscribe (SubEvent m event)
-
--- STREAMS
-type ResponseStream m event = StreamT m (ResponseEvent m event)
-
-type SubEvent m event = Event (Channel event) (event-> m GQLResponse)
-
-newtype Channel event = Channel {
-  unChannel :: StreamChannel event
-}
-
-instance (Eq (StreamChannel event)) => Eq (Channel event) where
-  Channel x == Channel y = x == y
-
-
-class GQLChannel a where
-    type StreamChannel a :: *
-    streamChannels :: a -> [Channel a]
-
-instance GQLChannel () where
-    type StreamChannel () = ()
-    streamChannels _ = []
-
-instance GQLChannel (Event channel content)  where
-   type StreamChannel (Event channel content)  = channel
-   streamChannels Event { channels } =  map Channel channels
-
-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)
-
-instance Monad m => Applicative (StreamT m c) where
-  pure = StreamT . return . StreamState []
-  StreamT app1 <*> StreamT app2 =
-    StreamT $ do
-      (StreamState effect1 func) <- app1
-      (StreamState effect2 val) <- app2
-      return $ StreamState (effect1 ++ effect2) (func val)
-
-instance Monad m => Monad (StreamT m c) where
-  return = pure
-  (StreamT m1) >>= mFunc =
-    StreamT $ do
-      (StreamState e1 v1) <- m1
-      (StreamState e2 v2) <- runStreamT $ mFunc v1
-      return $ StreamState (e1 ++ e2) v2
-
--- Helper Functions
-toTuple :: StreamState s a -> ([s], a)
-toTuple StreamState {streamEvents, streamValue} = (streamEvents, streamValue)
-
-closeStream :: Monad m => (StreamT m s) v -> m ([s], v)
-closeStream resolver = toTuple <$> runStreamT resolver
-
-mapS :: Monad m => (a -> b) -> StreamT m a value -> StreamT m b value
-mapS func (StreamT ma) =
-  StreamT $ do
-    state <- ma
-    return $ state {streamEvents = map func (streamEvents state)}
-
-pushEvents :: Functor m => [event] -> ExceptT e (StreamT m event) a -> ExceptT e (StreamT m event) a
-pushEvents events = ExceptT . StreamT . fmap updateState . runStreamT . runExceptT
-    where
-        updateState x = x { streamEvents = events <> streamEvents x }
-
-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,26 +1,10 @@
-{-# LANGUAGE TemplateHaskell #-}
 {-# LANGUAGE CPP #-}
 
 
 module Data.Morpheus.Types.Internal.TH where
 
-import           Data.Text                  (Text, pack, unpack)
 import           Language.Haskell.TH
-import           Language.Haskell.TH.Syntax
 
-liftMaybeText :: Maybe Text -> ExpQ
-liftMaybeText (Just x) = appE  (conE 'Just) (liftText x)
-liftMaybeText Nothing  = conE 'Nothing
-
-liftText :: Text -> ExpQ
-liftText x = appE (varE 'pack) (lift (unpack x))
-
-liftTextTuple :: Lift a => (Text, a) -> ExpQ
-liftTextTuple (name, x) = tupE [liftText name, lift x]
-
-liftTextMap :: Lift a => [(Text, a)] -> ExpQ
-liftTextMap = listE . map liftTextTuple
-
 apply :: Name -> [Q Exp] -> Q Exp
 apply n = foldl appE (conE n)
 
@@ -33,11 +17,15 @@
 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
+instanceProxyFunD :: (Name,ExpQ) -> DecQ
+instanceProxyFunD (name,body)  = instanceFunD name ["_"] body
+
+instanceFunD :: Name -> [String] -> ExpQ -> 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)
+
 
 -- "User" -> ["name","id"] -> (User name id)
 destructRecord :: String -> [String] -> PatQ
diff --git a/src/Data/Morpheus/Types/Internal/Validation.hs b/src/Data/Morpheus/Types/Internal/Validation.hs
deleted file mode 100644
--- a/src/Data/Morpheus/Types/Internal/Validation.hs
+++ /dev/null
@@ -1,34 +0,0 @@
-{-# LANGUAGE DeriveAnyClass #-}
-{-# LANGUAGE DeriveGeneric  #-}
-
-module Data.Morpheus.Types.Internal.Validation
-  ( GQLError(..)
-  , Location(..)
-  , GQLErrors
-  , JSONError(..)
-  , Validation
-  , ResolveValue
-  ) where
-
-import           Control.Monad.Trans.Except         (ExceptT (..))
-import           Data.Aeson                         (FromJSON, ToJSON)
-import           Data.Morpheus.Types.Internal.Base  (Location (..))
-import           Data.Morpheus.Types.Internal.Value (Value)
-import           Data.Text                          (Text)
-import           GHC.Generics                       (Generic)
-
-data GQLError = GQLError
-  { desc      :: Text
-  , positions :: [Location]
-  } deriving (Show)
-
-type GQLErrors = [GQLError]
-
-data JSONError = JSONError
-  { message   :: Text
-  , locations :: [Location]
-  } deriving (Show, Generic, FromJSON, ToJSON)
-
-type Validation = Either GQLErrors
-
-type ResolveValue m = ExceptT GQLErrors m Value
diff --git a/src/Data/Morpheus/Types/Internal/Value.hs b/src/Data/Morpheus/Types/Internal/Value.hs
deleted file mode 100644
--- a/src/Data/Morpheus/Types/Internal/Value.hs
+++ /dev/null
@@ -1,195 +0,0 @@
-{-# 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
-  , convertToHaskellName
-  ) 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.Scientific                 (Scientific, floatingOrInteger)
-import           Data.Semigroup                  ((<>))
-import           Data.Text                       (Text)
-import qualified Data.Text                       as T
-import qualified Data.Vector                     as V (toList)
-import           GHC.Generics                    (Generic)
-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
-isReserved "data"     = True
-isReserved "default"  = True
-isReserved "deriving" = True
-isReserved "do"       = True
-isReserved "else"     = True
-isReserved "foreign"  = True
-isReserved "if"       = True
-isReserved "import"   = True
-isReserved "in"       = True
-isReserved "infix"    = True
-isReserved "infixl"   = True
-isReserved "infixr"   = True
-isReserved "instance" = True
-isReserved "let"      = True
-isReserved "module"   = True
-isReserved "newtype"  = True
-isReserved "of"       = True
-isReserved "then"     = True
-isReserved "type"     = True
-isReserved "where"    = True
-isReserved "_"        = True
-isReserved _          = False
-
-{-# INLINE isReserved #-}
-convertToJSONName :: Text -> Text
-convertToJSONName hsName
-  | not (T.null hsName) && isReserved name && (T.last hsName == '\'') = name
-  | otherwise = hsName
-  where
-    name = T.init hsName
-
-convertToHaskellName :: Text -> Text
-convertToHaskellName name
-  | isReserved name = name <> "'"
-  | otherwise = name
-
--- | Primitive Values for GQLScalar: 'Int', 'Float', 'String', 'Boolean'.
--- for performance reason type 'Text' represents GraphQl 'String' value
-data ScalarValue
-  = Int Int
-  | Float Float
-  | String Text
-  | Boolean Bool
-  deriving (Show, Generic)
-
-instance Lift ScalarValue where
-  lift (String n)  = apply 'String [liftText n]
-  lift (Int n)     = apply 'Int [lift n]
-  lift (Float n)   = apply 'Float [lift n]
-  lift (Boolean n) = apply 'Boolean [lift n]
-
-instance A.ToJSON ScalarValue where
-  toJSON (Float x)   = A.toJSON x
-  toJSON (Int x)     = A.toJSON x
-  toJSON (Boolean x) = A.toJSON x
-  toJSON (String x)  = A.toJSON x
-
-instance A.FromJSON ScalarValue where
-  parseJSON (A.Bool v)   = pure $ Boolean v
-  parseJSON (A.Number v) = pure $ decodeScientific v
-  parseJSON (A.String v) = pure $ String v
-  parseJSON notScalar    = fail $ "Expected Scalar got :" <> show notScalar
-
-instance Lift Value where
-  lift (Object ls) = apply 'Object [liftTextMap ls]
-  lift (List n)    = apply 'List [lift n]
-  lift (Enum n)    = apply 'Enum [liftText n]
-  lift (Scalar n)  = apply 'Scalar [lift n]
-  lift Null        = varE 'Null
-
-type Object = [(Text, Value)]
-
-data Value
-  = Object Object
-  | List [Value]
-  | Enum Text
-  | Scalar ScalarValue
-  | Null
-  deriving (Show, Generic)
-
-instance A.ToJSON Value where
-  toEncoding Null = A.toEncoding A.Null
-  toEncoding (Enum x) = A.toEncoding x
-  toEncoding (List x) = A.toEncoding x
-  toEncoding (Scalar x) = A.toEncoding x
-  toEncoding (Object []) = A.toEncoding $ A.object []
-  toEncoding (Object x) = A.pairs $ foldl1 (<>) $ map encodeField x
-    where
-      encodeField (key, value) = convertToJSONName key A..= value
-
-decodeScientific :: Scientific -> ScalarValue
-decodeScientific v =
-  case floatingOrInteger v of
-    Left float -> Float float
-    Right int  -> Int int
-
-replaceValue :: A.Value -> Value
-replaceValue (A.Bool v) = gqlBoolean v
-replaceValue (A.Number v) = Scalar $ decodeScientific v
-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/Internal/WebSocket.hs b/src/Data/Morpheus/Types/Internal/WebSocket.hs
--- a/src/Data/Morpheus/Types/Internal/WebSocket.hs
+++ b/src/Data/Morpheus/Types/Internal/WebSocket.hs
@@ -4,15 +4,17 @@
   ( GQLClient(..)
   , ClientID
   , ClientSession(..)
-  ) where
+  )
+where
 
-import           Data.Semigroup                      ((<>))
-import           Data.Text                           (Text)
-import           Data.UUID                           (UUID)
-import           Network.WebSockets                  (Connection)
+import           Data.Semigroup                 ( (<>) )
+import           Data.Text                      ( Text )
+import           Data.UUID                      ( UUID )
+import           Network.WebSockets             ( Connection )
 
 -- MORPHEUS
-import           Data.Morpheus.Types.Internal.Stream (SubEvent)
+import           Data.Morpheus.Types.Internal.Resolving
+                                                ( SubEvent )
 
 type ClientID = UUID
 
@@ -23,7 +25,7 @@
     }
 
 instance (Show e) => Show (ClientSession m e ) where
-  show ClientSession {sessionId} =
+  show ClientSession { sessionId } =
     "GQLSession { id: " <> show sessionId <> ", sessions: " <> "" <> " }"
 
 data GQLClient m e  =
@@ -34,6 +36,9 @@
     }
 
 instance (Show e) => Show (GQLClient m e) where
-  show GQLClient {clientID, clientSessions} =
-    "GQLClient {id:" <> show clientID <> ", sessions:" <> show clientSessions <>
-    "}"
+  show GQLClient { clientID, clientSessions } =
+    "GQLClient {id:"
+      <> show clientID
+      <> ", sessions:"
+      <> show clientSessions
+      <> "}"
diff --git a/src/Data/Morpheus/Types/Types.hs b/src/Data/Morpheus/Types/Types.hs
--- a/src/Data/Morpheus/Types/Types.hs
+++ b/src/Data/Morpheus/Types/Types.hs
@@ -1,33 +1,46 @@
-{-# LANGUAGE DeriveGeneric   #-}
-{-# LANGUAGE KindSignatures  #-}
-{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE DeriveGeneric    #-}
+{-# LANGUAGE KindSignatures   #-}
 
 module Data.Morpheus.Types.Types
-  ( GQLQueryRoot(..)
-  , Variables
-  , Undefined(..)
-  ) where
-
-import           Data.Map                                      (Map)
-import           GHC.Generics                                  (Generic)
-import           Language.Haskell.TH.Syntax                    (Lift (..))
+  ( Undefined(..)
+  , Pair(..)
+  , MapKind(..)
+  , MapArgs(..)
+  , mapKindFromList
+  )
+where
 
--- Morpheus
-import           Data.Morpheus.Types.Internal.AST.Operation    (RawOperation)
-import           Data.Morpheus.Types.Internal.AST.RawSelection (FragmentLib)
-import           Data.Morpheus.Types.Internal.Base             (Key)
-import           Data.Morpheus.Types.Internal.TH               (apply, liftTextMap)
-import           Data.Morpheus.Types.Internal.Value            (Value)
+import           GHC.Generics                   ( Generic )
 
 data Undefined (m :: * -> *) = Undefined deriving (Show, Generic)
 
-type Variables = Map Key Value
+data Pair k v =
+  Pair
+    { key   :: k
+    , value :: v
+    }
+  deriving (Generic)
 
-data GQLQueryRoot = GQLQueryRoot
-  { fragments      :: FragmentLib
-  , operation      :: RawOperation
-  , inputVariables :: [(Key, Value)]
-  } deriving (Show)
+newtype MapArgs k =
+  MapArgs
+    { oneOf :: Maybe [k]
+    }
+  deriving (Generic)
 
-instance Lift GQLQueryRoot where
-  lift (GQLQueryRoot f o v) = apply 'GQLQueryRoot [liftTextMap f, lift o, liftTextMap v]
+data MapKind k v m =
+  MapKind
+    { size  :: Int
+    , pairs :: MapArgs k -> m [Pair k v]
+    }
+  deriving (Generic)
+
+mapKindFromList :: (Eq k, Applicative m) => [(k, v)] -> MapKind k v m
+mapKindFromList inputPairs = MapKind { size  = length inputPairs
+                                     , pairs = resolvePairs
+                                     }
+ where
+  filterBy MapArgs { oneOf = Just list } =
+    filter ((`elem` list) . fst) inputPairs
+  filterBy _ = inputPairs
+  resolvePairs = pure . (map toGQLTuple . filterBy)
+  toGQLTuple (x, y) = Pair x y
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
@@ -2,52 +2,76 @@
 
 module Data.Morpheus.Validation.Document.Validation
   ( validatePartialDocument
-  ) where
+  )
+where
 
 import           Data.Maybe
 
 --
 -- Morpheus
-import           Data.Morpheus.Error.Document.Interface  (ImplementsError (..), partialImplements, unknownInterface)
-import           Data.Morpheus.Rendering.RenderGQL       (RenderGQL (..))
-import           Data.Morpheus.Types.Internal.Data       (DataField (..), DataType (..), DataObject, DataTyCon (..),
-                                                          Key, RawDataType (..), TypeAlias (..), isWeaker, isWeaker)
-import           Data.Morpheus.Types.Internal.Validation (Validation)
+import           Data.Morpheus.Error.Document.Interface
+                                                ( ImplementsError(..)
+                                                , partialImplements
+                                                , unknownInterface
+                                                )
+import           Data.Morpheus.Rendering.RenderGQL
+                                                ( RenderGQL(..) )
+import           Data.Morpheus.Types.Internal.AST
+                                                ( DataField(..)
+                                                , DataType(..)
+                                                , DataObject
+                                                , DataTyCon(..)
+                                                , Key
+                                                , RawDataType(..)
+                                                , TypeAlias(..)
+                                                , isWeaker
+                                                , isWeaker
+                                                )
+import           Data.Morpheus.Types.Internal.Resolving
+                                                ( Validation
+                                                , Failure(..)
+                                                )
 
 validatePartialDocument :: [(Key, RawDataType)] -> Validation [(Key, DataType)]
 validatePartialDocument lib = catMaybes <$> traverse validateType lib
-  where
-    validateType :: (Key, RawDataType) -> Validation (Maybe (Key, DataType))
-    validateType (name, FinalDataType x)              = pure $ Just (name, x)
-    validateType (name, Implements interfaces object) = asTuple name <$> object `mustImplement` interfaces
-    validateType _                                    = pure Nothing
-    -----------------------------------
-    asTuple name x = Just (name, x)
-    -----------------------------------
-    mustImplement :: DataObject -> [Key] -> Validation DataType
-    mustImplement object interfaceKey = do
-      interface <- traverse getInterfaceByKey interfaceKey
-      case concatMap (mustBeSubset object) interface of
-        []     -> pure $ DataObject object
-        errors -> Left $ partialImplements (typeName object) errors
-    -------------------------------
-    mustBeSubset :: DataObject -> DataObject -> [(Key, Key, ImplementsError)]
-    mustBeSubset DataTyCon {typeData = objFields} DataTyCon {typeName, typeData = interfaceFields} =
-      concatMap checkField interfaceFields
-      where
-        checkField :: (Key, DataField) -> [(Key, Key, ImplementsError)]
-        checkField (key, DataField {fieldType = interfaceT@TypeAlias { aliasTyCon = interfaceTypeName
-                                                                     , aliasWrappers = interfaceWrappers
-                                                                     }}) =
-          case lookup key objFields of
-            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 DataObject
-    getInterfaceByKey key =
-      case lookup key lib of
-        Just (Interface x) -> pure x
-        _                  -> Left $ unknownInterface key
+ where
+  validateType :: (Key, RawDataType) -> Validation (Maybe (Key, DataType))
+  validateType (name, FinalDataType x) = pure $ Just (name, x)
+  validateType (name, Implements interfaces object) =
+    asTuple name <$> object `mustImplement` interfaces
+  validateType _ = pure Nothing
+  -----------------------------------
+  asTuple name x = Just (name, x)
+  -----------------------------------
+  mustImplement :: DataObject -> [Key] -> Validation DataType
+  mustImplement object interfaceKey = do
+    interface <- traverse getInterfaceByKey interfaceKey
+    case concatMap (mustBeSubset object) interface of
+      []     -> pure $ DataObject object
+      errors -> failure $ partialImplements (typeName object) errors
+  -------------------------------
+  mustBeSubset :: DataObject -> DataObject -> [(Key, Key, ImplementsError)]
+  mustBeSubset DataTyCon { typeData = objFields } DataTyCon { typeName, typeData = interfaceFields }
+    = concatMap checkField interfaceFields
+   where
+    checkField :: (Key, DataField) -> [(Key, Key, ImplementsError)]
+    checkField (key, DataField { fieldType = interfaceT@TypeAlias { aliasTyCon = interfaceTypeName, aliasWrappers = interfaceWrappers } })
+      = case lookup key objFields of
+        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 DataObject
+  getInterfaceByKey key = case lookup key lib of
+    Just (Interface x) -> pure x
+    _                  -> failure $ unknownInterface key
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
@@ -1,77 +1,47 @@
+{-# LANGUAGE NamedFieldPuns #-}
+
+
 module Data.Morpheus.Validation.Internal.Utils
   ( differKeys
-  , existsObjectType
-  , lookupType
-  , getInputType
-  , lookupField
   , checkNameCollision
   , checkForUnknownKeys
   , 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       (DataObject, DataType (..), DataTypeLib (..))
-import           Data.Morpheus.Types.Internal.Validation (Validation)
-import qualified Data.Set                                as S
-import           Data.Text                               (Text)
+  )
+where
 
-type GenError error a = error -> Either error a
+import           Data.List                      ( (\\) )
+import           Data.Morpheus.Types.Internal.AST
+                                                ( Ref(..)
+                                                , Key
+                                                , anonymousRef
+                                                )
+import qualified Data.Set                      as S
+import           Data.Text                      ( Text )
+import           Data.Morpheus.Types.Internal.Resolving
+                                                ( Failure(..) )
 
 data VALIDATION_MODE
   = WITHOUT_VARIABLES
   | FULL_VALIDATION
   deriving (Eq, Show)
 
-lookupType :: error -> [(Text, a)] -> Text -> Either error a
-lookupType error' lib' typeName' =
-  case lookup typeName' lib' of
-    Nothing -> Left error'
-    Just x  -> pure x
-
-lookupField :: Text -> [(Text, fType)] -> GenError error fType
-lookupField id' lib' error' =
-  case lookup id' lib' of
-    Nothing    -> Left error'
-    Just field -> pure field
-
-getInputType :: Text -> DataTypeLib -> GenError error DataType
-getInputType name lib gqlError =
-  case lookup name (inputObject lib) of
-    Just x -> pure (DataInputObject x)
-    Nothing ->
-      case lookup name (inputUnion lib) of
-        Just x -> pure (DataInputUnion x)
-        Nothing ->
-          case lookup name (scalar lib) of
-            Just x   -> pure (DataScalar x)
-            Nothing  -> case lookup name (enum lib) of
-                    Just x  -> pure (DataEnum x)
-                    Nothing -> Left gqlError
-
-existsObjectType :: Position -> Text -> DataTypeLib -> Validation DataObject
-existsObjectType position' typeName' lib = lookupType error' (object lib) typeName'
-  where
-    error' = unknownType typeName' position'
-
-differKeys :: [EnhancedKey] -> [Key] -> [EnhancedKey]
-differKeys enhanced keys = enhanced \\ map enhanceKeyWithNull keys
+differKeys :: [Ref] -> [Key] -> [Ref]
+differKeys enhanced keys = enhanced \\ map anonymousRef keys
 
 removeDuplicates :: Ord a => [a] -> [a]
 removeDuplicates = S.toList . S.fromList
 
-elementOfKeys :: [Text] -> EnhancedKey -> Bool
-elementOfKeys keys' EnhancedKey {uid = id'} = id' `elem` keys'
+elementOfKeys :: [Text] -> Ref -> Bool
+elementOfKeys keys Ref { refName } = refName `elem` keys
 
-checkNameCollision :: [EnhancedKey] -> ([EnhancedKey] -> error) -> Either error [EnhancedKey]
+checkNameCollision :: Failure e m => [Ref] -> ([Ref] -> e) -> m [Ref]
 checkNameCollision enhancedKeys errorGenerator =
   case enhancedKeys \\ removeDuplicates enhancedKeys of
     []         -> pure enhancedKeys
-    duplicates -> Left $ errorGenerator duplicates
+    duplicates -> failure $ errorGenerator duplicates
 
-checkForUnknownKeys :: [EnhancedKey] -> [Text] -> ([EnhancedKey] -> error) -> Either error [EnhancedKey]
+checkForUnknownKeys :: Failure e m => [Ref] -> [Text] -> ([Ref] -> e) -> m [Ref]
 checkForUnknownKeys enhancedKeys' keys' errorGenerator' =
   case filter (not . elementOfKeys keys') enhancedKeys' of
     []           -> pure enhancedKeys'
-    unknownKeys' -> Left $ errorGenerator' unknownKeys'
+    unknownKeys' -> failure $ errorGenerator' unknownKeys'
diff --git a/src/Data/Morpheus/Validation/Internal/Value.hs b/src/Data/Morpheus/Validation/Internal/Value.hs
--- a/src/Data/Morpheus/Validation/Internal/Value.hs
+++ b/src/Data/Morpheus/Validation/Internal/Value.hs
@@ -4,74 +4,110 @@
 module Data.Morpheus.Validation.Internal.Value
   ( validateInputValue
   , validateEnum
-  ) where
+  )
+where
 
-import           Data.List                               (elem)
+import           Data.List                      ( elem )
 
 -- MORPHEUS
-import           Data.Morpheus.Error.Input               (InputError (..), InputValidation, Prop (..))
-import           Data.Morpheus.Rendering.RenderGQL       (renderWrapped)
-import           Data.Morpheus.Types.Internal.Data       (DataField (..), DataTyCon (..), DataType (..),
-                                                          DataTypeLib (..), DataValidator (..), Key, TypeAlias (..),
-                                                          WrapperD (..), isNullable)
-import           Data.Morpheus.Types.Internal.Value      (Value (..))
-import           Data.Morpheus.Validation.Internal.Utils (getInputType, lookupField)
+import           Data.Morpheus.Error.Input      ( InputError(..)
+                                                , InputValidation
+                                                , Prop(..)
+                                                )
+import           Data.Morpheus.Rendering.RenderGQL
+                                                ( renderWrapped )
+import           Data.Morpheus.Types.Internal.AST
+                                                ( DataField(..)
+                                                , DataTyCon(..)
+                                                , DataType(..)
+                                                , DataTypeLib(..)
+                                                , DataValidator(..)
+                                                , Key
+                                                , TypeAlias(..)
+                                                , TypeWrapper(..)
+                                                , DataEnumValue(..)
+                                                , isNullable
+                                                , lookupField
+                                                , lookupInputType
+                                                , Value(..)
+                                                )
 
+import           Data.Morpheus.Types.Internal.Resolving
+                                                ( Failure(..) )
+
 -- Validate Variable Argument or all Possible input Values
-validateInputValue :: DataTypeLib -> [Prop] -> [WrapperD] -> DataType -> (Key, Value) -> InputValidation Value
+validateInputValue
+  :: DataTypeLib
+  -> [Prop]
+  -> [TypeWrapper]
+  -> DataType
+  -> (Key, Value)
+  -> InputValidation Value
 validateInputValue lib prop' = validate
-  where
-    throwError :: [WrapperD] -> DataType -> Value -> InputValidation Value
-    throwError wrappers datatype value = Left $ UnexpectedType prop' (renderWrapped datatype wrappers) value Nothing
-    -- VALIDATION
-    validate :: [WrapperD] -> DataType -> (Key, 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')
-    {-- 2. VALIDATE TYPES, all wrappers are already Processed --}
-    {-- VALIDATE OBJECT--}
-    validate [] (DataInputObject DataTyCon {typeData = parentFields'}) (_, Object fields) =
-      Object <$> mapM validateField fields
-      where
-        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' <- aliasTyCon . fieldType <$> getField
-              let currentProp = prop' ++ [Prop _name fieldTypeName']
-              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 [] (DataInputUnion DataTyCon {typeData}) (_, Object fields) = return (Object fields)
-    {-- VALIDATE SCALAR --}
-    validate [] (DataEnum DataTyCon {typeData = tags', typeName = name'}) (_, value') =
-      validateEnum (UnexpectedType prop' name' value' Nothing) tags' value'
-    {-- VALIDATE ENUM --}
-    validate [] (DataScalar DataTyCon {typeName = name', typeData = DataValidator {validateValue = validator'}}) (_, value') =
-      case validator' value' of
-        Right _           -> return value'
-        Left ""           -> Left $ UnexpectedType prop' name' value' Nothing
-        Left errorMessage -> Left $ UnexpectedType prop' name' value' (Just errorMessage)
-    {-- 3. THROW ERROR: on invalid values --}
-    validate wrappers datatype (_, value) = throwError wrappers datatype value
+ where
+  throwError :: [TypeWrapper] -> DataType -> Value -> InputValidation Value
+  throwError wrappers datatype value =
+    Left $ UnexpectedType prop' (renderWrapped datatype wrappers) value Nothing
+  -- VALIDATION
+  validate :: [TypeWrapper] -> DataType -> (Key, Value) -> InputValidation Value
+  -- Validate Null. value = null ?
+  validate wrappers tName (_, Null) | isNullable wrappers = return Null
+                                    | otherwise = throwError wrappers tName Null
+  -- Validate LIST
+  validate (TypeMaybe : wrappers) type' value' =
+    validateInputValue lib prop' wrappers type' value'
+  validate (TypeList : wrappers) type' (key', List list') =
+    List <$> mapM validateElement list'
+   where
+    validateElement element' =
+      validateInputValue lib prop' wrappers type' (key', element')
+  {-- 2. VALIDATE TYPES, all wrappers are already Processed --}
+  {-- VALIDATE OBJECT--}
+  validate [] (DataInputObject DataTyCon { typeData = parentFields' }) (_, Object fields)
+    = Object <$> mapM validateField fields
+   where
+    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' <- aliasTyCon . fieldType <$> getField
+        let currentProp = prop' ++ [Prop _name fieldTypeName']
+        type' <- lookupInputType fieldTypeName'
+                                 lib
+                                 (typeMismatch x fieldTypeName' currentProp)
+        return (type', currentProp)
+      getField = lookupField _name parentFields' (UnknownField prop' _name)
+  -- VALIDATE INPUT UNION
+  -- TODO: Validate Union
+  validate [] (DataInputUnion DataTyCon { typeData }) (_, Object fields) =
+    return (Object fields)
+  {-- VALIDATE SCALAR --}
+  validate [] (DataEnum DataTyCon { typeData = tags, typeName = name' }) (_, value')
+    = validateEnum (UnexpectedType prop' name' value' Nothing) tags value'
+  {-- VALIDATE ENUM --}
+  validate [] (DataScalar DataTyCon { typeName = name', typeData = DataValidator { validateValue = validator' } }) (_, value')
+    = case validator' value' of
+      Right _  -> return value'
+      Left  "" -> failure (UnexpectedType prop' name' value' Nothing)
+      Left errorMessage ->
+        Left $ UnexpectedType prop' name' value' (Just errorMessage)
+  {-- 3. THROW ERROR: on invalid values --}
+  validate wrappers datatype (_, value) = throwError wrappers datatype value
 
-validateEnum :: error -> [Key] -> Value -> Either error Value
-validateEnum error' tags' (Enum enumValue) =
-  if enumValue `elem` tags'
-    then pure (Enum enumValue)
-    else Left error'
-validateEnum error' _ _ = Left error'
+validateEnum :: error -> [DataEnumValue] -> Value -> Either error Value
+validateEnum gqlError enumValues (Enum enumValue)
+  | enumValue `elem` tags = pure (Enum enumValue)
+  | otherwise             = Left gqlError
+  where tags = map enumName enumValues
+validateEnum gqlError _ _ = Left gqlError
 
 typeMismatch :: Value -> Key -> [Prop] -> InputError
-typeMismatch jsType expected' path' = UnexpectedType path' expected' jsType Nothing
+typeMismatch jsType expected' path' =
+  UnexpectedType path' expected' jsType Nothing
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
@@ -3,87 +3,144 @@
 
 module Data.Morpheus.Validation.Query.Arguments
   ( validateArguments
-  ) where
+  )
+where
 
-import           Data.Morpheus.Error.Arguments                 (argumentGotInvalidValue, argumentNameCollision,
-                                                                undefinedArgument, unknownArguments)
-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 (..), 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)
-import           Data.Morpheus.Validation.Internal.Value       (validateInputValue)
-import           Data.Text                                     (Text)
+import           Data.Morpheus.Error.Arguments  ( argumentGotInvalidValue
+                                                , argumentNameCollision
+                                                , undefinedArgument
+                                                , unknownArguments
+                                                )
+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
+                                                ( ValidVariables
+                                                , Variable(..)
+                                                , Argument(..)
+                                                , ValueOrigin(..)
+                                                , Arguments
+                                                , RawArgument(..)
+                                                , RawArguments
+                                                , Ref(..)
+                                                , Position
+                                                , DataArgument
+                                                , DataField(..)
+                                                , DataTypeLib
+                                                , TypeAlias(..)
+                                                , isFieldNullable
+                                                , isWeaker
+                                                , lookupInputType
+                                                , Value(Null)
+                                                )
+import           Data.Morpheus.Types.Internal.Resolving
+                                                ( Validation
+                                                , Failure(..)
+                                                )
+import           Data.Morpheus.Validation.Internal.Utils
+                                                ( checkForUnknownKeys
+                                                , checkNameCollision
+                                                )
+import           Data.Morpheus.Validation.Internal.Value
+                                                ( validateInputValue )
+import           Data.Text                      ( Text )
 
-resolveArgumentVariables :: Text -> ValidVariables -> DataField -> RawArguments -> Validation Arguments
-resolveArgumentVariables operatorName variables DataField {fieldName, fieldArgs} = mapM resolveVariable
-  where
-    resolveVariable :: (Text, RawArgument) -> Validation (Text, Argument)
-    resolveVariable (key, RawArgument argument) = pure (key, argument)
-    resolveVariable (key, VariableReference Reference {referenceName, referencePosition}) =
-      (key, ) . toArgument <$> lookupVar
-      where
-        toArgument argumentValue =
-          Argument {argumentValue, argumentOrigin = VARIABLE, argumentPosition = referencePosition}
-        lookupVar =
-          case lookup referenceName variables of
-            Nothing -> Left $ undefinedVariable operatorName referencePosition referenceName
-            Just Variable {variableValue, variableType, variableTypeWrappers} ->
-              case lookup key fieldArgs of
-                Nothing -> Left $ unknownArguments fieldName [EnhancedKey key referencePosition]
-                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 = renderWrapped variableType variableTypeWrappers
-                        fieldSignature = render fieldT
+resolveArgumentVariables
+  :: Text -> ValidVariables -> DataField -> RawArguments -> Validation Arguments
+resolveArgumentVariables operatorName variables DataField { fieldName, fieldArgs }
+  = mapM resolveVariable
+ where
+  resolveVariable :: (Text, RawArgument) -> Validation (Text, Argument)
+  resolveVariable (key, RawArgument argument) = pure (key, argument)
+  resolveVariable (key, VariableRef Ref { refName, refPosition }) =
+    (key, ) . toArgument <$> lookupVar
+   where
+    toArgument argumentValue = Argument { argumentValue
+                                        , argumentOrigin   = VARIABLE
+                                        , argumentPosition = refPosition
+                                        }
+    lookupVar = case lookup refName variables of
+      Nothing -> failure $ undefinedVariable operatorName refPosition refName
+      Just Variable { variableValue, variableType, variableTypeWrappers } ->
+        case lookup key fieldArgs of
+          Nothing -> failure $ unknownArguments fieldName [Ref key refPosition]
+          Just DataField { fieldType = fieldT@TypeAlias { aliasTyCon, aliasWrappers } }
+            -> if variableType == aliasTyCon && not
+                 (isWeaker variableTypeWrappers aliasWrappers)
+              then return variableValue
+              else failure $ incompatibleVariableType refName
+                                                      varSignature
+                                                      fieldSignature
+                                                      refPosition
+           where
+            varSignature   = renderWrapped variableType variableTypeWrappers
+            fieldSignature = render fieldT
 
-validateArgument :: DataTypeLib -> Position -> Arguments -> (Text, DataArgument) -> Validation (Text, Argument)
-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 argument
-  where
-    handleNullable
-      | 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 ()
+validateArgument
+  :: DataTypeLib
+  -> Position
+  -> Arguments
+  -> (Text, DataArgument)
+  -> Validation (Text, Argument)
+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 argument
+ where
+  handleNullable
+    | isFieldNullable argType = pure
+      ( key
+      , Argument { argumentValue    = Null
+                 , argumentOrigin   = INLINE
+                 , argumentPosition = fieldPosition
+                 }
+      )
+    | otherwise = failure $ undefinedArgument (Ref key fieldPosition)
+  -------------------------------------------------------------------------
+  validateArgumentValue :: Argument -> Validation (Text, Argument)
+  validateArgumentValue arg@Argument { argumentValue, argumentPosition } =
+    lookupInputType 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) = failure
+      $ argumentGotInvalidValue key (inputErrorMessage err) argumentPosition
+    handleInputError _ = pure ()
 
-validateArguments ::
-     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
+validateArguments
+  :: 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 }) = Ref key' argumentPosition
+    fieldKeys = map fst fieldArgs
diff --git a/src/Data/Morpheus/Validation/Query/Fragment.hs b/src/Data/Morpheus/Validation/Query/Fragment.hs
--- a/src/Data/Morpheus/Validation/Query/Fragment.hs
+++ b/src/Data/Morpheus/Validation/Query/Fragment.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE NamedFieldPuns #-}
 
 module Data.Morpheus.Validation.Query.Fragment
@@ -5,97 +6,121 @@
   , castFragmentType
   , resolveSpread
   , getFragment
-  ) where
+  )
+where
 
-import           Data.List                                     ((\\))
-import           Data.Semigroup                                ((<>))
-import           Data.Text                                     (Text)
-import qualified Data.Text                                     as T (concat)
+import           Data.List                      ( (\\) )
+import           Data.Semigroup                 ( (<>) )
+import           Data.Text                      ( Text )
+import qualified Data.Text                     as T
+                                                ( concat )
 
 -- MORPHEUS
-import           Data.Morpheus.Error.Fragment                  (cannotBeSpreadOnType, cannotSpreadWithinItself,
-                                                                fragmentNameCollision, unknownFragment, unusedFragment)
-import           Data.Morpheus.Types.Internal.AST.RawSelection (Fragment (..), FragmentLib, RawSelection (..),
-                                                                Reference (..), Selection (..))
-import           Data.Morpheus.Types.Internal.Base             (EnhancedKey (..), Position)
-import           Data.Morpheus.Types.Internal.Data             (DataTypeLib)
-import           Data.Morpheus.Types.Internal.Validation       (Validation)
-import           Data.Morpheus.Validation.Internal.Utils       (checkNameCollision, existsObjectType)
+import           Data.Morpheus.Error.Fragment   ( cannotBeSpreadOnType
+                                                , cannotSpreadWithinItself
+                                                , fragmentNameCollision
+                                                , unknownFragment
+                                                , unusedFragment
+                                                )
+import           Data.Morpheus.Error.Variable   ( unknownType )
+import           Data.Morpheus.Types.Internal.AST
+                                                ( Fragment(..)
+                                                , FragmentLib
+                                                , RawSelection(..)
+                                                , Selection(..)
+                                                , Ref(..)
+                                                , Position
+                                                , DataTypeLib
+                                                , lookupDataObject
+                                                )
+import           Data.Morpheus.Types.Internal.Resolving
+                                                ( Validation
+                                                , Failure(..)
+                                                )
+import           Data.Morpheus.Validation.Internal.Utils
+                                                ( checkNameCollision )
 
 
-validateFragments :: DataTypeLib -> FragmentLib -> [(Text, RawSelection)] -> Validation ()
-validateFragments lib fragments operatorSel = validateNameCollision >> checkLoop >> checkUnusedFragments
-  where
-    validateNameCollision = checkNameCollision fragmentsKeys fragmentNameCollision
-    checkUnusedFragments =
-      case fragmentsKeys \\ usedFragments fragments operatorSel of
-        []     -> return ()
-        unused -> Left $ unusedFragment unused
-    checkLoop = mapM (validateFragment lib) fragments >>= detectLoopOnFragments
-    fragmentsKeys = map toEnhancedKey fragments
-      where
-        toEnhancedKey (key, Fragment {fragmentPosition}) = EnhancedKey key fragmentPosition
+validateFragments
+  :: DataTypeLib -> FragmentLib -> [(Text, RawSelection)] -> Validation ()
+validateFragments lib fragments operatorSel =
+  validateNameCollision >> checkLoop >> checkUnusedFragments
+ where
+  validateNameCollision =
+    checkNameCollision fragmentsKeys fragmentNameCollision
+  checkUnusedFragments =
+    case fragmentsKeys \\ usedFragments fragments operatorSel of
+      []     -> return ()
+      unused -> failure (unusedFragment unused)
+  checkLoop = mapM (validateFragment lib) fragments >>= detectLoopOnFragments
+  fragmentsKeys = map toRef fragments
+    where toRef (key, Fragment { fragmentPosition }) = Ref key fragmentPosition
 
-type Node = EnhancedKey
+type Node = Ref
 
 type NodeEdges = (Node, [Node])
 
 type Graph = [NodeEdges]
 
-getFragment :: Reference -> FragmentLib -> Validation Fragment
-getFragment Reference {referenceName, referencePosition} lib =
-  case lookup referenceName lib of
-    Nothing       -> Left $ unknownFragment referenceName referencePosition
-    Just fragment -> pure fragment
+getFragment :: Ref -> FragmentLib -> Validation Fragment
+getFragment Ref { refName, refPosition } lib = case lookup refName lib of
+  Nothing       -> failure $ unknownFragment refName refPosition
+  Just fragment -> pure fragment
 
-castFragmentType :: Maybe Text -> Position -> [Text] -> Fragment -> Validation Fragment
-castFragmentType key' position' targets' fragment@Fragment {fragmentType} =
+castFragmentType
+  :: Maybe Text -> Position -> [Text] -> Fragment -> Validation Fragment
+castFragmentType key' position' targets' fragment@Fragment { fragmentType } =
   if fragmentType `elem` targets'
     then pure fragment
-    else Left $ cannotBeSpreadOnType key' fragmentType position' (T.concat targets')
+    else failure
+      $ cannotBeSpreadOnType key' fragmentType position' (T.concat targets')
 
-resolveSpread :: FragmentLib -> [Text] -> Reference -> Validation Fragment
-resolveSpread fragments allowedTargets reference@Reference {referenceName, referencePosition} =
-  getFragment reference fragments >>= castFragmentType (Just referenceName) referencePosition allowedTargets
+resolveSpread :: FragmentLib -> [Text] -> Ref -> Validation Fragment
+resolveSpread fragments allowedTargets reference@Ref { refName, refPosition } =
+  getFragment reference fragments
+    >>= castFragmentType (Just refName) refPosition allowedTargets
 
 usedFragments :: FragmentLib -> [(Text, RawSelection)] -> [Node]
 usedFragments fragments = concatMap findAllUses
-  where
-    findAllUses :: (Text, RawSelection) -> [Node]
-    findAllUses (_, RawSelectionSet Selection {selectionRec}) = concatMap findAllUses selectionRec
-    findAllUses (_, InlineFragment Fragment {fragmentSelection}) = concatMap findAllUses fragmentSelection
-    findAllUses (_, RawSelectionField {}) = []
-    findAllUses (_, Spread Reference {referenceName, referencePosition}) =
-      [EnhancedKey referenceName referencePosition] <> searchInFragment
-      where
-        searchInFragment = maybe [] (concatMap findAllUses . fragmentSelection) (lookup referenceName fragments)
+ where
+  findAllUses :: (Text, RawSelection) -> [Node]
+  findAllUses (_, RawSelectionSet Selection { selectionRec }) =
+    concatMap findAllUses selectionRec
+  findAllUses (_, InlineFragment Fragment { fragmentSelection }) =
+    concatMap findAllUses fragmentSelection
+  findAllUses (_, RawSelectionField{}) = []
+  findAllUses (_, Spread Ref { refName, refPosition }) =
+    [Ref refName refPosition] <> searchInFragment
+   where
+    searchInFragment = maybe []
+                             (concatMap findAllUses . fragmentSelection)
+                             (lookup refName fragments)
 
 scanForSpread :: (Text, RawSelection) -> [Node]
-scanForSpread (_, RawSelectionSet Selection {selectionRec }) = concatMap scanForSpread selectionRec
-scanForSpread (_, InlineFragment Fragment {fragmentSelection = selection'}) = concatMap scanForSpread selection'
-scanForSpread (_, RawSelectionField {}) = []
-scanForSpread (_, Spread Reference {referenceName = name', referencePosition = position'}) =
-  [EnhancedKey name' position']
+scanForSpread (_, RawSelectionSet Selection { selectionRec }) =
+  concatMap scanForSpread selectionRec
+scanForSpread (_, InlineFragment Fragment { fragmentSelection = selection' }) =
+  concatMap scanForSpread selection'
+scanForSpread (_, RawSelectionField{}) = []
+scanForSpread (_, Spread Ref { refName = name', refPosition = position' }) =
+  [Ref name' position']
 
 validateFragment :: DataTypeLib -> (Text, Fragment) -> Validation NodeEdges
-validateFragment lib (fName, Fragment {fragmentSelection, fragmentType, fragmentPosition}) =
-  existsObjectType fragmentPosition fragmentType lib >>
-  pure (EnhancedKey fName fragmentPosition, concatMap scanForSpread fragmentSelection)
+validateFragment lib (fName, Fragment { fragmentSelection, fragmentType, fragmentPosition })
+  = lookupDataObject validationError fragmentType lib >> pure
+    (Ref fName fragmentPosition, concatMap scanForSpread fragmentSelection)
+  where validationError = unknownType fragmentType fragmentPosition
 
 detectLoopOnFragments :: Graph -> Validation ()
 detectLoopOnFragments lib = mapM_ checkFragment lib
-  where
-    checkFragment (fragmentID, _) = checkForCycle lib fragmentID [fragmentID]
+ where
+  checkFragment (fragmentID, _) = checkForCycle lib fragmentID [fragmentID]
 
 checkForCycle :: Graph -> Node -> [Node] -> Validation Graph
-checkForCycle lib parentNode history =
-  case lookup parentNode lib of
-    Just node -> concat <$> mapM checkNode node
-    Nothing   -> pure []
-  where
-    checkNode x =
-      if x `elem` history
-        then cycleError x
-        else recurse x
-    recurse node = checkForCycle lib node $ history ++ [node]
-    cycleError n = Left $ cannotSpreadWithinItself $ history ++ [n]
+checkForCycle lib parentNode history = case lookup parentNode lib of
+  Just node -> concat <$> mapM checkNode node
+  Nothing   -> pure []
+ where
+  checkNode x = if x `elem` history then cycleError x else recurse x
+  recurse node = checkForCycle lib node $ history ++ [node]
+  cycleError n = failure $ cannotSpreadWithinItself (n : history)
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
@@ -1,3 +1,4 @@
+{-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE FlexibleInstances   #-}
 {-# LANGUAGE NamedFieldPuns      #-}
 {-# LANGUAGE OverloadedStrings   #-}
@@ -6,69 +7,101 @@
 
 module Data.Morpheus.Validation.Query.Selection
   ( validateSelectionSet
-  ) where
+  )
+where
 
 
-import           Data.Maybe                                     (fromMaybe)
-import           Data.Text                                      (Text)
+import           Data.Maybe                     ( fromMaybe )
+import           Data.Text                      ( Text )
 
 -- MORPHEUS
-import           Data.Morpheus.Error.Selection                  (cannotQueryField, duplicateQuerySelections,
-                                                                 hasNoSubfields, subfieldsNotSelected)
-import           Data.Morpheus.Error.Variable                   (unknownType)
-import           Data.Morpheus.Types.Internal.AST.Operation     (ValidVariables)
-import           Data.Morpheus.Types.Internal.AST.RawSelection  (Fragment (..), FragmentLib, 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 (..), DataType (..), DataObject,
-                                                                 DataTyCon (..), DataTypeLib (..), TypeAlias (..),
-                                                                 allDataTypes, isEntNode)
-import           Data.Morpheus.Types.Internal.Validation        (Validation)
-import           Data.Morpheus.Validation.Internal.Utils        (checkNameCollision, lookupType)
-import           Data.Morpheus.Validation.Query.Arguments       (validateArguments)
-import           Data.Morpheus.Validation.Query.Fragment        (castFragmentType, resolveSpread)
-import           Data.Morpheus.Validation.Query.Utils.Selection (lookupFieldAsSelectionSet, lookupSelectionField,
-                                                                 lookupUnionTypes)
+import           Data.Morpheus.Error.Selection  ( cannotQueryField
+                                                , duplicateQuerySelections
+                                                , hasNoSubfields
+                                                , subfieldsNotSelected
+                                                )
+import           Data.Morpheus.Error.Variable   ( unknownType )
+import           Data.Morpheus.Types.Internal.AST
+                                                ( ValidVariables 
+                                                , Selection(..)
+                                                , SelectionRec(..)
+                                                , SelectionSet
+                                                , Fragment(..)
+                                                , FragmentLib
+                                                , RawSelection(..)
+                                                , RawSelectionSet
+                                                , DataField(..)
+                                                , Ref(..)
+                                                , DataObject
+                                                , DataTyCon(..)
+                                                , DataType(..)
+                                                , DataTypeLib(..)
+                                                , TypeAlias(..)
+                                                , allDataTypes
+                                                , isEntNode
+                                                , lookupFieldAsSelectionSet
+                                                , lookupSelectionField
+                                                , lookupType
+                                                , lookupUnionTypes
+                                                )
+import           Data.Morpheus.Types.Internal.Resolving
+                                                ( Validation
+                                                , Failure(..)
+                                                )
+import           Data.Morpheus.Validation.Internal.Utils
+                                                ( checkNameCollision )
+import           Data.Morpheus.Validation.Query.Arguments
+                                                ( validateArguments )
+import           Data.Morpheus.Validation.Query.Fragment
+                                                ( castFragmentType
+                                                , resolveSpread
+                                                )
 
 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' , selectionAlias }) = EnhancedKey (fromMaybe key selectionAlias) position'
+checkDuplicatesOn DataTyCon { typeName = name' } keys =
+  checkNameCollision enhancedKeys selError >> pure keys
+ where
+  selError     = duplicateQuerySelections name'
+  enhancedKeys = map selToKey keys
+  selToKey (key, Selection { selectionPosition = position', selectionAlias }) =
+    Ref (fromMaybe key selectionAlias) position'
 
-clusterUnionSelection ::
-     FragmentLib -> Text -> [DataObject] -> (Text, RawSelection) -> Validation ([Fragment], SelectionSet)
+clusterUnionSelection
+  :: FragmentLib
+  -> Text
+  -> [DataObject]
+  -> (Text, RawSelection)
+  -> Validation ([Fragment], SelectionSet)
 clusterUnionSelection fragments type' possibleTypes' = splitFrag
-  where
-    packFragment fragment = return ([fragment], [])
-    typeNames = map typeName possibleTypes'
-    splitFrag :: (Text, RawSelection) -> Validation ([Fragment], SelectionSet)
-    splitFrag (_, Spread ref) = resolveSpread fragments typeNames ref >>= packFragment
-    splitFrag ("__typename", RawSelectionField selection ) = pure ([] ,[
-      ( "__typename",
-      selection {
-        selectionArguments = [] ,
-        selectionRec = SelectionField}
+ where
+  packFragment fragment = return ([fragment], [])
+  typeNames = map typeName possibleTypes'
+  splitFrag :: (Text, RawSelection) -> Validation ([Fragment], SelectionSet)
+  splitFrag (_, Spread ref) =
+    resolveSpread fragments typeNames ref >>= packFragment
+  splitFrag ("__typename", RawSelectionField selection) = pure
+    ( []
+    , [ ( "__typename"
+        , selection { selectionArguments = [], selectionRec = SelectionField }
         )
-      ])
-    splitFrag (key, RawSelectionSet Selection {selectionPosition}) =
-      Left $ cannotQueryField key type' selectionPosition
-    splitFrag (key, RawSelectionField Selection {selectionPosition}) =
-      Left $ cannotQueryField key type' selectionPosition
-  --  splitFrag (key', RawAlias {rawAliasPosition = position'}) = Left $ cannotQueryField key' type' position'
-    splitFrag (_, InlineFragment fragment') =
-      castFragmentType Nothing (fragmentPosition fragment') typeNames fragment' >>= packFragment
+      ]
+    )
+  splitFrag (key, RawSelectionSet Selection { selectionPosition }) =
+    failure $ cannotQueryField key type' selectionPosition
+  splitFrag (key, RawSelectionField Selection { selectionPosition }) =
+    failure $ cannotQueryField key type' selectionPosition
+--  splitFrag (key', RawAlias {rawAliasPosition = position'}) = failure $ cannotQueryField key' type' position'
+  splitFrag (_, InlineFragment fragment') =
+    castFragmentType Nothing (fragmentPosition fragment') typeNames fragment'
+      >>= packFragment
 
 categorizeTypes :: [DataObject] -> [Fragment] -> [(DataObject, [Fragment])]
 categorizeTypes types fragments = filter notEmpty $ map categorizeType types
-  where
-    notEmpty = (0 /=) . length . snd
-    categorizeType :: DataObject -> (DataObject, [Fragment])
-    categorizeType datatype = (datatype, filter matches fragments)
-      where
-        matches fragment = fragmentType fragment == typeName datatype
+ where
+  notEmpty = (0 /=) . length . snd
+  categorizeType :: DataObject -> (DataObject, [Fragment])
+  categorizeType datatype = (datatype, filter matches fragments)
+    where matches fragment = fragmentType fragment == typeName datatype
 
 flatTuple :: [([a], [b])] -> ([a], [b])
 flatTuple list' = (concatMap fst list', concatMap snd list')
@@ -84,77 +117,112 @@
       ]
  -}
 
-validateSelectionSet ::
-     DataTypeLib -> FragmentLib -> Text -> ValidVariables -> DataObject -> RawSelectionSet -> Validation SelectionSet
+validateSelectionSet
+  :: DataTypeLib
+  -> FragmentLib
+  -> Text
+  -> ValidVariables
+  -> DataObject
+  -> RawSelectionSet
+  -> Validation SelectionSet
 validateSelectionSet lib fragments' operatorName variables = __validate
-  where
-    __validate dataType'@DataTyCon {typeName = typeName'} selectionSet' =
-      concat <$> mapM validateSelection selectionSet' >>= checkDuplicatesOn dataType'
-      where
-        validateFragment Fragment {fragmentSelection = selection'} = __validate dataType' selection'
-        {-
+ where
+  __validate dataType'@DataTyCon { typeName = typeName' } selectionSet' =
+    concat
+      <$> mapM validateSelection selectionSet'
+      >>= checkDuplicatesOn dataType'
+   where
+    validateFragment Fragment { fragmentSelection = selection' } =
+      __validate dataType' selection'
+    {-
             get dataField and validated arguments for RawSelection
         -}
-        getValidationData key Selection {selectionArguments, selectionPosition} = do
-          selectionField <- lookupSelectionField selectionPosition key dataType'
-          -- validate field Argument -----
-          arguments <-
-            validateArguments
-              lib
-              operatorName
-              variables
-              (key, selectionField)
-              selectionPosition
-              selectionArguments
-          -- check field Type existence  -----
-          fieldDataType <-
-            lookupType
-              (unknownType (aliasTyCon $fieldType selectionField) selectionPosition)
-              (allDataTypes lib)
-              (aliasTyCon $ fieldType selectionField)
-          return (selectionField, fieldDataType, arguments)
-        -- validate single selection: InlineFragments and Spreads will Be resolved and included in SelectionSet
-        --
-        validateSelection :: (Text, RawSelection) -> Validation SelectionSet
-        validateSelection (key', RawSelectionSet fullRawSelection@Selection { selectionRec = rawSelection, selectionPosition }) = do
-          (dataField, dataType, arguments) <- getValidationData key' fullRawSelection
-          case dataType of
-            DataUnion _ -> do
-              (categories, __typename) <- clusterTypes
-              mapM (validateCluster __typename) categories >>= returnSelection arguments . UnionSelection
-              where clusterTypes = do
-                      unionTypes <- lookupUnionTypes selectionPosition key' lib dataField
-                      (spreads, __typename) <-
-                        flatTuple <$> mapM (clusterUnionSelection fragments' typeName' unionTypes) rawSelection
-                      return (categorizeTypes unionTypes spreads, __typename)
-                    --
-                    --    second arguments will be added to every selection cluster
-                    validateCluster :: SelectionSet -> (DataObject, [Fragment]) -> Validation (Text, SelectionSet)
-                    validateCluster sysSelection' (type', frags') = do
-                      selection' <- __validate type' (concatMap fragmentSelection frags')
-                      return (typeName type', sysSelection' ++ selection')
-            DataObject _ -> do
-              fieldType' <- lookupFieldAsSelectionSet selectionPosition key' lib dataField
-              __validate fieldType' rawSelection >>= returnSelection arguments . SelectionSet
-            _ -> Left $ hasNoSubfields key' (aliasTyCon $fieldType dataField) selectionPosition
-          where
-            returnSelection selectionArguments selectionRec =
-              pure
-                [ ( key'
-                  , fullRawSelection
-                      { selectionArguments,
-                        selectionRec
-                      }
-                  )
-                ]
-        validateSelection (key, RawSelectionField rawSelection@Selection{selectionPosition}) = do
-          (dataField, datatype, selectionArguments) <- getValidationData key rawSelection
-          isLeaf datatype dataField
-          pure [( key , rawSelection { selectionArguments  , selectionRec = SelectionField })]
-          where
-            isLeaf dataType DataField {fieldType = TypeAlias {aliasTyCon}}
-                | isEntNode dataType = Right ()
-                | otherwise =  Left $ subfieldsNotSelected key aliasTyCon selectionPosition
-        validateSelection (_, Spread reference') = resolveSpread fragments' [typeName'] reference' >>= validateFragment
-        validateSelection (_, InlineFragment fragment') =
-          castFragmentType Nothing (fragmentPosition fragment') [typeName'] fragment' >>= validateFragment
+    getValidationData key Selection { selectionArguments, selectionPosition } =
+      do
+        selectionField <- lookupSelectionField selectionPosition key dataType'
+        -- validate field Argument -----
+        arguments      <- validateArguments lib
+                                            operatorName
+                                            variables
+                                            (key, selectionField)
+                                            selectionPosition
+                                            selectionArguments
+        -- check field Type existence  -----
+        fieldDataType <- lookupType
+          (unknownType (aliasTyCon $fieldType selectionField) selectionPosition)
+          (allDataTypes lib)
+          (aliasTyCon $ fieldType selectionField)
+        return (selectionField, fieldDataType, arguments)
+    -- validate single selection: InlineFragments and Spreads will Be resolved and included in SelectionSet
+    --
+    validateSelection :: (Text, RawSelection) -> Validation SelectionSet
+    validateSelection (key', RawSelectionSet fullRawSelection@Selection { selectionRec = rawSelection, selectionPosition })
+      = do
+        (dataField, dataType, arguments) <- getValidationData key'
+                                                              fullRawSelection
+        case dataType of
+          DataUnion _ -> do
+            (categories, __typename) <- clusterTypes
+            mapM (validateCluster __typename) categories
+              >>= returnSelection arguments
+              .   UnionSelection
+           where
+            clusterTypes = do
+              unionTypes <- lookupUnionTypes selectionPosition
+                                             key'
+                                             lib
+                                             dataField
+              (spreads, __typename) <-
+                flatTuple
+                  <$> mapM
+                        (clusterUnionSelection fragments' typeName' unionTypes)
+                        rawSelection
+              return (categorizeTypes unionTypes spreads, __typename)
+            --
+            --    second arguments will be added to every selection cluster
+            validateCluster
+              :: SelectionSet
+              -> (DataObject, [Fragment])
+              -> Validation (Text, SelectionSet)
+            validateCluster sysSelection' (type', frags') = do
+              selection' <- __validate type'
+                                       (concatMap fragmentSelection frags')
+              return (typeName type', sysSelection' ++ selection')
+          DataObject _ -> do
+            fieldType' <- lookupFieldAsSelectionSet selectionPosition
+                                                    key'
+                                                    lib
+                                                    dataField
+            __validate fieldType' rawSelection
+              >>= returnSelection arguments
+              .   SelectionSet
+          _ -> failure $ hasNoSubfields key'
+                                        (aliasTyCon $fieldType dataField)
+                                        selectionPosition
+     where
+      returnSelection selectionArguments selectionRec =
+        pure [(key', fullRawSelection { selectionArguments, selectionRec })]
+    validateSelection (key, RawSelectionField rawSelection@Selection { selectionPosition })
+      = do
+        (dataField, datatype, selectionArguments) <- getValidationData
+          key
+          rawSelection
+        isLeaf datatype dataField
+        pure
+          [ ( key
+            , rawSelection { selectionArguments, selectionRec = SelectionField }
+            )
+          ]
+     where
+      isLeaf dataType DataField { fieldType = TypeAlias { aliasTyCon } }
+        | isEntNode dataType = pure ()
+        | otherwise = failure
+        $ subfieldsNotSelected key aliasTyCon selectionPosition
+    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
deleted file mode 100644
--- a/src/Data/Morpheus/Validation/Query/Utils/Selection.hs
+++ /dev/null
@@ -1,32 +0,0 @@
-{-# LANGUAGE NamedFieldPuns #-}
-
-module Data.Morpheus.Validation.Query.Utils.Selection
-  ( lookupFieldAsSelectionSet
-  , lookupSelectionField
-  , lookupUnionTypes
-  ) where
-
-import           Data.Morpheus.Error.Selection           (cannotQueryField, hasNoSubfields)
-import           Data.Morpheus.Types.Internal.Base       (Position)
-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 -> 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 -> DataField -> Validation DataObject
-lookupFieldAsSelectionSet position key' lib DataField {fieldType = TypeAlias {aliasTyCon = type'}} =
-  lookupType error' (object lib) type'
-  where
-    error' = hasNoSubfields key' type' position
-
-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
@@ -5,44 +5,51 @@
 
 module Data.Morpheus.Validation.Query.Validation
   ( validateRequest
-  ) where
+  )
+where
 
-import           Data.Map                                   (fromList)
-import           Data.Morpheus.Error.Mutation               (mutationIsNotDefined)
-import           Data.Morpheus.Error.Subscription           (subscriptionIsNotDefined)
-import           Data.Morpheus.Types.Internal.AST.Operation (Operation (..), RawOperation, ValidOperation,
-                                                             getOperationName)
-import           Data.Morpheus.Types.Internal.Data          (DataObject, DataTypeLib (..), OperationType (..))
-import           Data.Morpheus.Types.Internal.Validation    (Validation)
-import           Data.Morpheus.Types.Types                  (GQLQueryRoot (..))
-import           Data.Morpheus.Validation.Internal.Utils    (VALIDATION_MODE)
-import           Data.Morpheus.Validation.Query.Fragment    (validateFragments)
-import           Data.Morpheus.Validation.Query.Selection   (validateSelectionSet)
-import           Data.Morpheus.Validation.Query.Variable    (resolveOperationVariables)
+import           Data.Map                       ( fromList )
+import           Data.Morpheus.Types.Internal.AST
+                                                ( Operation(..)
+                                                , ValidOperation
+                                                , getOperationName
+                                                , getOperationDataType
+                                                , DataTypeLib(..)
+                                                , GQLQuery(..)
+                                                )
+import           Data.Morpheus.Types.Internal.Resolving
+                                                ( Validation )
 
-getOperationDataType :: RawOperation -> DataTypeLib -> Validation DataObject
-getOperationDataType Operation {operationType = Query} lib = pure $ snd $ query lib
-getOperationDataType Operation {operationType = Mutation, operationPosition} lib =
-  case mutation lib of
-    Just (_, mutation') -> pure mutation'
-    Nothing             -> Left $ mutationIsNotDefined operationPosition
-getOperationDataType Operation {operationType = Subscription, operationPosition} lib =
-  case subscription lib of
-    Just (_, subscription') -> pure subscription'
-    Nothing                 -> Left $ subscriptionIsNotDefined operationPosition
+import           Data.Morpheus.Validation.Internal.Utils
+                                                ( VALIDATION_MODE )
+import           Data.Morpheus.Validation.Query.Fragment
+                                                ( validateFragments )
+import           Data.Morpheus.Validation.Query.Selection
+                                                ( validateSelectionSet )
+import           Data.Morpheus.Validation.Query.Variable
+                                                ( resolveOperationVariables )
 
-validateRequest :: DataTypeLib -> VALIDATION_MODE -> GQLQueryRoot -> Validation ValidOperation
-validateRequest lib validationMode GQLQueryRoot { fragments
-                                                , inputVariables
-                                                , operation = rawOperation@Operation { operationName
-                                                                                     , operationType
-                                                                                     , operationSelection
-                                                                                     , operationPosition
-                                                                                     }
-                                                } = do
-  operationDataType <- getOperationDataType rawOperation lib
-  variables <- resolveOperationVariables lib fragments (fromList inputVariables) validationMode rawOperation
-  validateFragments lib fragments operationSelection
-  selection <-
-    validateSelectionSet lib fragments (getOperationName operationName) variables operationDataType operationSelection
-  pure $ Operation {operationName, operationType, operationArgs = [], operationSelection = selection, operationPosition}
+
+validateRequest
+  :: DataTypeLib -> VALIDATION_MODE -> GQLQuery -> Validation ValidOperation
+validateRequest lib validationMode GQLQuery { fragments, inputVariables, operation = rawOperation@Operation { operationName, operationType, operationSelection, operationPosition } }
+  = do
+    operationDataType <- getOperationDataType rawOperation lib
+    variables         <- resolveOperationVariables lib
+                                                   fragments
+                                                   (fromList inputVariables)
+                                                   validationMode
+                                                   rawOperation
+    validateFragments lib fragments operationSelection
+    selection <- validateSelectionSet lib
+                                      fragments
+                                      (getOperationName operationName)
+                                      variables
+                                      operationDataType
+                                      operationSelection
+    pure $ Operation { operationName
+                     , operationType
+                     , operationArgs      = []
+                     , operationSelection = selection
+                     , 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
@@ -1,100 +1,147 @@
+{-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE NamedFieldPuns #-}
 
 module Data.Morpheus.Validation.Query.Variable
   ( resolveOperationVariables
-  ) where
+  )
+where
 
-import           Data.List                                     ((\\))
-import qualified Data.Map                                      as M (lookup)
-import           Data.Maybe                                    (maybe)
-import           Data.Semigroup                                ((<>))
-import           Data.Text                                     (Text)
+import           Data.List                      ( (\\) )
+import qualified Data.Map                      as M
+                                                ( lookup )
+import           Data.Maybe                     ( maybe )
+import           Data.Semigroup                 ( (<>) )
+import           Data.Text                      ( Text )
 
 --- MORPHEUS
-import           Data.Morpheus.Error.Input                     (inputErrorMessage)
-import           Data.Morpheus.Error.Variable                  (uninitializedVariable, unknownType, unusedVariables,
-                                                                variableGotInvalidValue)
-import           Data.Morpheus.Types.Internal.AST.Operation    (DefaultValue, Operation (..), RawOperation,
-                                                                ValidVariables, Variable (..), getOperationName)
-import           Data.Morpheus.Types.Internal.AST.RawSelection (Fragment (..), FragmentLib, RawArgument (..),
-                                                                RawSelection (..), RawSelectionSet, Reference (..),
-                                                                Selection (..))
-import           Data.Morpheus.Types.Internal.Base             (EnhancedKey (..), Position)
-import           Data.Morpheus.Types.Internal.Data             (DataType, DataTypeLib)
-import           Data.Morpheus.Types.Internal.Validation       (Validation)
-import           Data.Morpheus.Types.Internal.Value            (Value (..))
-import           Data.Morpheus.Types.Types                     (Variables)
-import           Data.Morpheus.Validation.Internal.Utils       (VALIDATION_MODE (..), getInputType)
-import           Data.Morpheus.Validation.Internal.Value       (validateInputValue)
-import           Data.Morpheus.Validation.Query.Fragment       (getFragment)
+import           Data.Morpheus.Error.Input      ( inputErrorMessage )
+import           Data.Morpheus.Error.Variable   ( uninitializedVariable
+                                                , unknownType
+                                                , unusedVariables
+                                                , variableGotInvalidValue
+                                                )
+import           Data.Morpheus.Types.Internal.AST
+                                                ( DefaultValue
+                                                , Operation(..)
+                                                , RawOperation
+                                                , ValidVariables
+                                                , Variable(..)
+                                                , getOperationName
+                                                , Fragment(..)
+                                                , FragmentLib
+                                                , RawArgument(..)
+                                                , RawSelection(..)
+                                                , RawSelectionSet
+                                                , Selection(..)
+                                                , Ref(..)
+                                                , Position
+                                                , DataType
+                                                , DataTypeLib
+                                                , lookupInputType
+                                                , Variables
+                                                , Value(..)
+                                                )
+import           Data.Morpheus.Types.Internal.Resolving
+                                                ( Validation
+                                                , Failure(..)
+                                                )
+import           Data.Morpheus.Validation.Internal.Utils
+                                                ( VALIDATION_MODE(..) )
+import           Data.Morpheus.Validation.Internal.Value
+                                                ( validateInputValue )
+import           Data.Morpheus.Validation.Query.Fragment
+                                                ( getFragment )
 
 getVariableType :: Text -> Position -> DataTypeLib -> Validation DataType
-getVariableType type' position' lib' = getInputType type' lib' error'
-  where
-    error' = unknownType type' position'
+getVariableType type' position' lib' = lookupInputType type' lib' error'
+  where error' = unknownType type' position'
 
 concatMapM :: Monad m => (a -> m [b]) -> [a] -> m [b]
 concatMapM f = fmap concat . mapM f
 
-allVariableReferences :: FragmentLib -> [RawSelectionSet] -> Validation [EnhancedKey]
-allVariableReferences fragmentLib = concatMapM (concatMapM searchReferences)
-  where
-    referencesFromArgument :: (Text, RawArgument) -> [EnhancedKey]
-    referencesFromArgument (_, RawArgument {}) = []
-    referencesFromArgument (_, VariableReference Reference {referenceName, referencePosition}) =
-      [EnhancedKey referenceName referencePosition]
-    -- | search used variables in every arguments
-    searchReferences :: (Text, RawSelection) -> Validation [EnhancedKey]
-    searchReferences (_, RawSelectionSet Selection {selectionArguments, selectionRec}) =
-      getArgs <$> concatMapM searchReferences selectionRec
-      where
-        getArgs :: [EnhancedKey] -> [EnhancedKey]
-        getArgs x = concatMap referencesFromArgument selectionArguments <> x
-    searchReferences (_, InlineFragment Fragment {fragmentSelection}) = concatMapM searchReferences fragmentSelection
-    searchReferences (_, RawSelectionField Selection {selectionArguments}) =
-      return $ concatMap referencesFromArgument selectionArguments
-    searchReferences (_, Spread reference) =
-      getFragment reference fragmentLib >>= concatMapM searchReferences . fragmentSelection
+allVariableRefs :: FragmentLib -> [RawSelectionSet] -> Validation [Ref]
+allVariableRefs fragmentLib = concatMapM (concatMapM searchRefs)
+ where
+  referencesFromArgument :: (Text, RawArgument) -> [Ref]
+  referencesFromArgument (_, RawArgument{}) = []
+  referencesFromArgument (_, VariableRef Ref { refName, refPosition }) =
+    [Ref refName refPosition]
+  -- | search used variables in every arguments
+  searchRefs :: (Text, RawSelection) -> Validation [Ref]
+  searchRefs (_, RawSelectionSet Selection { selectionArguments, selectionRec })
+    = getArgs <$> concatMapM searchRefs selectionRec
+   where
+    getArgs :: [Ref] -> [Ref]
+    getArgs x = concatMap referencesFromArgument selectionArguments <> x
+  searchRefs (_, InlineFragment Fragment { fragmentSelection }) =
+    concatMapM searchRefs fragmentSelection
+  searchRefs (_, RawSelectionField Selection { selectionArguments }) =
+    return $ concatMap referencesFromArgument selectionArguments
+  searchRefs (_, Spread reference) =
+    getFragment reference fragmentLib
+      >>= concatMapM searchRefs
+      .   fragmentSelection
 
-resolveOperationVariables ::
-     DataTypeLib -> FragmentLib -> Variables -> VALIDATION_MODE -> RawOperation -> Validation ValidVariables
-resolveOperationVariables typeLib lib root validationMode Operation {operationName, operationSelection, operationArgs} = do
-  allVariableReferences lib [operationSelection] >>= checkUnusedVariables
-  mapM (lookupAndValidateValueOnBody typeLib root validationMode) operationArgs
-  where
-    varToKey :: (Text, Variable a) -> EnhancedKey
-    varToKey (key', Variable {variablePosition}) = EnhancedKey key' variablePosition
-    --
-    checkUnusedVariables :: [EnhancedKey] -> Validation ()
-    checkUnusedVariables refs =
-      case map varToKey operationArgs \\ refs of
-        []      -> pure ()
-        unused' -> Left $ unusedVariables (getOperationName operationName) unused'
+resolveOperationVariables
+  :: DataTypeLib
+  -> FragmentLib
+  -> Variables
+  -> VALIDATION_MODE
+  -> RawOperation
+  -> Validation ValidVariables
+resolveOperationVariables typeLib lib root validationMode Operation { operationName, operationSelection, operationArgs }
+  = do
+    allVariableRefs lib [operationSelection] >>= checkUnusedVariables
+    mapM (lookupAndValidateValueOnBody typeLib root validationMode)
+         operationArgs
+ where
+  varToKey :: (Text, Variable a) -> Ref
+  varToKey (key', Variable { variablePosition }) = Ref key' variablePosition
+  --
+  checkUnusedVariables :: [Ref] -> Validation ()
+  checkUnusedVariables refs = case map varToKey operationArgs \\ refs of
+    [] -> pure ()
+    unused' ->
+      failure $ unusedVariables (getOperationName operationName) unused'
 
-lookupAndValidateValueOnBody ::
-     DataTypeLib -> Variables -> VALIDATION_MODE -> (Text, Variable DefaultValue) -> Validation (Text, Variable Value)
-lookupAndValidateValueOnBody typeLib bodyVariables validationMode (key, var@Variable { variableType
-                                                                                     , variablePosition
-                                                                                     , isVariableRequired
-                                                                                     , variableTypeWrappers
-                                                                                     , variableValue = defaultValue
-                                                                                     }) =
-  toVariable <$> (getVariableType variableType variablePosition typeLib >>= checkType getVariable defaultValue)
-  where
-    toVariable (varKey, variableValue) = (varKey, var {variableValue})
-    getVariable = M.lookup key bodyVariables
-    ------------------------------------------------------------------
-    checkType (Just variable) Nothing varType = validator varType variable
-    checkType (Just variable) (Just defValue) varType = validator varType defValue >> validator varType variable
-    checkType Nothing (Just defValue) varType = validator varType defValue
-    checkType Nothing Nothing varType
-      | validationMode /= WITHOUT_VARIABLES && isVariableRequired =
-        Left $ uninitializedVariable variablePosition variableType key
-      | otherwise = returnNull
-      where
-        returnNull = maybe (pure (key, Null)) (validator varType) (M.lookup key bodyVariables)
-    -----------------------------------------------------------------------------------------------
-    validator varType varValue =
-      case validateInputValue typeLib [] variableTypeWrappers varType (key, varValue) of
-        Left message -> Left $ variableGotInvalidValue key (inputErrorMessage message) variablePosition
-        Right value  -> pure (key, value)
+lookupAndValidateValueOnBody
+  :: DataTypeLib
+  -> Variables
+  -> VALIDATION_MODE
+  -> (Text, Variable DefaultValue)
+  -> Validation (Text, Variable Value)
+lookupAndValidateValueOnBody typeLib bodyVariables validationMode (key, var@Variable { variableType, variablePosition, isVariableRequired, variableTypeWrappers, variableValue = defaultValue })
+  = toVariable
+    <$> (   getVariableType variableType variablePosition typeLib
+        >>= checkType getVariable defaultValue
+        )
+ where
+  toVariable (varKey, variableValue) = (varKey, var { variableValue })
+  getVariable = M.lookup key bodyVariables
+  ------------------------------------------------------------------
+  checkType (Just variable) Nothing varType = validator varType variable
+  checkType (Just variable) (Just defValue) varType =
+    validator varType defValue >> validator varType variable
+  checkType Nothing (Just defValue) varType = validator varType defValue
+  checkType Nothing Nothing varType
+    | validationMode /= WITHOUT_VARIABLES && isVariableRequired
+    = failure $ uninitializedVariable variablePosition variableType key
+    | otherwise
+    = returnNull
+   where
+    returnNull =
+      maybe (pure (key, Null)) (validator varType) (M.lookup key bodyVariables)
+  -----------------------------------------------------------------------------------------------
+  validator varType varValue =
+    case
+        validateInputValue typeLib
+                           []
+                           variableTypeWrappers
+                           varType
+                           (key, varValue)
+      of
+        Left message -> failure $ variableGotInvalidValue
+          key
+          (inputErrorMessage message)
+          variablePosition
+        Right value -> pure (key, value)
diff --git a/test/Feature/Holistic/API.gql b/test/Feature/Holistic/API.gql
deleted file mode 100644
--- a/test/Feature/Holistic/API.gql
+++ /dev/null
@@ -1,51 +0,0 @@
-enum TestEnum {
-  EnumA
-  EnumB
-  EnumC
-}
-
-input NestedInputObject {
-  fieldTestID: ID!
-}
-
-input TestInputObject {
-  fieldTestScalar: TestScalar!
-  fieldNestedInputObject: [NestedInputObject]!
-}
-
-input Coordinates {
-  latitude: TestScalar!
-  longitude: Int!
-}
-
-type Address {
-  city: String!
-  street(
-    argInputObject: TestInputObject!
-    argMaybeString: String
-  ): [[[[String!]!]!]]
-  houseNumber: Int!
-}
-
-union TestUnion = User | Address
-
-type User {
-  name: String!
-  email: String!
-  address(coordinates: Coordinates!, comment: String): Address!
-  office(zipCode: [Int!], cityID: TestEnum!): Address!
-  friend: User
-}
-
-type Query {
-  user: User!
-  testUnion: TestUnion
-}
-
-type Mutation {
-  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
@@ -12,16 +12,27 @@
 module Feature.Holistic.API
   ( api
   , rootResolver
-  ) where
+  )
+where
 
-import           Data.Morpheus          (interpreter)
-import           Data.Morpheus.Document (importGQLDocument)
-import           Data.Morpheus.Kind     (SCALAR)
-import           Data.Morpheus.Types    (Event, GQLRequest, GQLResponse, GQLRootResolver (..), GQLScalar (..),
-                                         GQLType (..), ID (..), ScalarValue (..), Resolver (..), constRes )
-import           Data.Text              (Text)
-import           GHC.Generics           (Generic)
+import           Data.Morpheus                  ( interpreter )
+import           Data.Morpheus.Document         ( importGQLDocument )
+import           Data.Morpheus.Kind             ( SCALAR )
+import           Data.Morpheus.Types            ( Event
+                                                , GQLRequest
+                                                , GQLResponse
+                                                , GQLRootResolver(..)
+                                                , GQLScalar(..)
+                                                , GQLType(..)
+                                                , ID(..)
+                                                , ScalarValue(..)
+                                                , Resolver(..)
+                                                , constRes
+                                                )
+import           Data.Text                      ( Text )
+import           GHC.Generics                   ( Generic )
 
+
 data TestScalar =
   TestScalar Int
              Int
@@ -40,29 +51,31 @@
 
 type EVENT = Event Channel ()
 
-importGQLDocument "test/Feature/Holistic/API.gql"
+importGQLDocument "test/Feature/Holistic/schema.gql"
 
-rootResolver ::
-     GQLRootResolver IO EVENT Query Mutation Subscription
-rootResolver =
-  GQLRootResolver
-    { queryResolver = Query {user, testUnion = constRes Nothing}
-    , mutationResolver =  Mutation {createUser = user}
-    , subscriptionResolver = Subscription {newUser = const SubResolver {subChannels = [Channel], subResolver = user}}
-    }
-  where
-    user _ =
-      pure 
-      User
-        { name = constRes "testName"
-        , email = constRes ""
-        , address = resolveAddress
-        , office = resolveAddress
-        , friend = constRes Nothing
-        }
-      where
-        resolveAddress _ =
-          pure Address {city = constRes "", houseNumber = constRes 0, street = constRes Nothing}
+rootResolver :: GQLRootResolver IO EVENT Query Mutation Subscription
+rootResolver = GQLRootResolver
+  { queryResolver        = Query { user, testUnion = constRes Nothing }
+  , mutationResolver     = Mutation { createUser = user }
+  , subscriptionResolver = Subscription
+                             { newUser = const SubResolver
+                                           { subChannels = [Channel]
+                                           , subResolver = user
+                                           }
+                             }
+  }
+ where
+  user _ = pure User { name    = constRes "testName"
+                     , email   = constRes ""
+                     , address = resolveAddress
+                     , office  = resolveAddress
+                     , friend  = constRes Nothing
+                     }
+   where
+    resolveAddress _ = pure Address { city        = constRes ""
+                                    , houseNumber = constRes 0
+                                    , street      = constRes Nothing
+                                    }
 
 api :: GQLRequest -> IO GQLResponse
 api = interpreter rootResolver
diff --git a/test/Feature/Holistic/cases.json b/test/Feature/Holistic/cases.json
--- a/test/Feature/Holistic/cases.json
+++ b/test/Feature/Holistic/cases.json
@@ -198,5 +198,29 @@
   {
     "path": "parsing/directive/notOnVariable",
     "description": "fail when: directive is used in Variable Definition"
+  },
+  {
+    "path": "introspection/description/object",
+    "description": "check object descriptions, type, field, args"
+  },
+  {
+    "path": "introspection/description/inputObject",
+    "description": "check inputObject descriptions, type, field"
+  },
+  {
+    "path": "introspection/description/union",
+    "description": "check union descriptions, type"
+  },
+  {
+    "path": "introspection/description/enum",
+    "description": "check enum descriptions, type, enumValue"
+  },
+  {
+    "path": "introspection/deprecated/enumValue",
+    "description": "check if deprecated works with enumValue"
+  },
+  {
+    "path": "introspection/deprecated/field",
+    "description": "check if deprecated works with object fields"
   }
 ]
diff --git a/test/Feature/Holistic/fragment/loopingFragment/response.json b/test/Feature/Holistic/fragment/loopingFragment/response.json
--- a/test/Feature/Holistic/fragment/loopingFragment/response.json
+++ b/test/Feature/Holistic/fragment/loopingFragment/response.json
@@ -1,20 +1,11 @@
 {
   "errors": [
     {
-      "message": "Cannot spread fragment \"A\" within itself via A,C,A.",
+      "message": "Cannot spread fragment \"A\" within itself via A,A,C.",
       "locations": [
-        {
-          "line": 7,
-          "column": 10
-        },
-        {
-          "line": 9,
-          "column": 3
-        },
-        {
-          "line": 17,
-          "column": 3
-        }
+        { "line": 17, "column": 3 },
+        { "line": 7, "column": 10 },
+        { "line": 9, "column": 3 }
       ]
     }
   ]
diff --git a/test/Feature/Holistic/introspection/deprecated/enumValue/query.gql b/test/Feature/Holistic/introspection/deprecated/enumValue/query.gql
new file mode 100644
--- /dev/null
+++ b/test/Feature/Holistic/introspection/deprecated/enumValue/query.gql
@@ -0,0 +1,9 @@
+{
+  __type(name: "TestEnum") {
+    enumValues {
+      name
+      isDeprecated
+      deprecationReason
+    }
+  }
+}
diff --git a/test/Feature/Holistic/introspection/deprecated/enumValue/response.json b/test/Feature/Holistic/introspection/deprecated/enumValue/response.json
new file mode 100644
--- /dev/null
+++ b/test/Feature/Holistic/introspection/deprecated/enumValue/response.json
@@ -0,0 +1,15 @@
+{
+  "data": {
+    "__type": {
+      "enumValues": [
+        { "name": "EnumA", "isDeprecated": false, "deprecationReason": null },
+        {
+          "name": "EnumB",
+          "isDeprecated": true,
+          "deprecationReason": "test deprecation enumValue"
+        },
+        { "name": "EnumC", "isDeprecated": true, "deprecationReason": null }
+      ]
+    }
+  }
+}
diff --git a/test/Feature/Holistic/introspection/deprecated/field/query.gql b/test/Feature/Holistic/introspection/deprecated/field/query.gql
new file mode 100644
--- /dev/null
+++ b/test/Feature/Holistic/introspection/deprecated/field/query.gql
@@ -0,0 +1,9 @@
+{
+  __type(name: "Address") {
+    fields {
+      name
+      isDeprecated
+      deprecationReason
+    }
+  }
+}
diff --git a/test/Feature/Holistic/introspection/deprecated/field/response.json b/test/Feature/Holistic/introspection/deprecated/field/response.json
new file mode 100644
--- /dev/null
+++ b/test/Feature/Holistic/introspection/deprecated/field/response.json
@@ -0,0 +1,19 @@
+{
+  "data": {
+    "__type": {
+      "fields": [
+        {
+          "name": "city",
+          "isDeprecated": true,
+          "deprecationReason": "test deprecation field with reason"
+        },
+        { "name": "street", "isDeprecated": true, "deprecationReason": null },
+        {
+          "name": "houseNumber",
+          "isDeprecated": false,
+          "deprecationReason": null
+        }
+      ]
+    }
+  }
+}
diff --git a/test/Feature/Holistic/introspection/description/enum/query.gql b/test/Feature/Holistic/introspection/description/enum/query.gql
new file mode 100644
--- /dev/null
+++ b/test/Feature/Holistic/introspection/description/enum/query.gql
@@ -0,0 +1,9 @@
+{
+  __type(name: "TestEnum") {
+    description
+    enumValues {
+      name
+      description
+    }
+  }
+}
diff --git a/test/Feature/Holistic/introspection/description/enum/response.json b/test/Feature/Holistic/introspection/description/enum/response.json
new file mode 100644
--- /dev/null
+++ b/test/Feature/Holistic/introspection/description/enum/response.json
@@ -0,0 +1,12 @@
+{
+  "data": {
+    "__type": {
+      "description": "type Description: TestEnum\n\nsome random enums for test",
+      "enumValues": [
+        { "name": "EnumA", "description": "enumValue Description: EnumA" },
+        { "name": "EnumB", "description": null },
+        { "name": "EnumC", "description": "enumValue Description: EnumC" }
+      ]
+    }
+  }
+}
diff --git a/test/Feature/Holistic/introspection/description/inputObject/query.gql b/test/Feature/Holistic/introspection/description/inputObject/query.gql
new file mode 100644
--- /dev/null
+++ b/test/Feature/Holistic/introspection/description/inputObject/query.gql
@@ -0,0 +1,9 @@
+{
+  __type(name: "Coordinates") {
+    description
+    inputFields {
+      name
+      description
+    }
+  }
+}
diff --git a/test/Feature/Holistic/introspection/description/inputObject/response.json b/test/Feature/Holistic/introspection/description/inputObject/response.json
new file mode 100644
--- /dev/null
+++ b/test/Feature/Holistic/introspection/description/inputObject/response.json
@@ -0,0 +1,17 @@
+{
+  "data": {
+    "__type": {
+      "description": "type Description: Coordinates\n\nsome random text",
+      "inputFields": [
+        {
+          "name": "latitude",
+          "description": "inputValue Description: latitude"
+        },
+        {
+          "name": "longitude",
+          "description": "inputValue Description: longitude\n  some random inputValue details"
+        }
+      ]
+    }
+  }
+}
diff --git a/test/Feature/Holistic/introspection/description/object/query.gql b/test/Feature/Holistic/introspection/description/object/query.gql
new file mode 100644
--- /dev/null
+++ b/test/Feature/Holistic/introspection/description/object/query.gql
@@ -0,0 +1,13 @@
+{
+  __type(name: "Address") {
+    description
+    fields {
+      name
+      description
+      args {
+        name
+        description
+      }
+    }
+  }
+}
diff --git a/test/Feature/Holistic/introspection/description/object/response.json b/test/Feature/Holistic/introspection/description/object/response.json
new file mode 100644
--- /dev/null
+++ b/test/Feature/Holistic/introspection/description/object/response.json
@@ -0,0 +1,26 @@
+{
+  "data": {
+    "__type": {
+      "description": "type Description:\n\n  Address",
+      "fields": [
+        {
+          "name": "city",
+          "description": "field Description: city",
+          "args": []
+        },
+        {
+          "name": "street",
+          "description": null,
+          "args": [
+            {
+              "name": "argInputObject",
+              "description": "argument Description: inputObject"
+            },
+            { "name": "argMaybeString", "description": null }
+          ]
+        },
+        { "name": "houseNumber", "description": null, "args": [] }
+      ]
+    }
+  }
+}
diff --git a/test/Feature/Holistic/introspection/description/union/query.gql b/test/Feature/Holistic/introspection/description/union/query.gql
new file mode 100644
--- /dev/null
+++ b/test/Feature/Holistic/introspection/description/union/query.gql
@@ -0,0 +1,5 @@
+{
+  __type(name: "TestUnion") {
+    description
+  }
+}
diff --git a/test/Feature/Holistic/introspection/description/union/response.json b/test/Feature/Holistic/introspection/description/union/response.json
new file mode 100644
--- /dev/null
+++ b/test/Feature/Holistic/introspection/description/union/response.json
@@ -0,0 +1,7 @@
+{
+  "data": {
+    "__type": {
+      "description": "type Description: TestUnion\n\nsome random text for union type"
+    }
+  }
+}
diff --git a/test/Feature/Holistic/introspection/kinds/ENUM/response.json b/test/Feature/Holistic/introspection/kinds/ENUM/response.json
--- a/test/Feature/Holistic/introspection/kinds/ENUM/response.json
+++ b/test/Feature/Holistic/introspection/kinds/ENUM/response.json
@@ -7,21 +7,13 @@
       "inputFields": null,
       "interfaces": null,
       "enumValues": [
-        {
-          "name": "EnumA",
-          "isDeprecated": false,
-          "deprecationReason": null
-        },
+        { "name": "EnumA", "isDeprecated": false, "deprecationReason": null },
         {
           "name": "EnumB",
-          "isDeprecated": false,
-          "deprecationReason": null
+          "isDeprecated": true,
+          "deprecationReason": "test deprecation enumValue"
         },
-        {
-          "name": "EnumC",
-          "isDeprecated": false,
-          "deprecationReason": null
-        }
+        { "name": "EnumC", "isDeprecated": true, "deprecationReason": null }
       ],
       "possibleTypes": null
     }
diff --git a/test/Feature/Holistic/introspection/kinds/OBJECT/response.json b/test/Feature/Holistic/introspection/kinds/OBJECT/response.json
--- a/test/Feature/Holistic/introspection/kinds/OBJECT/response.json
+++ b/test/Feature/Holistic/introspection/kinds/OBJECT/response.json
@@ -10,14 +10,10 @@
           "type": {
             "kind": "NON_NULL",
             "name": null,
-            "ofType": {
-              "kind": "SCALAR",
-              "name": "String",
-              "ofType": null
-            }
+            "ofType": { "kind": "SCALAR", "name": "String", "ofType": null }
           },
-          "isDeprecated": false,
-          "deprecationReason": null
+          "isDeprecated": true,
+          "deprecationReason": "test deprecation field with reason"
         },
         {
           "name": "street",
@@ -37,11 +33,7 @@
             },
             {
               "name": "argMaybeString",
-              "type": {
-                "kind": "SCALAR",
-                "name": "String",
-                "ofType": null
-              },
+              "type": { "kind": "SCALAR", "name": "String", "ofType": null },
               "defaultValue": null
             }
           ],
@@ -66,10 +58,7 @@
                       "ofType": {
                         "kind": "NON_NULL",
                         "name": null,
-                        "ofType": {
-                          "kind": "SCALAR",
-                          "name": "String"
-                        }
+                        "ofType": { "kind": "SCALAR", "name": "String" }
                       }
                     }
                   }
@@ -77,7 +66,7 @@
               }
             }
           },
-          "isDeprecated": false,
+          "isDeprecated": true,
           "deprecationReason": null
         },
         {
@@ -86,11 +75,7 @@
           "type": {
             "kind": "NON_NULL",
             "name": null,
-            "ofType": {
-              "kind": "SCALAR",
-              "name": "Int",
-              "ofType": null
-            }
+            "ofType": { "kind": "SCALAR", "name": "Int", "ofType": null }
           },
           "isDeprecated": false,
           "deprecationReason": null
diff --git a/test/Feature/Holistic/parsing/complex/response.json b/test/Feature/Holistic/parsing/complex/response.json
--- a/test/Feature/Holistic/parsing/complex/response.json
+++ b/test/Feature/Holistic/parsing/complex/response.json
@@ -2,12 +2,27 @@
   "errors": [
     {
       "message": "Argument coordinates got invalid value ;on longitude Expected type \"Int\" found [null,[[],[{\"uid\":\"1\"}]]].",
-      "locations": [
-        {
-          "line": 8,
-          "column": 36
-        }
-      ]
+      "locations": [{ "line": 8, "column": 36 }]
+    },
+    {
+      "message": "Argument coordinates got invalid value ;on longitude Expected type \"Int\" found [].",
+      "locations": [{ "line": 11, "column": 36 }]
+    },
+    {
+      "message": "Variable \"$v\" of type \"[[[ID!]]!]\" used in position expecting type \"[Int!]\".",
+      "locations": [{ "line": 15, "column": 21 }]
+    },
+    {
+      "message": "Cannot query field \"home\" on type \"User\".",
+      "locations": [{ "line": 25, "column": 5 }]
+    },
+    {
+      "message": "Cannot query field \"myUnion\" on type \"User\".",
+      "locations": [{ "line": 26, "column": 18 }]
+    },
+    {
+      "message": "Cannot query field \"myUnion\" on type \"User\".",
+      "locations": [{ "line": 32, "column": 18 }]
     }
   ]
 }
diff --git a/test/Feature/Holistic/parsing/extraCommas/response.json b/test/Feature/Holistic/parsing/extraCommas/response.json
--- a/test/Feature/Holistic/parsing/extraCommas/response.json
+++ b/test/Feature/Holistic/parsing/extraCommas/response.json
@@ -2,12 +2,31 @@
   "errors": [
     {
       "message": "Required Argument: \"coordinates\" was not Defined",
-      "locations": [
-        {
-          "line": 2,
-          "column": 18
-        }
-      ]
+      "locations": [{ "line": 2, "column": 18 }]
+    },
+    {
+      "message": "Required Argument: \"coordinates\" was not Defined",
+      "locations": [{ "line": 4, "column": 18 }]
+    },
+    {
+      "message": "Required Argument: \"coordinates\" was not Defined",
+      "locations": [{ "line": 6, "column": 18 }]
+    },
+    {
+      "message": "Required Argument: \"coordinates\" was not Defined",
+      "locations": [{ "line": 10, "column": 9 }]
+    },
+    {
+      "message": "Required Argument: \"coordinates\" was not Defined",
+      "locations": [{ "line": 14, "column": 14 }]
+    },
+    {
+      "message": "Required Argument: \"coordinates\" was not Defined",
+      "locations": [{ "line": 18, "column": 15 }]
+    },
+    {
+      "message": "Required Argument: \"coordinates\" was not Defined",
+      "locations": [{ "line": 22, "column": 15 }]
     }
   ]
 }
diff --git a/test/Feature/Holistic/schema.gql b/test/Feature/Holistic/schema.gql
new file mode 100644
--- /dev/null
+++ b/test/Feature/Holistic/schema.gql
@@ -0,0 +1,103 @@
+"""
+type Description: TestEnum
+
+some random enums for test
+"""
+enum TestEnum {
+  """
+  enumValue Description: EnumA
+  """
+  EnumA
+  EnumB @deprecated(reason: "test deprecation enumValue")
+  """
+  enumValue Description: EnumC
+  """
+  EnumC @deprecated
+}
+
+input NestedInputObject {
+  fieldTestID: ID!
+}
+
+input TestInputObject {
+  fieldTestScalar: TestScalar!
+  fieldNestedInputObject: [NestedInputObject]!
+}
+
+"""
+type Description: Coordinates
+
+some random text
+"""
+input Coordinates {
+  """
+  inputValue Description: latitude
+  """
+  latitude: TestScalar!
+  """
+  inputValue Description: longitude
+  some random inputValue details
+  """
+  longitude: Int!
+}
+
+"""
+type Description:
+
+  Address
+"""
+type Address {
+  """
+  field Description: city
+  """
+  city: String! @deprecated(reason: "test deprecation field with reason")
+  street(
+    """
+    argument Description: inputObject
+    """
+    argInputObject: TestInputObject!
+    argMaybeString: String
+  ): [[[[String!]!]!]] @deprecated
+  houseNumber: Int!
+}
+
+"""
+type Description: TestUnion
+
+some random text for union type
+"""
+union TestUnion = User | Address
+
+"""
+User
+
+MultilineDescription
+
+Test
+"""
+type User {
+  """
+  field description: name
+  """
+  name: String!
+  """
+  field description: email
+  """
+  email: String!
+  address(coordinates: Coordinates!, comment: String): Address!
+  office(zipCode: [Int!], cityID: TestEnum!): Address!
+  friend: User
+}
+
+type Query {
+  user: User!
+  testUnion: TestUnion
+}
+
+type Mutation {
+  createUser(userID: String!, userName: String): User!
+}
+
+type Subscription {
+  newUser: User!
+}
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
@@ -6,14 +6,20 @@
 
 module Feature.InputType.API
   ( api
-  ) where
+  )
+where
 
-import           Data.Morpheus       (interpreter)
-import           Data.Morpheus.Kind  (OBJECT)
-import           Data.Morpheus.Types (GQLRequest, GQLResponse, GQLRootResolver (..), GQLType (..), IORes,
-                                      Undefined (..))
-import           Data.Text           (Text)
-import           GHC.Generics        (Generic)
+import           Data.Morpheus                  ( interpreter )
+import           Data.Morpheus.Kind             ( OBJECT )
+import           Data.Morpheus.Types            ( GQLRequest
+                                                , GQLResponse
+                                                , GQLRootResolver(..)
+                                                , GQLType(..)
+                                                , IORes
+                                                , Undefined(..)
+                                                )
+import           Data.Text                      ( Text )
+import           GHC.Generics                   ( Generic )
 
 data F1Args = F1Args
   { arg1 :: Text
@@ -38,12 +44,15 @@
   } deriving (Generic, GQLType)
 
 rootResolver :: GQLRootResolver IO () Query Undefined Undefined
-rootResolver =
-  GQLRootResolver
-    { queryResolver = Query {q1 = A {a1 = const $ return "a1Test", a2 = const $ return 1}}
-    , mutationResolver = Undefined
-    , subscriptionResolver = Undefined
-    }
+rootResolver = GQLRootResolver
+  { queryResolver        = Query
+                             { q1 = A { a1 = const $ return "a1Test"
+                                      , a2 = const $ return 1
+                                      }
+                             }
+  , mutationResolver     = Undefined
+  , subscriptionResolver = Undefined
+  }
 
 api :: GQLRequest -> IO GQLResponse
 api = interpreter rootResolver
diff --git a/test/Rendering/TestSchemaRendering.hs b/test/Rendering/TestSchemaRendering.hs
--- a/test/Rendering/TestSchemaRendering.hs
+++ b/test/Rendering/TestSchemaRendering.hs
@@ -16,4 +16,4 @@
   where
     schema = toGraphQLDocument schemaProxy
     expected =
-        "type Query { \n  user: User!\n  testUnion: TestUnion\n}\n\nscalar TestScalar\n\nenum TestEnum { \n  EnumA\n  EnumB\n  EnumC\n}\n\ninput Coordinates { \n  latitude: TestScalar!\n  longitude: Int!\n}\n\ntype Address { \n  street: [[[[String!]!]!]]\n}\n\ntype User { \n  type: String!\n  address(coordinates: Coordinates!, type: String): Int!\n  friend(id: ID!, cityID: TestEnum): User!\n}\n\nunion TestUnion =\n    User!\n  | Address!"
+        "type Query { \n  user: User!\n  testUnion: TestUnion\n}\n\nenum TestEnum { \n  EnumA\n  EnumB\n  EnumC\n}\n\ntype Address { \n  street: [[[[String!]!]!]]\n}\n\ninput Coordinates { \n  latitude: TestScalar!\n  longitude: Int!\n}\n\ntype User { \n  type: String!\n  address(coordinates: Coordinates!, type: String): Int!\n  friend(id: ID!, cityID: TestEnum): User!\n}\n\nunion TestUnion =\n    User\n  | Address\n\nscalar TestScalar"
