anchor.diff:                      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 (acc : ValidationResult) (variableDefinitions : VariableDefinition list) (path : Path) (directive : Directive) =
  +    let private checkVariablesDefinedInDirective (variableDefinitions : VariableDefinition list) (path : Path) (directive : Directive) =
           directive.Arguments
  -        |> List.choose (fun arg -> match arg.Value with | Variable varName -> Some (arg.Name, varName) | _ -> None)
  -        |> List.fold (fun acc (argName, varName) -> 
  -            match variableDefinitions |> List.tryFind (fun x -> x.VariableName = varName) with
  -            | Some _ -> acc
  -            | None -> acc @ 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 argName directive.Name path.Head, path)) acc
  -
  -    let rec private checkVariablesDefinedInSelection (acc : ValidationResult) (fragmentDefinitions : FragmentDefinition list) (visitedFragments : string list ref) (variableDefinitions : VariableDefinition list) (path : Path) =
  +        |> 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 -> 
  +        | Field field ->
               let path = field.AliasOrName :: path
  -            let acc = 
  -                field.Arguments 
  -                |> List.choose (fun arg -> match arg.Value with | Variable varName -> Some (arg.Name, varName) | _ -> None)
  -                |> List.fold (fun acc (argName, varName) ->
  -                    match variableDefinitions |> List.tryFind (fun x -> x.VariableName = varName) with
  -                    | Some _ -> acc
  -                    | None -> acc @ 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 argName field.AliasOrName)) acc
  -            let acc =
  -                field.SelectionSet 
  -                |> List.fold (fun acc selection -> checkVariablesDefinedInSelection acc fragmentDefinitions visitedFragments variableDefinitions path selection) acc
  -            field.Directives
  -            |> List.fold (fun acc directive -> checkVariablesDefinedInDirective acc variableDefinitions path directive) acc
  -        | InlineFragment frag -> 
  -            let acc =
  +            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
  -                |> List.fold (fun acc selection -> checkVariablesDefinedInSelection acc fragmentDefinitions visitedFragments variableDefinitions path selection) acc
  -            frag.Directives
  -            |> List.fold (fun acc directive -> checkVariablesDefinedInDirective acc variableDefinitions path directive) acc
  +                |> collectResults(checkVariablesDefinedInSelection fragmentDefinitions visitedFragments variableDefinitions path)
  +            variablesValid @ (frag.Directives |> collectResults (checkVariablesDefinedInDirective variableDefinitions path))
           | FragmentSpread spread ->
               if List.contains spread.Name !visitedFragments
  -            then acc
  +            then Success
               else
                   visitedFragments := spread.Name :: !visitedFragments
  -                let acc =
  +                let spreadValid =
  +                    // FIXME: Use a map?
                       match fragmentDefinitions |> List.tryFind (fun x -> x.Name.IsSome && x.Name.Value = spread.Name) with
  -                    | Some frag -> 
  -                        let acc =
  -                            frag.SelectionSet 
  -                            |> List.fold (fun acc selection -> checkVariablesDefinedInSelection acc fragmentDefinitions visitedFragments variableDefinitions path selection) acc
  -                        frag.Directives
  -                        |> List.fold (fun acc directive -> checkVariablesDefinedInDirective acc variableDefinitions path directive) acc
  -                    | None -> acc
  -                spread.Directives
  -                |> List.fold (fun acc directive -> checkVariablesDefinedInDirective acc variableDefinitions path directive) acc
  +                    | 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
  -        |> List.choose (function OperationDefinition def -> Some (def.Name, def.SelectionSet, def.VariableDefinitions) | _ -> None)
  -        |> List.fold (fun acc (operationName, selectionSet, varDefs) ->
  -            let path = match operationName with | Some name -> [name] | None -> []
  -            selectionSet |> List.fold (fun acc selection -> checkVariablesDefinedInSelection acc fragmentDefinitions visitedFragments varDefs path selection) acc) Success
  -
  -    let rec private variableIsUsedInDirective (name : string) (directive : Directive) =
  -        let validArgNames = directive.Arguments |> List.choose (fun x -> match x.Value with | Variable varName -> Some varName | _ -> None)
  -        List.contains name validArgNames
  +        |> 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 ->
  -            let validArgNames = field.Arguments |> List.choose (fun x -> match x.Value with | Variable varName -> Some varName | _ -> None)
  -            if List.contains name validArgNames
  +            if argumentsContains name field.Arguments
               then true
  -            else 
  -                let acc = field.SelectionSet |> List.fold (fun acc selection -> acc || variableIsUsedInSelection name fragmentDefinitions visitedFragments selection) false
  -                field.Directives |> List.fold (fun acc directive -> acc || variableIsUsedInDirective name directive) acc
  +            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 acc = frag.SelectionSet |> List.fold (fun acc selection -> acc || variableIsUsedInSelection name fragmentDefinitions visitedFragments selection) false
  -            frag.Directives |> List.fold (fun acc directive -> acc || variableIsUsedInDirective name directive) acc
  +                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 acc =
  +                let usedInSpread =
                       match fragmentDefinitions |> List.tryFind (fun x -> x.Name.IsSome && x.Name.Value = spread.Name) with
  -                    | Some frag -> 
  -                        let acc = frag.SelectionSet |> List.fold (fun acc selection -> acc || variableIsUsedInSelection name fragmentDefinitions visitedFragments selection) false
  -                        frag.Directives |> List.fold (fun acc directive -> acc || variableIsUsedInDirective name directive) acc
  +                    | 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
  -                spread.Directives |> List.fold (fun acc directive -> acc || variableIsUsedInDirective name directive) acc
  +                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
  -        |> List.choose (function OperationDefinition def -> Some (def.Name, def.SelectionSet, def.VariableDefinitions) | _ -> None)
  -        |> List.fold (fun acc (operationName, selectionSet, varDefs) ->
  -            varDefs |> List.map (fun x -> x.VariableName) |> List.fold (fun acc varName ->
  -                let isUsed = selectionSet |> List.fold (fun acc selection -> acc || variableIsUsedInSelection varName fragmentDefinitions visitedFragments selection) false
  -                match operationName, isUsed with
  -                | _ , true -> acc
  -                | Some operationName, _ -> acc @ Error.AsResult(sprintf "Variable definition '%s' is not used in operation '%s'. Every variable must be used." varName operationName)
  -                | None, _ -> acc @ Error.AsResult(sprintf "Variable definition '%s' is not used in operation. Every variable must be used." varName))
  -                acc) Success
  +        |> 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
  
positive.code:         elif variableTypeRef.Kind = TypeKind.LIST then false
          else variableTypeRef.Name = locationTypeRef.Name && variableTypeRef.Kind = locationTypeRef.Kind
  
      let private checkVariableUsageAllowedOnArguments (acc : ValidationResult) (inputs : IntrospectionInputVal []) (varNamesAndTypeRefs : Map<string, VariableDefinition *  IntrospectionTypeRef>) (path : Path) (args : Argument list) =
          args
          |> List.choose (fun arg -> match arg.Value with | Variable varName -> Some (arg.Name, varName) | _ -> None)
          |> List.fold (fun acc (argName, varName) ->
              match varNamesAndTypeRefs.TryFind(varName) with
              | Some (varDef, variableTypeRef) ->
                  let err = Error.AsResult(sprintf "Variable '%s' can not be used in its reference. The type of the variable definition is not compatible with the type of its reference." varName, path)
                  match inputs |> Array.tryFind (fun x -> x.Name = argName) with
                  | Some input ->
                      let locationTypeRef = input.Type
                      if locationTypeRef.Kind = TypeKind.NON_NULL && locationTypeRef.OfType.IsSome && variableTypeRef.Kind <> TypeKind.NON_NULL
                      then
                          let hasNonNullVariableDefaultValue = varDef.DefaultValue.IsSome
                          let hasLocationDefaultValue = input.DefaultValue.IsSome
                          if not hasNonNullVariableDefaultValue && not hasLocationDefaultValue
                          then acc @ err
                          else
                              let nullableLocationType = locationTypeRef.OfType.Value
                              if not (areTypesCompatible variableTypeRef nullableLocationType)
                              then acc @ err else acc
                      elif not (areTypesCompatible variableTypeRef locationTypeRef)
                      then acc @ err else acc
                  | None -> acc
              | None -> acc) acc
  
      let rec private checkVariableUsageAllowedOnSelection (acc : ValidationResult) (varNamesAndTypeRefs : Map<string, VariableDefinition * IntrospectionTypeRef>) (visitedFragments : string list ref) (selection : SelectionInfo) =
          let inputs = Option.defaultValue [||] selection.InputValues
          match selection.FragmentSpreadName with
          | Some spreadName when List.contains spreadName !visitedFragments -> acc
          | _ ->
              if selection.FragmentSpreadName.IsSome then visitedFragments := selection.FragmentSpreadName.Value :: !visitedFragments
              match selection.FieldType with
              | Some fieldType ->
                  let acc = selection.Field.Arguments |> checkVariableUsageAllowedOnArguments acc inputs varNamesAndTypeRefs selection.Path
                  let acc = selection.SelectionSet |> List.fold (fun acc selection -> checkVariableUsageAllowedOnSelection acc varNamesAndTypeRefs visitedFragments selection) acc
                  selection.Field.Directives
                  |> List.fold (fun acc directive -> directive.Arguments |> checkVariableUsageAllowedOnArguments acc inputs varNamesAndTypeRefs selection.Path) acc
              | None -> acc
  
      let internal validateVariableUsagesAllowed (ctx : ValidationContext) =
          let visitedFragments = ref []
          ctx.OperationDefinitions
          |> List.map (function def -> def.SelectionSet, def.Definition.VariableDefinitions)
          |> List.map (fun (selectionSet, varDefs) -> 
              let varNamesAndTypeRefs = 
                  varDefs 
                  |> List.choose (fun varDef -> ctx.Schema.TryGetInputType(varDef.Type) |> Option.map (fun t -> varDef.VariableName, (varDef, t)))
                  |> Map.ofList
              selectionSet, varNamesAndTypeRefs)
          |> List.fold (fun acc (selectionSet, varNamesAndTypeRefs) ->
              selectionSet |> List.fold (fun acc selection -> checkVariableUsageAllowedOnSelection acc varNamesAndTypeRefs visitedFragments selection) acc) Success
  
      let private allValidations =
          [ validateFragmentsMustNotFormCycles
  
negative.code:             | EnumValue "null" when tref.Kind = TypeKind.NON_NULL -> Error.AsResult(sprintf "Argument '%s' value can not be coerced. It's type is non-nullable but the argument has a null value." argName, selection.Path)
              | EnumValue "null" -> Success
              | _ when tref.Kind = TypeKind.NON_NULL -> checkIsCoercible tref.OfType.Value argName value
              | IntValue _ ->
                  match tref.Name, tref.Kind with
                  | Some ("Int" | "Float"), TypeKind.SCALAR -> Success
                  | _ -> canNotCoerce
  