anchor.diff:          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) =
  +    let private checkVariableUsageAllowedOnArguments (inputs : IntrospectionInputVal []) (varNamesAndTypeRefs : Map<string, VariableDefinition *  IntrospectionTypeRef>) (path : Path) (args : Argument list) =
  +        // FIXME: Refactor this
           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) =
  +        |> collectResults(fun arg ->
  +            match arg.Value with
  +            | Variable 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 = arg.Name) 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 err
  +                            else
  +                                let nullableLocationType = locationTypeRef.OfType.Value
  +                                if not (areTypesCompatible variableTypeRef nullableLocationType)
  +                                then err else Success
  +                        elif not (areTypesCompatible variableTypeRef locationTypeRef)
  +                        then err else Success
  +                    | None -> Success
  +                | None -> Success
  +            | _ -> Success)
  +
  +    let rec private checkVariableUsageAllowedOnSelection (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
  +        | Some spreadName when List.contains spreadName !visitedFragments -> Success
           | _ ->
               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 argumentsValid = selection.Field.Arguments |> checkVariableUsageAllowedOnArguments inputs varNamesAndTypeRefs selection.Path
  +                let selectionValid = selection.SelectionSet |> collectResults (checkVariableUsageAllowedOnSelection varNamesAndTypeRefs visitedFragments)
  +                argumentsValid
  +                @ selectionValid
  +                @ (selection.Field.Directives |> collectResults (fun directive -> directive.Arguments |> checkVariableUsageAllowedOnArguments inputs varNamesAndTypeRefs selection.Path))
  +            | None -> Success
   
       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)))
  +        |> collectResults(fun def ->
  +            let varNamesAndTypeRefs =
  +                def.Definition.VariableDefinitions
  +                |> 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
  +            def.SelectionSet |> collectResults(checkVariableUsageAllowedOnSelection varNamesAndTypeRefs visitedFragments))
   
       let private allValidations =
           [ validateFragmentsMustNotFormCycles
  
positive.code:         | Success, _ -> res2
          | _, Success -> res1
          | Error e1, Error e2 -> Error (e1 @ e2)
  
      type SchemaInfo =
          { SchemaTypes : Map<string, IntrospectionType>
  
negative.code:     let validateDocument (schema : IntrospectionSchema) (ast : Document) =
          let schemaInfo = SchemaInfo.FromIntrospectionSchema(schema)
          let context = getValidationContext schemaInfo ast
          allValidations |> collectResults(fun validate -> validate context)
  