anchor.diff:  
       let internal validateUniqueDirectivesPerLocation (ctx : ValidationContext) =
           ctx.Definitions
  +        // FIXME: Better algorithm
           |> List.collect (fun def ->
               let path = match def.Name with | Some name -> [name] | None -> []
               let defDirectives = path, def.Directives |> List.map (fun x -> x.Name)
  
positive.code:                 then acc
                  else acc @ Error.AsResult(sprintf "Directive '%s' is not defined in the schema." name, path)) acc) Success
  
      let rec private checkDirectivesInSelectionSet (acc : ValidationResult) (schemaInfo : SchemaInfo) (fragmentDefinitions : FragmentDefinition list) (path : Path) (visitedFragments : string list ref) (selectionSet : Selection list) =
          match selectionSet |> List.map (checkDirectivesInValidLocationOnSelection acc schemaInfo fragmentDefinitions path visitedFragments) with
          | [] -> acc
          | results -> List.reduce (@) results
  
      and private checkDirectivesInFragment (acc : ValidationResult) (schemaInfo : SchemaInfo)  (fragmentDefinitions : FragmentDefinition list) (path : Path) (visitedFragments : string list ref) (frag : FragmentDefinition) =
          let acc =
              frag.Directives
              |> List.fold (fun acc directive ->
                  match schemaInfo.Directives |> Array.tryFind (fun x -> x.Name = directive.Name) with
                  | Some directiveDef ->
                      let expectedLocation =
                          match frag.Name with
                          | Some _ -> DirectiveLocation.FRAGMENT_DEFINITION
                          | None -> DirectiveLocation.INLINE_FRAGMENT
                      if directiveDef.Locations |> Array.contains expectedLocation
                      then acc
                      else 
                          match frag.Name with
                          | Some fragName -> acc @ Error.AsResult(sprintf "Fragment definition '%s' has a directive '%s', but this directive location is not supported by the schema definition." fragName directive.Name, path)
                          | None -> acc @ Error.AsResult(sprintf "An inline fragment has a directive '%s', but this directive location is not supported by the schema definition." directive.Name, path)
                  | None -> acc) acc
          match frag.Name with
          | Some fragName when List.contains fragName !visitedFragments -> acc
          | _ -> checkDirectivesInSelectionSet acc schemaInfo fragmentDefinitions path visitedFragments frag.SelectionSet
  
      and private checkDirectivesInValidLocationOnSelection (acc : ValidationResult) (schemaInfo : SchemaInfo) (fragmentDefinitions : FragmentDefinition list) (path : Path) (visitedFragments : string list ref) =
          function
          | Field field ->
              let path = field.AliasOrName :: path
              let acc =
                  field.Directives
                  |> List.fold (fun acc directive ->
                      match schemaInfo.Directives |> Array.tryFind (fun x -> x.Name = directive.Name) with
                      | Some directiveDef ->
                          if directiveDef.Locations |> Array.contains DirectiveLocation.FIELD
                          then acc
                          else acc @ Error.AsResult(sprintf "Field or alias '%s' has a directive '%s', but this directive location is not supported by the schema definition." field.AliasOrName directive.Name, path)
                      | None -> acc) acc
              checkDirectivesInSelectionSet acc schemaInfo fragmentDefinitions path visitedFragments field.SelectionSet
          | InlineFragment frag -> checkDirectivesInFragment acc schemaInfo fragmentDefinitions path visitedFragments frag
          | FragmentSpread spread ->
              spread.Directives
              |> List.fold (fun acc directive ->
                  match schemaInfo.Directives |> Array.tryFind (fun x -> x.Name = directive.Name) with
                  | Some directiveDef ->
                      if directiveDef.Locations |> Array.contains DirectiveLocation.FRAGMENT_SPREAD
                      then acc
                      else acc @ Error.AsResult(sprintf "Fragment spread '%s' has a directive '%s', but this directive location is not supported by the schema definition." spread.Name directive.Name, path)
                  | None -> acc) acc
  
      let private checkDirectivesInOperation (acc : ValidationResult) (schemaInfo : SchemaInfo) (fragmentDefinitions : FragmentDefinition list) (path : Path) (visitedFragments : string list ref) (operation : OperationDefinition) =
          let expectedDirectiveLocation =
              match operation.OperationType with
              | Query -> DirectiveLocation.QUERY
              | Mutation -> DirectiveLocation.MUTATION
              | Subscription -> DirectiveLocation.SUBSCRIPTION
          let acc =
              operation.Directives
              |> List.fold (fun acc directive ->
                  match schemaInfo.Directives |> Array.tryFind (fun x -> x.Name = directive.Name) with
                  | Some directiveDef ->
                      if directiveDef.Locations |> Array.contains expectedDirectiveLocation
                      then acc
                      else 
                          match operation.Name with
                          | Some operationName -> acc @ Error.AsResult(sprintf "%s operation '%s' has a directive '%s', but this directive location is not supported by the schema definition." (operation.OperationType.ToString()) operationName directive.Name, path)
                          | None -> acc @ Error.AsResult(sprintf "This %s operation has a directive '%s', but this directive location is not supported by the schema definition." (operation.OperationType.ToString()) directive.Name, path)
                  | None -> acc) acc
          operation.SelectionSet |> List.fold (fun acc selection -> checkDirectivesInValidLocationOnSelection acc schemaInfo fragmentDefinitions path visitedFragments selection) acc
  
      let internal validateDirectivesAreInValidLocations (ctx : ValidationContext) =
          let fragmentDefinitions = ctx.FragmentDefinitions |> List.map (fun x -> x.Definition)
          let visitedFragments = ref []
          ctx.Document.Definitions
          |> List.fold (fun acc def ->
              let path = match def.Name with | Some name -> [name] | None -> []
              match def with
              | OperationDefinition odef -> checkDirectivesInOperation acc ctx.Schema fragmentDefinitions path visitedFragments odef
              | FragmentDefinition frag -> checkDirectivesInFragment acc ctx.Schema fragmentDefinitions path visitedFragments frag) Success
  
      let rec private getDirectiveNamesInSelection (path : Path) (selection : Selection) : (Path * string list) list =
          match selection with
  
negative.code:                     acc @ Error.AsResult(sprintf "Variable '%s' has a type is not an input type defined by the schema (%s)." var.VariableName (var.Type.ToString()))
                  | _ -> acc) acc) Success
  
      let private checkVariablesDefinedInDirective (variableDefinitions : VariableDefinition list) (path : Path) (directive : Directive) =
          directive.Arguments
          |> collectResults(fun arg ->
              match arg.Value with
              | Variable varName ->
                  // FIXME: Use a set
                  match variableDefinitions |> List.tryFind (fun x -> x.VariableName = varName) with
                  | Some _ -> Success
                  | None -> Error.AsResult(sprintf "A variable '%s' is referenced in an argument '%s' of directive '%s' of field with alias or name '%s', but that variable is not defined in the operation." varName arg.Name directive.Name path.Head, path)
              | _ -> Success)
  
      let rec private checkVariablesDefinedInSelection (fragmentDefinitions : FragmentDefinition list) (visitedFragments : string list ref) (variableDefinitions : VariableDefinition list) (path : Path) =
          function
          | Field field ->
              let path = field.AliasOrName :: path
              let variablesValid =
                  field.Arguments
                  |> collectResults(fun arg ->
                      match arg.Value with
                      | Variable varName ->
                          match variableDefinitions |> List.tryFind (fun x -> x.VariableName = varName) with
                          | Some _ -> Success
                          | None -> Error.AsResult(sprintf "A variable '%s' is referenced in argument '%s' of field with alias or name '%s', but that variable is not defined in the operation." varName arg.Name field.AliasOrName)
                      | _ -> Success)
              variablesValid
              @ (field.SelectionSet |> collectResults(checkVariablesDefinedInSelection fragmentDefinitions visitedFragments variableDefinitions path))
              @ (field.Directives |> collectResults(checkVariablesDefinedInDirective variableDefinitions path))
          | InlineFragment frag ->
              let variablesValid =
                  frag.SelectionSet
                  |> collectResults(checkVariablesDefinedInSelection fragmentDefinitions visitedFragments variableDefinitions path)
              variablesValid @ (frag.Directives |> collectResults (checkVariablesDefinedInDirective variableDefinitions path))
          | FragmentSpread spread ->
              if List.contains spread.Name !visitedFragments
              then Success
              else
                  visitedFragments := spread.Name :: !visitedFragments
                  let spreadValid =
                      // FIXME: Use a map?
                      match fragmentDefinitions |> List.tryFind (fun x -> x.Name.IsSome && x.Name.Value = spread.Name) with
                      | Some frag ->
                          let variablesValid =
                              frag.SelectionSet
                              |> collectResults(checkVariablesDefinedInSelection fragmentDefinitions visitedFragments variableDefinitions path)
                          variablesValid @ (frag.Directives |> collectResults (checkVariablesDefinedInDirective variableDefinitions path))
                      | None -> Success
                  spreadValid @ (spread.Directives |> collectResults (checkVariablesDefinedInDirective variableDefinitions path))
  
      let internal validateVariablesUsesDefined (ctx : ValidationContext) =
          let fragmentDefinitions = getFragmentDefinitions ctx.Document
          let visitedFragments = ref []
          ctx.Document.Definitions
          |> collectResults(function
              | OperationDefinition def ->
                  let path = Option.toList def.Name
                  def.SelectionSet |> collectResults (checkVariablesDefinedInSelection fragmentDefinitions visitedFragments def.VariableDefinitions path)
              | _ -> Success)
  
      let rec private argumentsContains (name : string) (args : Argument list) =
          args |> List.exists (fun x -> match x.Value with | Variable varName -> varName = name | _ -> false)
  
      let rec private variableIsUsedInSelection (name : string) (fragmentDefinitions : FragmentDefinition list) (visitedFragments : string list ref) =
          function
          | Field field ->
              if argumentsContains name field.Arguments
              then true
              else
                  let usedInSelection = field.SelectionSet |> List.exists (variableIsUsedInSelection name fragmentDefinitions visitedFragments)
                  usedInSelection || (field.Directives |> List.exists (fun directive -> argumentsContains name directive.Arguments))
          | InlineFragment frag ->
                  let usedInSelection = frag.SelectionSet |> List.exists (variableIsUsedInSelection name fragmentDefinitions visitedFragments)
                  usedInSelection || (frag.Directives |> List.exists (fun directive -> argumentsContains name directive.Arguments))
          | FragmentSpread spread ->
              // FIXME: Is this buggy?
              if List.contains spread.Name !visitedFragments
              then false
              else
                  let usedInSpread =
                      match fragmentDefinitions |> List.tryFind (fun x -> x.Name.IsSome && x.Name.Value = spread.Name) with
                      | Some frag ->
                          let usedInSelection = frag.SelectionSet |> List.exists (variableIsUsedInSelection name fragmentDefinitions visitedFragments)
                          usedInSelection || (frag.Directives |> List.exists (fun directive -> argumentsContains name directive.Arguments))
                      | None -> false
                  usedInSpread || (spread.Directives |> List.exists (fun directive -> argumentsContains name directive.Arguments))
  
      let internal validateAllVariablesUsed (ctx : ValidationContext) =
          let fragmentDefinitions = getFragmentDefinitions ctx.Document
          let visitedFragments = ref  []
          ctx.Document.Definitions
          |> collectResults(function
              | OperationDefinition def ->
                  def.VariableDefinitions
                  |> collectResults(fun varDef ->
                          let isUsed = def.SelectionSet |> List.exists (variableIsUsedInSelection varDef.VariableName fragmentDefinitions visitedFragments)
                          match def.Name, isUsed with
                          | _, true -> Success
                          | Some operationName, _ -> Error.AsResult(sprintf "Variable definition '%s' is not used in operation '%s'. Every variable must be used." varDef.VariableName operationName)
                          | None, _ -> Error.AsResult(sprintf "Variable definition '%s' is not used in operation. Every variable must be used." varDef.VariableName))
              | _ -> Success)
  
      let rec private areTypesCompatible (variableTypeRef : IntrospectionTypeRef) (locationTypeRef : IntrospectionTypeRef) =
          if locationTypeRef.Kind = TypeKind.NON_NULL && locationTypeRef.OfType.IsSome
  