[{"name":"Field","comment":"\n\n\n# Field\n\n@docs Field\n\n\n# Type\n\n@docs Type\n\n\n# Primitive\n\nElm's primitive types: `Int`, `Float`, `Bool`, `Char`, and `String`, all have corresponding field types.\n\n\n# Int\n\n@docs int, nonNegativeInt, positiveInt, nonPositiveInt, negativeInt, subsetOfInt\n\n\n# Float\n\n@docs float, nonNegativeFloat, positiveFloat, nonPositiveFloat, negativeFloat, subsetOfFloat\n\n\n# Bool\n\n@docs bool, true, false, customSubsetOfBool\n@docs CustomBoolOptions, defaultCustomBoolOptions, defaultTruthy, defaultFalsy, defaultBoolToString\n\n\n# Char\n\n@docs char, subsetOfChar\n\n\n# String\n\nA **blank** string is either the empty string or a non-empty string consisting entirely of whitespace characters.\n\nThe empty string: `\"\"`\n\nSome blank strings: `\"\"`, `\" \"`, `\"  \"`, `\" \\t \"`, `\"\\n \\t \\r\"`\n\n@docs string, subsetOfString\n@docs nonEmptyString, subsetOfNonEmptyString\n@docs nonBlankString, subsetOfNonBlankString\n\n\n# User-defined\n\n@docs subsetOfType, customType\n\n\n# Optional\n\n@docs optional\n\n\n# Construct\n\nAll newly constructed fields are clean.\n\n@docs empty, fromString, fromValue\n\n\n# Change\n\nAny change to a field using these setter functions makes the field dirty. Furthermore,\nthese are the only functions that can dirty a field.\n\n@docs setFromString, setFromValue, setError, setErrors, setCustomError, setCustomErrors\n\n\n# Query\n\n@docs isEmpty, isNonEmpty, isBlank, isNonBlank, isClean, isDirty, isValid, isInvalid\n\n\n# Convert\n\n@docs toRawString, toString, toMaybe, toResult, toValidation\n\n\n# Validation\n\n@docs Validation, succeed, validationToResult\n\n\n# Converters\n\n@docs Converters, typeToConverters, toConverters\n\n\n# Validate\n\n@docs validate, validate2, validate3, validate4, validate5\n\n\n# Apply\n\n[`Field e`](Field-Advanced#Field) is not applicative. However, `Maybe`, `Result e`, and `Validaton e` are all applicative.\nThe functions below attempt to make it convenient to do an applicative style of programming with fields by\nleveraging the applicative nature of `Maybe`, `Result e`, and `Validation e`.\n\n@docs applyMaybe, applyResult, applyValidation\n\n\n# String Helpers\n\n@docs trim\n\n\n# Error\n\n@docs Error, blankError, syntaxError, validationError, customError, errorToString\n\n\n# Handle Errors\n\n@docs mapError\n@docs firstError, lastError, allErrors\n\n","unions":[],"aliases":[{"name":"Converters","comment":" The collection of conversion functions that comprise a `Type`. The conversion functions are useful\nfor building new field types from existing field types.\n\n    type Positive\n        = Positive Int\n\n    fromString : String -> Result Error Positive\n    fromString =\n        (typeToConverters positiveInt).fromString >> Result.map Positive\n\n    toString : Positive -> String\n    toString (Positive p) =\n        (typeToConverters positiveInt).toString p\n\n    fieldType : Type Positive\n    fieldType =\n        customType\n            { fromString = fromString\n            , toString = toString\n            }\n\n","args":["a"],"type":"Field.Advanced.Converters Field.Error a"},{"name":"CustomBoolOptions","comment":" Used by [`customSubsetOfBool`](#customSubsetOfBool) to customize the options.\n","args":[],"type":"Field.Advanced.CustomBoolOptions"},{"name":"Error","comment":" The error type returned by the built-in field types. It supports blank, syntax, validation, and custom validation errors.\n","args":[],"type":"Field.Advanced.Error String.String"},{"name":"Field","comment":" Tracks the raw `String` input and either the value of type `a` that the `String` represents or\nthe errors of type [`Error`](#Error) that can accumulate.\n","args":["a"],"type":"Field.Advanced.Field Field.Error a"},{"name":"Type","comment":" Represents the type information for a field. It specifies how a `String` is converted to a type `a`\nand back to a `String`. Conversion may result in errors of type [`Error`](#Error).\n","args":["a"],"type":"Field.Advanced.Type Field.Error a"},{"name":"Validation","comment":" Re-export the `Validation` type for convenience.\n","args":["e","a"],"type":"Validation.Validation e a"}],"values":[{"name":"allErrors","comment":"\n\n    fromString string \"A string\"\n        |> allErrors\n        |> (==) []\n\n    fromString string \"A string\"\n        |> setCustomErrors \"First error\" [ \"Second error\", \"Third error\" ]\n        |> allErrors\n        |> (==) [ customError \"First error\", customError \"Second error\", customError \"Third error\" ]\n\n","type":"Field.Field a -> List.List Field.Error"},{"name":"applyMaybe","comment":" Suppose you want to use the values from multiple fields but you don't care about any of the\nerrors that are present.\n\n    type Primitives\n        = Positive Int Float Bool Char String\n        | NonPositive Int Float Bool Char String\n\n    let\n        maybePrimitives =\n            (\\n f b c s ->\n                if n > 0 then\n                    Positive n f b c s\n                else\n                    NonPositive n f b c s\n            )\n            |> Just\n            |> applyMaybe (fromString int \"5\")\n            |> applyMaybe (fromString float \"3.14\")\n            |> applyMaybe (fromValue bool True)\n            |> applyMaybe (fromValue char 'a')\n            |> applyMaybe (fromString string \"Hello\")\n    in\n    maybePrimitives == Just (Positive 5 3.14 True 'a' \"Hello\")\n\n","type":"Field.Field a -> Maybe.Maybe (a -> b) -> Maybe.Maybe b"},{"name":"applyResult","comment":" Suppose you want to use the values from multiple fields and you only care about the\nfirst error that occurs.\n\n    type Primitives\n        = Positive Int Float Bool Char String\n        | NonPositive Int Float Bool Char String\n\n    let\n        resultPrimitives =\n            (\\n f b c s ->\n                if n > 0 then\n                    Positive n f b c s\n                else\n                    NonPositive n f b c s\n            )\n            |> Ok\n            |> applyResult (fromString int \"5\")\n            |> applyResult (fromString float \"pi\")\n            |> applyResult (fromString bool \"not\")\n            |> applyResult (fromValue char 'a')\n            |> applyResult (fromString string \"Hello\")\n    in\n    resultPrimitives == Err [ syntaxError \"pi\" ]\n\n","type":"Field.Advanced.Field e a -> Result.Result (List.List e) (a -> b) -> Result.Result (List.List e) b"},{"name":"applyValidation","comment":" Suppose you want to use the values from multiple fields and you care about all the\nerrors that occur.\n\n    type Primitives\n        = Positive Int Float Bool Char String\n        | NonPositive Int Float Bool Char String\n\n    let\n        resultPrimitives =\n            (\\n f b c s ->\n                if n > 0 then\n                    Positive n f b c s\n                else\n                    NonPositive n f b c s\n            )\n            |> succeed\n            |> applyValidation (fromString int \"5\")\n            |> applyValidation (fromString float \"pi\")\n            |> applyValidation (fromString bool \"not\")\n            |> applyValidation (fromValue char 'a')\n            |> applyValidation (fromString string \"Hello\")\n            |> validationToResult\n    in\n    resultPrimitives == Err [ syntaxError \"pi\", syntaxError \"not\" ]\n\n","type":"Field.Advanced.Field e a -> Field.Validation e (a -> b) -> Field.Validation e b"},{"name":"blankError","comment":" Indicates that the user's input string is either the empty string or a string containing only whitespace characters.\n\n    toResult (fromString positiveInt \"\") == Err [ blankError ]\n\n    toResult (fromString positiveInt \"\\n\\t \") == Err [ blankError ]\n\n","type":"Field.Error"},{"name":"bool","comment":" Any case-insensitive [`defaultTruthy`](#defaultTruthy) or [`defaultFalsy`](#defaultFalsy) trimmed string.\n\n    (typeToConverters bool).fromString \"true\" == Ok True\n\n    (typeToConverters bool).fromString \"TrUe\" == Ok True\n\n    (typeToConverters bool).fromString \"false\" == Ok False\n\n    (typeToConverters bool).fromString \"fAlSe\" == Ok False\n\n    (typeToConverters bool).fromString \" 1 \" == Ok True\n\n    (typeToConverters bool).fromString \" 0 \" == Ok False\n\n    (typeToConverters bool).fromString \"\" == Err blankError\n\n    (typeToConverters bool).fromString \"not\" == Err (syntaxError \"not\")\n\n","type":"Field.Type Basics.Bool"},{"name":"char","comment":" Any `Char` that can be parsed from a string of exactly length one. The string is not trimmed.\n\n    (typeToConverters char).fromString \"a\" == Ok 'a'\n\n    (typeToConverters char).fromString \"A\" == Ok 'A'\n\n    (typeToConverters char).fromString \"8\" == Ok '8'\n\n    (typeToConverters char).fromString \"\\n\" == Ok '\\n'\n\n    (typeToConverters char).fromString \"\" == Err blankError\n\n    (typeToConverters char).fromString \" \" == Ok ' '\n\n    (typeToConverters char).fromString \"  \" == Err blankError\n\n    (typeToConverters char).fromString \"aA\" == Err (syntaxError \"aA\")\n\n    (typeToConverters char).fromString \" 2 \" == Err (syntaxError \" 2 \")\n\n","type":"Field.Type Char.Char"},{"name":"customError","comment":" Indicates that the user's input string was successfully converted to a value of the desired type but\nthat the value wasn't contained in the subset of values under consideration.\n\nIt's similar to a [`validationError`](#validationError) but the string it takes can be a user-friendly\nerror message.\n\n    type Username = Username String\n\n    username : Type Username\n    username =\n        customType\n            { fromString =\n                trim\n                    (\\s ->\n                        let\n                            len =\n                                String.length s\n                        in\n                        if len < 3 then\n                            Err (customError <| \"The username must have at least 3 characters: \" ++ String.fromInt len)\n                        else if len > 25 then\n                            Err (customError <| \"The username must have at most 25 characters: \" ++ String.fromInt len)\n                        else\n                            Ok (Username s)\n                    )\n            , toString =\n                \\(Username s) -> s\n            }\n\n    toResult (fromString username \"abc\") == Ok (Username \"abc\")\n\n    toResult (fromString username \"ab\") == Err [ customError \"The username must have at least 3 characters: 2\" ]\n\n    toResult (fromString username \"abcdefghijklmnopqrstuvwxyz\") == Err [ customError \"The username must have at most 25 characters: 26\" ]\n\n","type":"String.String -> Field.Error"},{"name":"customSubsetOfBool","comment":" Customize the options.\n\n    import Set\n\n    mySubsetOfBool : (Bool -> Bool) -> Type Bool\n    mySubsetOfBool =\n        customSubsetOfBool\n            { truthy = Set.fromList [ \"#t\" ]\n            , falsy = Set.fromList [ \"#f\" ]\n            , toString =\n                \\b ->\n                    if b then\n                        \"#t\"\n\n                    else\n                        \"#f\"\n            , caseSensitive = True\n            }\n\n    myBool : Type Bool\n    myBool =\n        mySubsetOfBool (always True)\n\n    myTrue : Type Bool\n    myTrue =\n        mySubsetOfBool ((==) True)\n\n    myFalse : Type Bool\n    myFalse =\n        mySubsetOfBool ((==) False)\n\n","type":"Field.CustomBoolOptions -> (Basics.Bool -> Basics.Bool) -> Field.Type Basics.Bool"},{"name":"customType","comment":" Define a new field type.\n\n    type Email = Email String\n\n    email : Type Email\n    email =\n        customType\n            { fromString =\n                trim\n                    (\\s ->\n                        if s |> String.contains \"@\" then\n                            Ok (Email s)\n                        else\n                            Err (syntaxError s)\n                    )\n            , toString =\n                \\(Email s) -> s\n            }\n\n    (typeToConverters email).fromString \"a@b.c\" == Ok (Email \"a@b.c\")\n\n    (typeToConverters email).fromString \" a@b.c \" == Ok (Email \"a@b.c\")\n\n    (typeToConverters email).fromString \"\" == Err blankError\n\n    (typeToConverters email).fromString \" ab.c \" == Err (syntaxError \"ab.c\")\n\n","type":"{ fromString : String.String -> Result.Result Field.Error a, toString : a -> String.String } -> Field.Type a"},{"name":"defaultBoolToString","comment":"\n\n    defaultBoolToString True == \"true\"\n\n    defaultBoolToString False == \"false\"\n\n","type":"Basics.Bool -> String.String"},{"name":"defaultCustomBoolOptions","comment":" The default options used by [`bool`](#bool), [`true`](#true), and [`false`](#false).\n\n    { truthy = defaultTruthy\n    , falsy = defaultFalsy\n    , toString = defaultBoolToString\n    , caseSensitive = False\n    }\n\n","type":"Field.CustomBoolOptions"},{"name":"defaultFalsy","comment":" The default falsy strings: `\"false\"`, `\"0\"`, `\"no\"`, `\"off\"`, `\"n\"`, and `\"disabled\"`.\n","type":"Set.Set String.String"},{"name":"defaultTruthy","comment":" The default truthy strings: `\"true\"`, `\"1\"`, `\"yes\"`, `\"on\"`, `\"y\"`, and `\"enabled\"`.\n","type":"Set.Set String.String"},{"name":"empty","comment":" Initialize a new field from the given type and the empty string.\n\nFor all field types, `t`, `empty t` is equivalent to `fromString t \"\"`.\n\n","type":"Field.Type a -> Field.Field a"},{"name":"errorToString","comment":" Convert your errors to user-friendly error messages.\n\n    toErrorMessage : Error -> String\n    toErrorMessage =\n        errorToString\n            { onBlank = \"It is required\"\n            , onSyntaxError = (++) \"It is incorrectly formatted: \"\n            , onValidationError = (++) \"It is invalid: \"\n            }\n\n    toErrorMessage blankError == \"It is required\"\n\n    toErrorMessage (syntaxError \"five\") == \"It is incorrectly formatted: five\"\n\n    toErrorMessage (validationError \"-1\") == \"It is invalid: -1\"\n\n    toErrorMessage (customError \"The username must have at least 3 characters: 2\") == \"The username must have at least 3 characters: 2\"\n\n","type":"{ onBlank : String.String, onSyntaxError : String.String -> String.String, onValidationError : String.String -> String.String } -> Field.Error -> String.String"},{"name":"false","comment":" Any case-insensitive [`defaultFalsy`](#defaultFalsy) trimmed string.\n\n    (typeToConverters false).fromString \"true\" == Err (validationError \"true\")\n\n    (typeToConverters false).fromString \"TrUe\" == Err (validationError \"true\")\n\n    (typeToConverters false).fromString \"false\" == Ok False\n\n    (typeToConverters false).fromString \"fAlSe\" == Ok False\n\n    (typeToConverters false).fromString \" 1 \" == Err (validationError \"true\")\n\n    (typeToConverters false).fromString \" 0 \" == Ok False\n\n    (typeToConverters false).fromString \"\" == Err blankError\n\n    (typeToConverters false).fromString \"not\" == Err (syntaxError \"not\")\n\n","type":"Field.Type Basics.Bool"},{"name":"firstError","comment":"\n\n    fromString string \"A string\"\n        |> firstError\n        |> (==) Nothing\n\n    fromString string \"A string\"\n        |> setCustomErrors \"First error\" [ \"Second error\", \"Third error\" ]\n        |> firstError\n        |> (==) (Just <| customError \"First error\")\n\n","type":"Field.Field a -> Maybe.Maybe Field.Error"},{"name":"float","comment":" Any `Float` that can be parsed from a trimmed string using `String.toFloat`.\n\n    (typeToConverters float).fromString \"-0.1\" == Ok -0.1\n\n    (typeToConverters float).fromString \"0\" == Ok 0\n\n    (typeToConverters float).fromString \"1.1\" == Ok 1.1\n\n    (typeToConverters float).fromString \" 3.14 \" == Ok 3.14\n\n    (typeToConverters float).fromString \"\" == Err blankError\n\n    (typeToConverters float).fromString \"pi\" == Err (syntaxError \"pi\")\n\n","type":"Field.Type Basics.Float"},{"name":"fromString","comment":" Initialize a new field from the given type and string.\n\n    toMaybe (fromString bool \"enabled\") == Just True\n\n","type":"Field.Type a -> String.String -> Field.Field a"},{"name":"fromValue","comment":" Initialize a new field from the given type and value.\n\n    toMaybe (fromValue char 'a') == Just 'a'\n\n","type":"Field.Type a -> a -> Field.Field a"},{"name":"int","comment":" Any `Int` that can be parsed from a trimmed string using `String.toInt`.\n\n    (typeToConverters int).fromString \"-1\" == Ok -1\n\n    (typeToConverters int).fromString \"0\" == Ok 0\n\n    (typeToConverters int).fromString \"1\" == Ok 1\n\n    (typeToConverters int).fromString \" 5 \" == Ok 5\n\n    (typeToConverters int).fromString \"\" == Err blankError\n\n    (typeToConverters int).fromString \"five\" == Err (syntaxError \"five\")\n\n","type":"Field.Type Basics.Int"},{"name":"isBlank","comment":" Determine whether or not the raw string is equal to a blank string.\n\n    isBlank (empty int) == True\n\n    isBlank (fromString int \"   \") == True\n\n    isBlank (fromString int \"1\") == False\n\n","type":"Field.Field a -> Basics.Bool"},{"name":"isClean","comment":" `True` if the field is [clean](#state).\n\n    isClean (empty int) == True\n\n    isClean (fromString int \"1\") == True\n\n    isClean (setFromString \"1\" (empty int)) == False\n\n","type":"Field.Field a -> Basics.Bool"},{"name":"isDirty","comment":" `True` if the field is [dirty](#state). `isDirty f` is equivalent to `not (isClean f)`.\n\n    isDirty (empty int) == False\n\n    isDirty (fromString int \"1\") == False\n\n    isDirty (setFromString \"1\" (empty int)) == True\n\n","type":"Field.Field a -> Basics.Bool"},{"name":"isEmpty","comment":" Determine whether or not the raw string is equal to the empty string.\n\n    isEmpty (empty int) == True\n\n    isEmpty (fromString int \"   \") == False\n\n    isEmpty (fromString int \"1\") == False\n\n","type":"Field.Field a -> Basics.Bool"},{"name":"isInvalid","comment":" `True` if the field has errors. `isInvalid f` is equivalent to `not (isValid f)`.\n\n    isInvalid (empty int) == True\n\n    isInvalid (fromString int \"1\") == False\n\n","type":"Field.Field a -> Basics.Bool"},{"name":"isNonBlank","comment":" `isNonBlank f` is equivalent to `not (isBlank f)`.\n\n    isNonBlank (empty int) == False\n\n    isNonBlank (fromString int \"   \") == False\n\n    isNonBlank (fromString int \"1\") == True\n\n","type":"Field.Field a -> Basics.Bool"},{"name":"isNonEmpty","comment":" `isNonEmpty f` is equivalent to `not (isEmpty f)`.\n\n    isNonEmpty (empty int) == False\n\n    isNonEmpty (fromString int \"   \") == True\n\n    isNonEmpty (fromString int \"1\") == True\n\n","type":"Field.Field a -> Basics.Bool"},{"name":"isValid","comment":" `True` if the field does not have any errors.\n\n    isValid (empty int) == False\n\n    isValid (fromString int \"1\") == True\n\n","type":"Field.Field a -> Basics.Bool"},{"name":"lastError","comment":"\n\n    fromString string \"A string\"\n        |> lastError\n        |> (==) Nothing\n\n    fromString string \"A string\"\n        |> setCustomErrors \"First error\" [ \"Second error\", \"Third error\" ]\n        |> lastError\n        |> (==) (Just <| customError \"Third error\")\n\n","type":"Field.Field a -> Maybe.Maybe Field.Error"},{"name":"mapError","comment":" Apply a function to the error value of the field type. It's useful for unifying\nmultiple custom field errors under a single error type.\n\nLet's continue with the example from [`customError`](#customError) and incorporate an `Age` type.\n\n    type Age = Age Int\n\n    age : Type Age\n    age =\n        customType\n            { fromString =\n                (typeToConverters positiveInt).fromString\n                    >> Result.andThen\n                        (\\n ->\n                            if n < 21 then\n                                Err (customError <| \"The age must be at least 21 years: \" ++ String.fromInt n)\n                            else if n > 65 then\n                                Err (customError <| \"The age must be at most 65 years: \" ++ String.fromInt n)\n                            else\n                                Ok (Age n)\n                        )\n            , toString =\n                \\(Age n) -> String.fromInt n\n            }\n\n    --\n    -- 1. The single error type under which we will unify the username and age field errors.\n    --\n    type Errors\n        = MyUsernameError Error\n        | MyAgeError Error\n\n    usernameField : Field Username\n    usernameField = fromString username \"ab\"\n\n    ageField : Field Age\n    ageField = fromString age \"67\"\n\n    type alias UserDetails = { username : Username, age : Age }\n\n    --\n    -- 2. We use mapError in order to validate both fields at the same time.\n    --\n    resultUserDetails =\n        validationToResult <|\n            validate2\n                UserDetails\n                (usernameField |> mapError MyUsernameError)\n                (ageField |> mapError MyAgeError)\n\n    resultUserDetails == Err [ MyUsernameError (customError \"The username must have at least 3 characters: 2\"), MyAgeError (customError \"The age must be at most 65 years: 67\") ]\n\n","type":"(x -> y) -> Field.Advanced.Field x a -> Field.Advanced.Field y a"},{"name":"negativeFloat","comment":" Any `Float`, `f`, that can be parsed from a trimmed string using `String.toFloat` such that `f < 0`.\n\n    (typeToConverters negativeFloat).fromString \"-0.1\" == Ok -0.1\n\n    (typeToConverters negativeFloat).fromString \"0\" == Err (validationError \"0\")\n\n    (typeToConverters negativeFloat).fromString \"1.1\" == Err (validationError \"1.1\")\n\n    (typeToConverters negativeFloat).fromString \" 3.14 \" == Err (validationError \"3.14\")\n\n    (typeToConverters negativeFloat).fromString \"\" == Err blankError\n\n    (typeToConverters negativeFloat).fromString \"pi\" == Err (syntaxError \"pi\")\n\n","type":"Field.Type Basics.Float"},{"name":"negativeInt","comment":" Any `Int`, `n`, that can be parsed from a trimmed string using `String.toInt` such that `n < 0`.\n\n    (typeToConverters negativeInt).fromString \"-1\" == Ok -1\n\n    (typeToConverters negativeInt).fromString \"0\" == Err (validationError \"0\")\n\n    (typeToConverters negativeInt).fromString \"1\" == Err (validationError \"1\")\n\n    (typeToConverters negativeInt).fromString \" 5 \" == Err (validationError \"5\")\n\n    (typeToConverters negativeInt).fromString \"\" == Err blankError\n\n    (typeToConverters negativeInt).fromString \"five\" == Err (syntaxError \"five\")\n\n","type":"Field.Type Basics.Int"},{"name":"nonBlankString","comment":" Any non-blank trimmed `String` is accepted.\n\n    (typeToConverters nonBlankString).fromString \"Hello\" == Ok \"Hello\"\n\n    (typeToConverters nonBlankString).fromString \" Hello \" == Ok \"Hello\"\n\n    (typeToConverters nonBlankString).fromString \"\" == Err blankError\n\n    (typeToConverters nonBlankString).fromString \" \\n\\t \" == Err blankError\n\n","type":"Field.Type String.String"},{"name":"nonEmptyString","comment":" Any `String` except the empty string is accepted. The string is not trimmed.\n\n    (typeToConverters nonEmptyString).fromString \"Hello\" == Ok \"Hello\"\n\n    (typeToConverters nonEmptyString).fromString \" Hello \" == Ok \" Hello \"\n\n    (typeToConverters nonEmptyString).fromString \"\" == Err blankError\n\n    (typeToConverters nonEmptyString).fromString \" \\n\\t \" == Ok \" \\n\\t \"\n\n","type":"Field.Type String.String"},{"name":"nonNegativeFloat","comment":" Any `Float`, `f`, that can be parsed from a trimmed string using `String.toFloat` such that `f >= 0`.\n\n    (typeToConverters nonNegativeFloat).fromString \"-0.1\" == Err (validationError \"-0.1\")\n\n    (typeToConverters nonNegativeFloat).fromString \"0\" == Ok 0\n\n    (typeToConverters nonNegativeFloat).fromString \"1.1\" == Ok 1.1\n\n    (typeToConverters nonNegativeFloat).fromString \" 3.14 \" == Ok 3.14\n\n    (typeToConverters nonNegativeFloat).fromString \"\" == Err blankError\n\n    (typeToConverters nonNegativeFloat).fromString \"pi\" == Err (syntaxError \"pi\")\n\n","type":"Field.Type Basics.Float"},{"name":"nonNegativeInt","comment":" Any `Int`, `n`, that can be parsed from a trimmed string using `String.toInt` such that `n >= 0`.\n\n    (typeToConverters nonNegativeInt).fromString \"-1\" == Err (validationError \"-1\")\n\n    (typeToConverters nonNegativeInt).fromString \"0\" == Ok 0\n\n    (typeToConverters nonNegativeInt).fromString \"1\" == Ok 1\n\n    (typeToConverters nonNegativeInt).fromString \" 5 \" == Ok 5\n\n    (typeToConverters nonNegativeInt).fromString \"\" == Err blankError\n\n    (typeToConverters nonNegativeInt).fromString \"five\" == Err (syntaxError \"five\")\n\n","type":"Field.Type Basics.Int"},{"name":"nonPositiveFloat","comment":" Any `Float`, `f`, that can be parsed from a trimmed string using `String.toFloat` such that `f <= 0`.\n\n    (typeToConverters nonPositiveFloat).fromString \"-0.1\" == Ok -0.1\n\n    (typeToConverters nonPositiveFloat).fromString \"0\" == Ok 0\n\n    (typeToConverters nonPositiveFloat).fromString \"1.1\" == Err (validationError \"1.1\")\n\n    (typeToConverters nonPositiveFloat).fromString \" 3.14 \" == Err (validationError \"3.14\")\n\n    (typeToConverters nonPositiveFloat).fromString \"\" == Err blankError\n\n    (typeToConverters nonPositiveFloat).fromString \"pi\" == Err (syntaxError \"pi\")\n\n","type":"Field.Type Basics.Float"},{"name":"nonPositiveInt","comment":" Any `Int`, `n`, that can be parsed from a trimmed string using `String.toInt` such that `n <= 0`.\n\n    (typeToConverters nonPositiveInt).fromString \"-1\" == Ok -1\n\n    (typeToConverters nonPositiveInt).fromString \"0\" == Ok 0\n\n    (typeToConverters nonPositiveInt).fromString \"1\" == Err (validationError \"1\")\n\n    (typeToConverters nonPositiveInt).fromString \" 5 \" == Err (validationError \"5\")\n\n    (typeToConverters nonPositiveInt).fromString \"\" == Err blankError\n\n    (typeToConverters nonPositiveInt).fromString \"five\" == Err (syntaxError \"five\")\n\n","type":"Field.Type Basics.Int"},{"name":"optional","comment":" Make any field type optional.\n\n    maybePositiveInt = optional positiveInt\n\n    (typeToConverters maybePositiveInt).fromString \"-1\" == Err (validationError \"-1\")\n\n    (typeToConverters maybePositiveInt).fromString \"0\" == Err (validationError \"0\")\n\n    (typeToConverters maybePositiveInt).fromString \"1\" == Ok (Just 1)\n\n    (typeToConverters maybePositiveInt).fromString \" 5 \" == Ok (Just 5)\n\n    (typeToConverters maybePositiveInt).fromString \"\" == Ok Nothing\n\n    (typeToConverters maybePositiveInt).fromString \"five\" == Err (syntaxError \"five\")\n\n","type":"Field.Type a -> Field.Type (Maybe.Maybe a)"},{"name":"positiveFloat","comment":" Any `Float`, `f`, that can be parsed from a trimmed string using `String.toFloat` such that `f > 0`.\n\n    (typeToConverters positiveFloat).fromString \"-0.1\" == Err (validationError \"-0.1\")\n\n    (typeToConverters positiveFloat).fromString \"0\" == Err (validationError \"0\")\n\n    (typeToConverters positiveFloat).fromString \"1.1\" == Ok 1.1\n\n    (typeToConverters positiveFloat).fromString \" 3.14 \" == Ok 3.14\n\n    (typeToConverters positiveFloat).fromString \"\" == Err blankError\n\n    (typeToConverters positiveFloat).fromString \"pi\" == Err (syntaxError \"pi\")\n\n","type":"Field.Type Basics.Float"},{"name":"positiveInt","comment":" Any `Int`, `n`, that can be parsed from a trimmed string using `String.toInt` such that `n > 0`.\n\n    (typeToConverters positiveInt).fromString \"-1\" == Err (validationError \"-1\")\n\n    (typeToConverters positiveInt).fromString \"0\" == Err (validationError \"0\")\n\n    (typeToConverters positiveInt).fromString \"1\" == Ok 1\n\n    (typeToConverters positiveInt).fromString \" 5 \" == Ok 5\n\n    (typeToConverters positiveInt).fromString \"\" == Err blankError\n\n    (typeToConverters positiveInt).fromString \"five\" == Err (syntaxError \"five\")\n\n","type":"Field.Type Basics.Int"},{"name":"setCustomError","comment":"\n\n    field = empty int\n\n    error = customError \"Not an integer\"\n\n    toResult (setCustomError \"Not an integer\" field) == Err [ error ]\n\n","type":"String.String -> Field.Field a -> Field.Field a"},{"name":"setCustomErrors","comment":" ","type":"String.String -> List.List String.String -> Field.Field a -> Field.Field a"},{"name":"setError","comment":"\n\n    field = empty int\n\n    error = customError \"Not an integer\"\n\n    toResult (setError error field) == Err [ error ]\n\n","type":"Field.Error -> Field.Field a -> Field.Field a"},{"name":"setErrors","comment":" ","type":"Field.Error -> List.List Field.Error -> Field.Field a -> Field.Field a"},{"name":"setFromString","comment":"\n\n    field = empty positiveInt\n\n    toResult field == Err [ blankError ]\n\n    toResult (setFromString \"-1\" field) == Err [ validationError \"-1\" ]\n\n    toResult (setFromString \"0\" field) == Err [ validationError \"0\" ]\n\n    toResult (setFromString \"1\" field) == Ok 1\n\n    toResult (setFromString \" 5 \" field) == Ok 5\n\n    toResult (setFromString \"   \" field) == Err [ blankError ]\n\n    toResult (setFromString \"five\" field) == Err [ syntaxError \"five\" ]\n\n","type":"String.String -> Field.Field a -> Field.Field a"},{"name":"setFromValue","comment":"\n\n    field = empty (optional positiveInt)\n\n    toResult field == Ok Nothing\n\n    toResult (setFromValue (Just -1) field) == Err [ validationError \"-1\" ]\n\n    toResult (setFromValue (Just 0) field) == Err [ validationError \"0\" ]\n\n    toResult (setFromValue (Just 1) field) == Ok (Just 1)\n\n    toResult (setFromValue (Just 5) field) == Ok (Just 5)\n\n    toResult (setFromValue Nothing field) == Ok Nothing\n\n","type":"a -> Field.Field a -> Field.Field a"},{"name":"string","comment":" Any trimmed `String` is accepted. It never fails.\n\n    (typeToConverters string).fromString \"Hello\" == Ok \"Hello\"\n\n    (typeToConverters string).fromString \" Hello \" == Ok \"Hello\"\n\n    (typeToConverters string).fromString \"\" == Ok \"\"\n\n    (typeToConverters string).fromString \" \\n\\t \" == Ok \"\"\n\n","type":"Field.Advanced.Type e String.String"},{"name":"subsetOfChar","comment":" Any `Char`, `c`, that can be parsed from a string of exactly length one such that `isGood c` is `True`. The string is not trimmed.\n\n    digit = subsetOfChar Char.isDigit\n\n    (typeToConverters digit).fromString \"a\" == Err (validationError \"a\")\n\n    (typeToConverters digit).fromString \"A\" == Err (validationError \"A\")\n\n    (typeToConverters digit).fromString \"8\" == Ok '8'\n\n    (typeToConverters digit).fromString \"\\n\" == Err (validationError \"\\n\")\n\n    (typeToConverters digit).fromString \"\" == Err blankError\n\n    (typeToConverters digit).fromString \" \" == Err (validationError \" \")\n\n    (typeToConverters digit).fromString \"  \" == Err blankError\n\n    (typeToConverters digit).fromString \"aA\" == Err (syntaxError \"aA\")\n\n    (typeToConverters digit).fromString \" 2 \" == Err (syntaxError \" 2 \")\n\n","type":"(Char.Char -> Basics.Bool) -> Field.Type Char.Char"},{"name":"subsetOfFloat","comment":" Any `Float`, `f`, that can be parsed from a trimmed string using `String.toFloat` such that `isGood f` is `True`.\n\n    roundsToTwo = subsetOfFloat (round >> (==) 2)\n\n    (typeToConverters roundsToTwo).fromString \"1.3\" == Err (validationError \"1.3\")\n\n    (typeToConverters roundsToTwo).fromString \"1.5\" == Ok 1.5\n\n    (typeToConverters roundsToTwo).fromString \"1.8\" == Ok 1.8\n\n    (typeToConverters roundsToTwo).fromString \"2.0\" == Ok 2.0\n\n    (typeToConverters roundsToTwo).fromString \"2.3\" == Ok 2.3\n\n    (typeToConverters roundsToTwo).fromString \"2.5\" == Err (validationError \"2.5\")\n\n    (typeToConverters roundsToTwo).fromString \"3.14\" == Err (validationError \"3.14\")\n\n    (typeToConverters roundsToTwo).fromString \"\" == Err blankError\n\n    (typeToConverters roundsToTwo).fromString \"pi\" == Err (syntaxError \"pi\")\n\n","type":"(Basics.Float -> Basics.Bool) -> Field.Type Basics.Float"},{"name":"subsetOfInt","comment":" Any `Int`, `n`, that can be parsed from a trimmed string using `String.toInt` such that `isGood n` is `True`.\n\n    evens = subsetOfInt (modBy 2 >> (==) 0)\n\n    (typeToConverters evens).fromString \"-2\" == Ok -2\n\n    (typeToConverters evens).fromString \"-1\" == Err (validationError \"-1\")\n\n    (typeToConverters evens).fromString \"0\" == Ok 0\n\n    (typeToConverters evens).fromString \"1\" == Err (validationError \"1\")\n\n    (typeToConverters evens).fromString \" 2 \" == Ok 2\n\n    (typeToConverters evens).fromString \"\" == Err blankError\n\n    (typeToConverters evens).fromString \"five\" == Err (syntaxError \"five\")\n\n","type":"(Basics.Int -> Basics.Bool) -> Field.Type Basics.Int"},{"name":"subsetOfNonBlankString","comment":" Any non-blank trimmed `String`, `s`, is accepted if `isGood s` is `True`.\n\n    atMost3 = subsetOfNonBlankString (String.length >> (>=) 3)\n\n    (typeToConverters atMost3).fromString \"p\" == Ok \"p\"\n\n    (typeToConverters atMost3).fromString \"pi\" == Ok \"pi\"\n\n    (typeToConverters atMost3).fromString \"pie\" == Ok \"pie\"\n\n    (typeToConverters atMost3).fromString \" pie \" == Ok \"pie\"\n\n    (typeToConverters atMost3).fromString \"Hello\" == Err (validationError \"Hello\")\n\n    (typeToConverters atMost3).fromString \" Hello \" == Err (validationError \"Hello\")\n\n    (typeToConverters atMost3).fromString \"\" == Err blankError\n\n    (typeToConverters atMost3).fromString \" \\n\\t \" == Err blankError\n\n","type":"(String.String -> Basics.Bool) -> Field.Type String.String"},{"name":"subsetOfNonEmptyString","comment":" Any non-empty `String`, `s`, is only accepted if `isGood s` is `True`. The string is not trimmed.\n\n    hello = subsetOfNonEmptyString ((==) \"Hello\")\n\n    (typeToConverters hello).fromString \"Hello\" == Ok \"Hello\"\n\n    (typeToConverters hello).fromString \" Hello \" == Err (validationError \" Hello \")\n\n    (typeToConverters hello).fromString \"\" == Err blankError\n\n    (typeToConverters hello).fromString \" \\n\\t \" == Err (validationError \" \\n\\t \")\n\n","type":"(String.String -> Basics.Bool) -> Field.Type String.String"},{"name":"subsetOfString","comment":" Any trimmed `String`, `s`, is accepted if `isGood s` is `True`.\n\n    atMost3 = subsetOfString (String.length >> (>=) 3)\n\n    (typeToConverters atMost3).fromString \"p\" == Ok \"p\"\n\n    (typeToConverters atMost3).fromString \"pi\" == Ok \"pi\"\n\n    (typeToConverters atMost3).fromString \"pie\" == Ok \"pie\"\n\n    (typeToConverters atMost3).fromString \" pie \" == Ok \"pie\"\n\n    (typeToConverters atMost3).fromString \"Hello\" == Err (validationError \"Hello\")\n\n    (typeToConverters atMost3).fromString \" Hello \" == Err (validationError \"Hello\")\n\n    (typeToConverters atMost3).fromString \"\" == Ok \"\"\n\n    (typeToConverters atMost3).fromString \" \\n\\t \" == Ok \"\"\n\n","type":"(String.String -> Basics.Bool) -> Field.Type String.String"},{"name":"subsetOfType","comment":" Accept a subset of the values accepted by the given type.\n\n    positiveEvens = subsetOfType (modBy 2 >> (==) 0) positiveInt\n\n    (typeToConverters positiveEvens).fromString \" 2 \" == Ok 2\n\n    (typeToConverters positiveEvens).fromString \"-2\" == Err (validationError \"-2\")\n\n    (typeToConverters positiveEvens).fromString \"-1\" == Err (validationError \"-1\")\n\n    (typeToConverters positiveEvens).fromString \"0\" == Err (validationError \"0\")\n\n    (typeToConverters positiveEvens).fromString \"1\" == Err (validationError \"1\")\n\n    (typeToConverters positiveEvens).fromString \"\" == Err blankError\n\n    (typeToConverters positiveEvens).fromString \"five\" == Err (syntaxError \"five\")\n\n","type":"(a -> Basics.Bool) -> Field.Type a -> Field.Type a"},{"name":"succeed","comment":" Useful to use with [`applyValidation`](#applyValidation).\n\nLet `f` represent a function that takes `N >= 1` arguments. Then,\n\n    succeed f\n        |> applyValidation field1\n        |> applyValidation field2\n        |> ...\n        |> applyValidation fieldN\n\napplies `f` to `N` arguments as long as no field has an error.\n\n","type":"a -> Field.Validation e a"},{"name":"syntaxError","comment":" Indicates that the user's input string cannot be converted to the desired type.\n\n    toResult (fromString positiveInt \"five\") == Err [ syntaxError \"five\" ]\n\nThe string used in the syntax error is the trimmed user's input string that caused the error.\n\n    toResult (fromString positiveInt \" five\\n \\t\") == Err [ syntaxError \"five\" ]\n\n","type":"String.String -> Field.Error"},{"name":"toConverters","comment":" ","type":"Field.Field a -> Field.Converters a"},{"name":"toMaybe","comment":"\n\n    toMaybe (empty int) == Nothing\n\n    toMaybe (fromString int \"5\") == Just 5\n\n","type":"Field.Field a -> Maybe.Maybe a"},{"name":"toRawString","comment":"\n\n    toRawString (empty int) == \"\"\n\n    toRawString (fromString int \" \\n5  \\t \\n\") == \" \\n5  \\t \\n\"\n\n","type":"Field.Field a -> String.String"},{"name":"toResult","comment":"\n\n    toResult (empty int) == Err [ blankError ]\n\n    toResult (fromString int \"5\") == Ok 5\n\n","type":"Field.Field a -> Result.Result (List.List Field.Error) a"},{"name":"toString","comment":"\n\n    toString (empty int) == \"\"\n\n    toString (fromString int \" \\n5  \\t \\n\") == \"5\"\n\n","type":"Field.Field a -> String.String"},{"name":"toValidation","comment":"\n\n    import Validation as V\n\n    toValidation (empty int) == V.fail blankError\n\n    toValidation (fromString int \"5\") == V.succeed 5\n\n","type":"Field.Field a -> Field.Validation Field.Error a"},{"name":"trim","comment":" Get rid of whitespace on both sides of a string.\n\nIf the trimmed string is empty return [`blankError`](#blankError),\notherwise apply the given function to the trimmed string.\n\nIt is useful when you're defining a custom field type.\n\n    type Username = Username String\n\n    username : Type Username\n    username =\n        customType\n            { fromString =\n                trim\n                    (\\s ->\n                        let\n                            len =\n                                String.length s\n                        in\n                        if len < 3 then\n                            Err <| customError \"The username must have at least 3 characters\"\n                        else if len > 25 then\n                            Err <| customError \"The username must have at most 25 characters\"\n                        else\n                            Ok (Username s)\n                    )\n            , toString =\n                \\(Username s) -> s\n            }\n\n\n    toResult (fromString username \"abc\") == Ok (Username \"abc\")\n\n    toResult (fromString username \"ab\") == Err [ customError \"The username must have at least 3 characters\" ]\n\n    toResult (fromString username \"abcdefghijklmnopqrstuvwxyz\") == Err [ customError \"The username must have at most 25 characters\" ]\n\n","type":"(String.String -> Result.Result Field.Error a) -> String.String -> Result.Result Field.Error a"},{"name":"true","comment":" Any case-insensitive [`defaultTruthy`](#defaultTruthy) trimmed string.\n\n    (typeToConverters true).fromString \"true\" == Ok True\n\n    (typeToConverters true).fromString \"TrUe\" == Ok True\n\n    (typeToConverters true).fromString \"false\" == Err (validationError \"false\")\n\n    (typeToConverters true).fromString \"fAlSe\" == Err (validationError \"false\")\n\n    (typeToConverters true).fromString \" 1 \" == Ok True\n\n    (typeToConverters true).fromString \" 0 \" == Err (validationError \"false\")\n\n    (typeToConverters true).fromString \"\" == Err blankError\n\n    (typeToConverters true).fromString \"not\" == Err (syntaxError \"not\")\n\n","type":"Field.Type Basics.Bool"},{"name":"typeToConverters","comment":" ","type":"Field.Type a -> Field.Converters a"},{"name":"validate","comment":" Apply a function to the processed value of a field. If the field is valid,\nthe value will be converted. If the field is invalid, the same error will be\npropagated.\n\n    import Validation as V\n\n    validate sqrt (fromString float \"4.0\") == V.succeed 2.0\n\n    validate sqrt (fromString float \"\") == V.fail blankError\n\n","type":"(a -> value) -> Field.Advanced.Field x a -> Field.Validation x value"},{"name":"validate2","comment":" Apply a function if both fields are valid. If not, the errors will be accumulated\nin order of failure.\n\n    import Validation as V\n\n    validate2 max (fromString int \"42\") (fromString int \"13\") == V.succeed 42\n\n    validate2 max (fromString int \"x\") (fromString int \"13\") == V.fail (syntaxError \"x\")\n\n    validate2 max (fromString int \"42\") (fromString int \"y\") == V.fail (syntaxError \"y\")\n\n    validate2 max (fromString int \"x\") (fromString int \"y\") == V.failWithErrors (syntaxError \"x\") [ syntaxError \"y\" ]\n\n","type":"(a -> b -> value) -> Field.Advanced.Field x a -> Field.Advanced.Field x b -> Field.Validation x value"},{"name":"validate3","comment":" Apply a function if all three fields are valid. If not, the errors will be accumulated\nin order of failure.\n\n    validate3 (\\a b c -> a + b + c) (fromString int \"1\") (fromString int \"2\") (fromString int \"3\") == V.succeed 6\n\n    validate3 (\\a b c -> a + b + c) (fromString int \"1\") (fromString int \"y\") (fromString int \"3\") == V.fail (syntaxError \"y\")\n\n    validate3 (\\a b c -> a + b + c) (fromString int \"x\") (fromString int \"2\") (fromString int \"z\") == V.failWithErrors (syntaxError \"x\") [ syntaxError \"z\" ]\n\n    validate3 (\\a b c -> a + b + c) (fromString int \"x\") (fromString int \"y\") (fromString int \"z\") == V.failWithErrors (syntaxError \"x\") [ syntaxError \"y\", syntaxError \"z\" ]\n\n","type":"(a -> b -> c -> value) -> Field.Advanced.Field x a -> Field.Advanced.Field x b -> Field.Advanced.Field x c -> Field.Validation x value"},{"name":"validate4","comment":" ","type":"(a -> b -> c -> d -> value) -> Field.Advanced.Field x a -> Field.Advanced.Field x b -> Field.Advanced.Field x c -> Field.Advanced.Field x d -> Field.Validation x value"},{"name":"validate5","comment":" ","type":"(a -> b -> c -> d -> e -> value) -> Field.Advanced.Field x a -> Field.Advanced.Field x b -> Field.Advanced.Field x c -> Field.Advanced.Field x d -> Field.Advanced.Field x e -> Field.Validation x value"},{"name":"validationError","comment":" Indicates that the user's input string was successfully converted to a value of the desired type but\nthat the value wasn't contained in the subset of values under consideration.\n\n    toResult (fromString positiveInt \"0\") == Err [ validationError \"0\" ]\n\n    toResult (fromString positiveInt \"-1\") == Err [ validationError \"-1\" ]\n\nLet `v` represent the value to which the user's input string was successfully converted. The string used\nin the validation error is the string returned by the `toString` function of the field's type when it's\napplied to `v`.\n\n    v : Int\n    v = -1\n\n    field : Field Int\n    field = fromString positiveInt \" -1 \\n \\t\"\n\n    negativeOne : String\n    negativeOne = (toConverters field).toString v\n\n    toResult field == Err [ validationError negativeOne ]\n\nIn the above example, the user's input string, `\" -1 \\n \\t\"`, would be successfully converted to the\nvalue, `-1`, but `-1` is not a positive integer. Hence, the string representation of `-1` as determined\nby `(toConverters field).toString` is used in the validation error.\n\n","type":"String.String -> Field.Error"},{"name":"validationToResult","comment":" Convert from a `Validaton` to a `Result` for convenience.\n\nUseful to use with [`applyValidation`](#applyValidation).\n\nLet `f` represent a function that takes `N >= 1` arguments. Then,\n\n    succeed f\n        |> applyValidation field1\n        |> applyValidation field2\n        |> ...\n        |> applyValidation fieldN\n        |> validationToResult\n\napplies `f` to `N` arguments as long as no field has an error.\n\n","type":"Field.Validation e a -> Result.Result (List.List e) a"}],"binops":[]},{"name":"Field.Advanced","comment":"\n\n\n# Field\n\n@docs Field\n\n\n# Type\n\n@docs Type\n\n\n# Primitive\n\nElm's primitive types: `Int`, `Float`, `Bool`, `Char`, and `String`, all have corresponding field types.\n\n\n# Int\n\n@docs int, nonNegativeInt, positiveInt, nonPositiveInt, negativeInt, subsetOfInt, customSubsetOfInt\n\n\n# Float\n\n@docs float, nonNegativeFloat, positiveFloat, nonPositiveFloat, negativeFloat, subsetOfFloat, customSubsetOfFloat\n\n\n# Bool\n\n@docs bool, true, false, customSubsetOfBool\n@docs CustomBoolOptions, defaultCustomBoolOptions, defaultTruthy, defaultFalsy, defaultBoolToString\n\n\n# Char\n\n@docs char, subsetOfChar, customSubsetOfChar\n\n\n# String\n\nA **blank** string is either the empty string or a non-empty string consisting entirely of whitespace characters.\n\nThe empty string: `\"\"`\n\nSome blank strings: `\"\"`, `\" \"`, `\"  \"`, `\" \\t \"`, `\"\\n \\t \\r\"`\n\n@docs string, subsetOfString, customSubsetOfString\n@docs nonEmptyString, subsetOfNonEmptyString, customSubsetOfNonEmptyString\n@docs nonBlankString, subsetOfNonBlankString, customSubsetOfNonBlankString\n\n\n# User-defined\n\n@docs subsetOfType, customSubsetOfType, customType\n\n\n# Optional\n\n@docs optional, customOptional\n\n\n# Construct\n\nAll newly constructed fields are clean.\n\n@docs empty, fromString, fromValue\n\n\n# Change\n\nAny change to a field using these setter functions makes the field dirty. Furthermore,\nthese are the only functions that can dirty a field.\n\n@docs setFromString, setFromValue, setError, setErrors, setCustomError, setCustomErrors\n\n\n# Query\n\n@docs isEmpty, isNonEmpty, isBlank, isNonBlank, isClean, isDirty, isValid, isInvalid\n\n\n# Convert\n\n@docs toRawString, toString, toMaybe, toResult, toValidation, toType\n\n\n# State\n\n@docs State, toState\n\n\n# Validation\n\n@docs Validation, succeed, validationToResult\n\n\n# Converters\n\n@docs Converters, typeToConverters, toConverters\n\n\n# Validate\n\n@docs validate, validate2, validate3, validate4, validate5\n\n\n# Apply\n\n[`Field e`](#Field) is not applicative. However, `Maybe`, `Result e`, and `Validaton e` are all applicative.\nThe functions below attempt to make it convenient to do an applicative style of programming with fields by\nleveraging the applicative nature of `Maybe`, `Result e`, and `Validation e`.\n\n@docs applyMaybe, applyResult, applyValidation\n\n\n# String Helpers\n\n@docs trim, customTrim\n\n\n# Error\n\n@docs Error, defaultErrors, blankError, syntaxError, validationError, customError, errorToString, mapErrorType\n\n\n# Handle Errors\n\n@docs mapTypeError\n@docs mapError\n@docs firstError, lastError, allErrors\n\n","unions":[{"name":"Error","comment":" The error type returned by the built-in field types. It supports blank, syntax, validation, and custom validation errors.\n","args":["e"],"cases":[]},{"name":"Field","comment":" Tracks the raw `String` input and either the value of type `a` that the `String` represents or the errors of type `e` that can accumulate.\n","args":["e","a"],"cases":[]},{"name":"Type","comment":" Represents the type information for a field. It specifies how a `String` is converted to a type `a`\nand back to a `String`. Conversion may result in errors of type `e`.\n","args":["e","a"],"cases":[]}],"aliases":[{"name":"Converters","comment":" The collection of conversion functions that comprise a `Type`. The conversion functions are useful\nfor building new field types from existing field types.\n\n    type Positive\n        = Positive Int\n\n    fromString : String -> Result (Error e) Positive\n    fromString =\n        (typeToConverters positiveInt).fromString >> Result.map Positive\n\n    toString : Positive -> String\n    toString (Positive p) =\n        (typeToConverters positiveInt).toString p\n\n    fieldType : Type (Error e) Positive\n    fieldType =\n        customType\n            { fromString = fromString\n            , toString = toString\n            }\n\n","args":["e","a"],"type":"{ fromString : String.String -> Result.Result e a, fromValue : a -> Result.Result e a, toString : a -> String.String }"},{"name":"CustomBoolOptions","comment":" Used by [`customSubsetOfBool`](#customSubsetOfBool) to customize the options.\n","args":[],"type":"{ truthy : Set.Set String.String, falsy : Set.Set String.String, toString : Basics.Bool -> String.String, caseSensitive : Basics.Bool }"},{"name":"State","comment":" The internal state of a `Field`.\n\n`raw` contains the unprocessed `String` input.\n\n`processed` contains the result of parsing `raw`. Either it was successfully parsed into a type `a` or there were errors of type `e`.\n\n`clean` indicates whether or not the corresponding `Field` is considered to be **clean** or **dirty**.\n\nA `Field` is **clean** if it has never been changed, via one of `setFromString`, `setFromValue`, `setError`, `setErrors`, `setCustomError`,\nor `setCustomErrors`, after it was initially created. Otherwise, the `Field` is considered to be **dirty**.\n\n","args":["e","a"],"type":"{ raw : String.String, processed : Field.Advanced.Validation e a, clean : Basics.Bool }"},{"name":"Validation","comment":" Re-export the `Validation` type for convenience.\n","args":["e","a"],"type":"Validation.Validation e a"}],"values":[{"name":"allErrors","comment":"\n\n    fromString string \"A string\"\n        |> allErrors\n        |> (==) []\n\n    fromString string \"A string\"\n        |> setErrors \"First error\" [ \"Second error\", \"Third error\" ]\n        |> allErrors\n        |> (==) [ \"First error\", \"Second error\", \"Third error\" ]\n\n","type":"Field.Advanced.Field e a -> List.List e"},{"name":"applyMaybe","comment":" Suppose you want to use the values from multiple fields but you don't care about any of the\nerrors that are present.\n\n    type Primitives\n        = Positive Int Float Bool Char String\n        | NonPositive Int Float Bool Char String\n\n    let\n        maybePrimitives =\n            (\\n f b c s ->\n                if n > 0 then\n                    Positive n f b c s\n                else\n                    NonPositive n f b c s\n            )\n            |> Just\n            |> applyMaybe (fromString int \"5\")\n            |> applyMaybe (fromString float \"3.14\")\n            |> applyMaybe (fromValue bool True)\n            |> applyMaybe (fromValue char 'a')\n            |> applyMaybe (fromString string \"Hello\")\n    in\n    maybePrimitives == Just (Positive 5 3.14 True 'a' \"Hello\")\n\n","type":"Field.Advanced.Field e a -> Maybe.Maybe (a -> b) -> Maybe.Maybe b"},{"name":"applyResult","comment":" Suppose you want to use the values from multiple fields and you only care about the\nfirst error that occurs.\n\n    type Primitives\n        = Positive Int Float Bool Char String\n        | NonPositive Int Float Bool Char String\n\n    let\n        resultPrimitives =\n            (\\n f b c s ->\n                if n > 0 then\n                    Positive n f b c s\n                else\n                    NonPositive n f b c s\n            )\n            |> Ok\n            |> applyResult (fromString int \"5\")\n            |> applyResult (fromString float \"pi\")\n            |> applyResult (fromString bool \"not\")\n            |> applyResult (fromValue char 'a')\n            |> applyResult (fromString string \"Hello\")\n    in\n    resultPrimitives == Err [ syntaxError \"pi\" ]\n\n","type":"Field.Advanced.Field e a -> Result.Result (List.List e) (a -> b) -> Result.Result (List.List e) b"},{"name":"applyValidation","comment":" Suppose you want to use the values from multiple fields and you care about all the\nerrors that occur.\n\n    type Primitives\n        = Positive Int Float Bool Char String\n        | NonPositive Int Float Bool Char String\n\n    let\n        resultPrimitives =\n            (\\n f b c s ->\n                if n > 0 then\n                    Positive n f b c s\n                else\n                    NonPositive n f b c s\n            )\n            |> succeed\n            |> applyValidation (fromString int \"5\")\n            |> applyValidation (fromString float \"pi\")\n            |> applyValidation (fromString bool \"not\")\n            |> applyValidation (fromValue char 'a')\n            |> applyValidation (fromString string \"Hello\")\n            |> validationToResult\n    in\n    resultPrimitives == Err [ syntaxError \"pi\", syntaxError \"not\" ]\n\n","type":"Field.Advanced.Field e a -> Field.Advanced.Validation e (a -> b) -> Field.Advanced.Validation e b"},{"name":"blankError","comment":" Indicates that the user's input string is either the empty string or a string containing only whitespace characters.\n\n    toResult (fromString positiveInt \"\") == Err [ blankError ]\n\n    toResult (fromString positiveInt \"\\n\\t \") == Err [ blankError ]\n\n","type":"Field.Advanced.Error e"},{"name":"bool","comment":" Any case-insensitive [`defaultTruthy`](#defaultTruthy) or [`defaultFalsy`](#defaultFalsy) trimmed string.\n\n    (typeToConverters bool).fromString \"true\" == Ok True\n\n    (typeToConverters bool).fromString \"TrUe\" == Ok True\n\n    (typeToConverters bool).fromString \"false\" == Ok False\n\n    (typeToConverters bool).fromString \"fAlSe\" == Ok False\n\n    (typeToConverters bool).fromString \" 1 \" == Ok True\n\n    (typeToConverters bool).fromString \" 0 \" == Ok False\n\n    (typeToConverters bool).fromString \"\" == Err blankError\n\n    (typeToConverters bool).fromString \"not\" == Err (syntaxError \"not\")\n\n","type":"Field.Advanced.Type (Field.Advanced.Error e) Basics.Bool"},{"name":"char","comment":" Any `Char` that can be parsed from a string of exactly length one. The string is not trimmed.\n\n    (typeToConverters char).fromString \"a\" == Ok 'a'\n\n    (typeToConverters char).fromString \"A\" == Ok 'A'\n\n    (typeToConverters char).fromString \"8\" == Ok '8'\n\n    (typeToConverters char).fromString \"\\n\" == Ok '\\n'\n\n    (typeToConverters char).fromString \"\" == Err blankError\n\n    (typeToConverters char).fromString \" \" == Ok ' '\n\n    (typeToConverters char).fromString \"  \" == Err blankError\n\n    (typeToConverters char).fromString \"aA\" == Err (syntaxError \"aA\")\n\n    (typeToConverters char).fromString \" 2 \" == Err (syntaxError \" 2 \")\n\n","type":"Field.Advanced.Type (Field.Advanced.Error e) Char.Char"},{"name":"customError","comment":" Indicates that the user's input string was successfully converted to a value of the desired type but\nthat the value wasn't contained in the subset of values under consideration.\n\nIt's similar to a [`validationError`](#validationError) but rather than a `String` you get to customize\nthe type used to record any extra error details.\n\n    type Username = Username String\n\n    type UsernameError\n        = TooShort { actual : Int, min : Int }\n        | TooLong { actual : Int, max : Int }\n\n    username : Type (Error UsernameError) Username\n    username =\n        customType\n            { fromString =\n                trim\n                    (\\s ->\n                        let\n                            len =\n                                String.length s\n                        in\n                        if len < 3 then\n                            Err <| customError (TooShort { actual = len, min = 3 })\n                        else if len > 25 then\n                            Err <| customError (TooLong { actual = len, max = 25 })\n                        else\n                            Ok (Username s)\n                    )\n            , toString =\n                \\(Username s) -> s\n            }\n\n    toResult (fromString username \"abc\") == Ok (Username \"abc\")\n\n    toResult (fromString username \"ab\") == Err [ customError (TooShort { actual = 2, min = 3 }) ]\n\n    toResult (fromString username \"abcdefghijklmnopqrstuvwxyz\") == Err [ customError (TooLong { actual = 26, max = 25 }) ]\n\nYou get to design the type so that you'd have enough information available to display\na user-friendly error message. See [`errorToString`](#errorToString) for an example.\n\n","type":"e -> Field.Advanced.Error e"},{"name":"customOptional","comment":" Similar to [`optional`](#optional) but you get to customize the blank error check.\n","type":"(e -> Basics.Bool) -> Field.Advanced.Type e a -> Field.Advanced.Type e (Maybe.Maybe a)"},{"name":"customSubsetOfBool","comment":" Customize the errors and options.\n\n    import Set\n\n    type MyError\n        = MyBlank\n        | MySyntaxError String\n        | MyValidationError String\n\n    mySubsetOfBool : (Bool -> Bool) -> Type MyError Bool\n    mySubsetOfBool =\n        customSubsetOfBool\n            { blankError = MyBlank\n            , syntaxError = MySyntaxError\n            , validationError = MyValidationError\n            }\n            { truthy = Set.fromList [ \"#t\" ]\n            , falsy = Set.fromList [ \"#f\" ]\n            , toString =\n                \\b ->\n                    if b then\n                        \"#t\"\n\n                    else\n                        \"#f\"\n            , caseSensitive = True\n            }\n\n    myBool : Type MyError Bool\n    myBool =\n        mySubsetOfBool (always True)\n\n    myTrue : Type MyError Bool\n    myTrue =\n        mySubsetOfBool ((==) True)\n\n    myFalse : Type MyError Bool\n    myFalse =\n        mySubsetOfBool ((==) False)\n\n","type":"{ blankError : e, syntaxError : String.String -> e, validationError : String.String -> e } -> Field.Advanced.CustomBoolOptions -> (Basics.Bool -> Basics.Bool) -> Field.Advanced.Type e Basics.Bool"},{"name":"customSubsetOfChar","comment":" Similar to [`subsetOfChar`](#subsetOfChar) but you get to customize the errors.\n","type":"{ blankError : e, syntaxError : String.String -> e, validationError : String.String -> e } -> (Char.Char -> Basics.Bool) -> Field.Advanced.Type e Char.Char"},{"name":"customSubsetOfFloat","comment":" Similar to [`subsetOfFloat`](#subsetOfFloat) but you get to customize the errors.\n","type":"{ blankError : e, syntaxError : String.String -> e, validationError : String.String -> e } -> (Basics.Float -> Basics.Bool) -> Field.Advanced.Type e Basics.Float"},{"name":"customSubsetOfInt","comment":" Similar to [`subsetOfInt`](#subsetOfInt) but you get to customize the errors.\n","type":"{ blankError : e, syntaxError : String.String -> e, validationError : String.String -> e } -> (Basics.Int -> Basics.Bool) -> Field.Advanced.Type e Basics.Int"},{"name":"customSubsetOfNonBlankString","comment":" Similar to [`subsetOfNonBlankString`](#subsetOfNonBlankString) but you get to customize the errors.\n","type":"{ blankError : e, validationError : String.String -> e } -> (String.String -> Basics.Bool) -> Field.Advanced.Type e String.String"},{"name":"customSubsetOfNonEmptyString","comment":" Similar to [`subsetOfNonEmptyString`](#subsetOfNonEmptyString) but you get to customize the errors.\n","type":"{ blankError : e, validationError : String.String -> e } -> (String.String -> Basics.Bool) -> Field.Advanced.Type e String.String"},{"name":"customSubsetOfString","comment":" Similar to [`subsetOfString`](#subsetOfString) but you get to customize the validation error.\n","type":"(String.String -> e) -> (String.String -> Basics.Bool) -> Field.Advanced.Type e String.String"},{"name":"customSubsetOfType","comment":" Similar to [`subsetOfType`](#subsetOfType) but you get to customize the validation error.\n","type":"(String.String -> e) -> (a -> Basics.Bool) -> Field.Advanced.Type e a -> Field.Advanced.Type e a"},{"name":"customTrim","comment":" Similar to [`trim`](#trim) but you get to customize the blank error.\n","type":"e -> (String.String -> Result.Result e a) -> String.String -> Result.Result e a"},{"name":"customType","comment":" Define a new field type.\n\n    type Email = Email String\n\n    email : Type (Error e) Email\n    email =\n        customType\n            { fromString =\n                trim\n                    (\\s ->\n                        if s |> String.contains \"@\" then\n                            Ok (Email s)\n                        else\n                            Err (syntaxError s)\n                    )\n            , toString =\n                \\(Email s) -> s\n            }\n\n    (typeToConverters email).fromString \"a@b.c\" == Ok (Email \"a@b.c\")\n\n    (typeToConverters email).fromString \" a@b.c \" == Ok (Email \"a@b.c\")\n\n    (typeToConverters email).fromString \"\" == Err blankError\n\n    (typeToConverters email).fromString \" ab.c \" == Err (syntaxError \"ab.c\")\n\n","type":"{ fromString : String.String -> Result.Result e a, toString : a -> String.String } -> Field.Advanced.Type e a"},{"name":"defaultBoolToString","comment":"\n\n    defaultBoolToString True == \"true\"\n\n    defaultBoolToString False == \"false\"\n\n","type":"Basics.Bool -> String.String"},{"name":"defaultCustomBoolOptions","comment":" The default options used by [`bool`](#bool), [`true`](#true), and [`false`](#false).\n\n    { truthy = defaultTruthy\n    , falsy = defaultFalsy\n    , toString = defaultBoolToString\n    , caseSensitive = False\n    }\n\n","type":"Field.Advanced.CustomBoolOptions"},{"name":"defaultErrors","comment":" The default [blank](#blankError), [syntax](#syntaxError), and [validation](#validationError) errors. It's particularly useful when\ncustomizing the `Bool` type with [`customSubsetOfBool`](#customSubsetOfBool) and you don't want to customize the errors.\n\n    myBool = customSubsetOfBool defaultErrors { defaultCustomBoolOptions | caseSensitive = True } (always True)\n\n    toResult (fromString myBool \"true\") == Ok True\n\n    toResult (fromString bool \"True\") == Ok True\n\n    toResult (fromString myBool \"True\") == Err [ syntaxError \"True\" ]\n\n","type":"{ blankError : Field.Advanced.Error e, syntaxError : String.String -> Field.Advanced.Error e, validationError : String.String -> Field.Advanced.Error e }"},{"name":"defaultFalsy","comment":" The default falsy strings: `\"false\"`, `\"0\"`, `\"no\"`, `\"off\"`, `\"n\"`, and `\"disabled\"`.\n","type":"Set.Set String.String"},{"name":"defaultTruthy","comment":" The default truthy strings: `\"true\"`, `\"1\"`, `\"yes\"`, `\"on\"`, `\"y\"`, and `\"enabled\"`.\n","type":"Set.Set String.String"},{"name":"empty","comment":" Initialize a new field from the given type and the empty string.\n\nFor all field types, `t`, `empty t` is equivalent to `fromString t \"\"`.\n\n","type":"Field.Advanced.Type e a -> Field.Advanced.Field e a"},{"name":"errorToString","comment":" Convert your errors to user-friendly error messages.\n\nLet's continue with the example from [`customError`](#customError).\n\n    toErrorMessage : Error UsernameError -> String\n    toErrorMessage =\n        errorToString\n            { onBlank = \"The username is required\"\n            , onSyntaxError = always \"\"\n            , onValidationError = always \"\"\n            , onCustomError =\n                \\e ->\n                    case e of\n                        TooShort { actual, min } ->\n                            \"The username must have at least \" ++ String.fromInt min ++ \" characters: \" ++ String.fromInt actual\n                        TooLong { actual, max } ->\n                            \"The username must have at most \" ++ String.fromInt max ++ \" characters: \" ++ String.fromInt actual\n            }\n\n    toErrorMessage (customError <| TooShort { actual = 2, min = 3 }) == \"The username must have at least 3 characters: 2\"\n\n    toErrorMessage (customError <| TooLong { actual = 26, max = 25 }) == \"The username must have at most 25 characters: 26\"\n\n","type":"{ onBlank : String.String, onSyntaxError : String.String -> String.String, onValidationError : String.String -> String.String, onCustomError : e -> String.String } -> Field.Advanced.Error e -> String.String"},{"name":"false","comment":" Any case-insensitive [`defaultFalsy`](#defaultFalsy) trimmed string.\n\n    (typeToConverters false).fromString \"true\" == Err (validationError \"true\")\n\n    (typeToConverters false).fromString \"TrUe\" == Err (validationError \"true\")\n\n    (typeToConverters false).fromString \"false\" == Ok False\n\n    (typeToConverters false).fromString \"fAlSe\" == Ok False\n\n    (typeToConverters false).fromString \" 1 \" == Err (validationError \"true\")\n\n    (typeToConverters false).fromString \" 0 \" == Ok False\n\n    (typeToConverters false).fromString \"\" == Err blankError\n\n    (typeToConverters false).fromString \"not\" == Err (syntaxError \"not\")\n\n","type":"Field.Advanced.Type (Field.Advanced.Error e) Basics.Bool"},{"name":"firstError","comment":"\n\n    fromString string \"A string\"\n        |> firstError\n        |> (==) Nothing\n\n    fromString string \"A string\"\n        |> setErrors \"First error\" [ \"Second error\", \"Third error\" ]\n        |> firstError\n        |> (==) (Just \"First error\")\n\n","type":"Field.Advanced.Field e a -> Maybe.Maybe e"},{"name":"float","comment":" Any `Float` that can be parsed from a trimmed string using `String.toFloat`.\n\n    (typeToConverters float).fromString \"-0.1\" == Ok -0.1\n\n    (typeToConverters float).fromString \"0\" == Ok 0\n\n    (typeToConverters float).fromString \"1.1\" == Ok 1.1\n\n    (typeToConverters float).fromString \" 3.14 \" == Ok 3.14\n\n    (typeToConverters float).fromString \"\" == Err blankError\n\n    (typeToConverters float).fromString \"pi\" == Err (syntaxError \"pi\")\n\n","type":"Field.Advanced.Type (Field.Advanced.Error e) Basics.Float"},{"name":"fromString","comment":" Initialize a new field from the given type and string.\n\n    toMaybe (fromString bool \"enabled\") == Just True\n\n","type":"Field.Advanced.Type e a -> String.String -> Field.Advanced.Field e a"},{"name":"fromValue","comment":" Initialize a new field from the given type and value.\n\n    toMaybe (fromValue char 'a') == Just 'a'\n\n","type":"Field.Advanced.Type e a -> a -> Field.Advanced.Field e a"},{"name":"int","comment":" Any `Int` that can be parsed from a trimmed string using `String.toInt`.\n\n    (typeToConverters int).fromString \"-1\" == Ok -1\n\n    (typeToConverters int).fromString \"0\" == Ok 0\n\n    (typeToConverters int).fromString \"1\" == Ok 1\n\n    (typeToConverters int).fromString \" 5 \" == Ok 5\n\n    (typeToConverters int).fromString \"\" == Err blankError\n\n    (typeToConverters int).fromString \"five\" == Err (syntaxError \"five\")\n\n","type":"Field.Advanced.Type (Field.Advanced.Error e) Basics.Int"},{"name":"isBlank","comment":" Determine whether or not the raw string is equal to a blank string.\n\n    isBlank (empty int) == True\n\n    isBlank (fromString int \"   \") == True\n\n    isBlank (fromString int \"1\") == False\n\n","type":"Field.Advanced.Field e a -> Basics.Bool"},{"name":"isClean","comment":" `True` if the field is [clean](#state).\n\n    isClean (empty int) == True\n\n    isClean (fromString int \"1\") == True\n\n    isClean (setFromString \"1\" (empty int)) == False\n\n","type":"Field.Advanced.Field e a -> Basics.Bool"},{"name":"isDirty","comment":" `True` if the field is [dirty](#state). `isDirty f` is equivalent to `not (isClean f)`.\n\n    isDirty (empty int) == False\n\n    isDirty (fromString int \"1\") == False\n\n    isDirty (setFromString \"1\" (empty int)) == True\n\n","type":"Field.Advanced.Field e a -> Basics.Bool"},{"name":"isEmpty","comment":" Determine whether or not the raw string is equal to the empty string.\n\n    isEmpty (empty int) == True\n\n    isEmpty (fromString int \"   \") == False\n\n    isEmpty (fromString int \"1\") == False\n\n","type":"Field.Advanced.Field e a -> Basics.Bool"},{"name":"isInvalid","comment":" `True` if the field has errors. `isInvalid f` is equivalent to `not (isValid f)`.\n\n    isInvalid (empty int) == True\n\n    isInvalid (fromString int \"1\") == False\n\n","type":"Field.Advanced.Field e a -> Basics.Bool"},{"name":"isNonBlank","comment":" `isNonBlank f` is equivalent to `not (isBlank f)`.\n\n    isNonBlank (empty int) == False\n\n    isNonBlank (fromString int \"   \") == False\n\n    isNonBlank (fromString int \"1\") == True\n\n","type":"Field.Advanced.Field e a -> Basics.Bool"},{"name":"isNonEmpty","comment":" `isNonEmpty f` is equivalent to `not (isEmpty f)`.\n\n    isNonEmpty (empty int) == False\n\n    isNonEmpty (fromString int \"   \") == True\n\n    isNonEmpty (fromString int \"1\") == True\n\n","type":"Field.Advanced.Field e a -> Basics.Bool"},{"name":"isValid","comment":" `True` if the field does not have any errors.\n\n    isValid (empty int) == False\n\n    isValid (fromString int \"1\") == True\n\n","type":"Field.Advanced.Field e a -> Basics.Bool"},{"name":"lastError","comment":"\n\n    fromString string \"A string\"\n        |> lastError\n        |> (==) Nothing\n\n    fromString string \"A string\"\n        |> setErrors \"First error\" [ \"Second error\", \"Third error\" ]\n        |> lastError\n        |> (==) (Just \"Third error\")\n\n","type":"Field.Advanced.Field e a -> Maybe.Maybe e"},{"name":"mapError","comment":" Apply a function to the error value of the field type. It's useful for unifying\nmultiple custom field errors under a single error type.\n\nLet's continue with the example from [`customError`](#customError) and incorporate an `Age` type.\n\n    type Age = Age Int\n\n    type AgeError\n        = TooYoung { actual : Int, min : Int }\n        | TooOld { actual : Int, max : Int }\n\n    age : Type (Error AgeError) Age\n    age =\n        customType\n            { fromString =\n                (typeToConverters positiveInt).fromString\n                    >> Result.andThen\n                        (\\n ->\n                            if n < 21 then\n                                Err <| customError (TooYoung { actual = n, min = 21 })\n                            else if n > 65 then\n                                Err <| customError (TooOld { actual = n, max = 65 })\n                            else\n                                Ok (Age n)\n                        )\n            , toString =\n                \\(Age n) -> String.fromInt n\n            }\n\n    --\n    -- 1. The single error type under which we will unify the two custom field errors.\n    --\n    type Errors\n        = MyUsernameError (Error UsernameError)\n        | MyAgeError (Error AgeError)\n\n    usernameField : Field (Error UsernameError) Username\n    usernameField = fromString username \"ab\"\n\n    ageField : Field (Error AgeError) Age\n    ageField = fromString age \"67\"\n\n    type alias UserDetails = { username : Username, age : Age }\n\n    --\n    -- 2. We use mapError in order to validate both fields at the same time.\n    --\n    resultUserDetails =\n        validationToResult <|\n            validate2\n                UserDetails\n                (usernameField |> mapError MyUsernameError)\n                (ageField |> mapError MyAgeError)\n\n    resultUserDetails == Err [ MyUsernameError (customError <| TooShort { actual = 2, min = 3 }), MyAgeError (customError <| TooOld { actual = 67, max = 65 }) ]\n\n","type":"(x -> y) -> Field.Advanced.Field x a -> Field.Advanced.Field y a"},{"name":"mapErrorType","comment":" ","type":"(x -> y) -> Field.Advanced.Error x -> Field.Advanced.Error y"},{"name":"mapTypeError","comment":" ","type":"(x -> y) -> Field.Advanced.Type x a -> Field.Advanced.Type y a"},{"name":"negativeFloat","comment":" Any `Float`, `f`, that can be parsed from a trimmed string using `String.toFloat` such that `f < 0`.\n\n    (typeToConverters negativeFloat).fromString \"-0.1\" == Ok -0.1\n\n    (typeToConverters negativeFloat).fromString \"0\" == Err (validationError \"0\")\n\n    (typeToConverters negativeFloat).fromString \"1.1\" == Err (validationError \"1.1\")\n\n    (typeToConverters negativeFloat).fromString \" 3.14 \" == Err (validationError \"3.14\")\n\n    (typeToConverters negativeFloat).fromString \"\" == Err blankError\n\n    (typeToConverters negativeFloat).fromString \"pi\" == Err (syntaxError \"pi\")\n\n","type":"Field.Advanced.Type (Field.Advanced.Error e) Basics.Float"},{"name":"negativeInt","comment":" Any `Int`, `n`, that can be parsed from a trimmed string using `String.toInt` such that `n < 0`.\n\n    (typeToConverters negativeInt).fromString \"-1\" == Ok -1\n\n    (typeToConverters negativeInt).fromString \"0\" == Err (validationError \"0\")\n\n    (typeToConverters negativeInt).fromString \"1\" == Err (validationError \"1\")\n\n    (typeToConverters negativeInt).fromString \" 5 \" == Err (validationError \"5\")\n\n    (typeToConverters negativeInt).fromString \"\" == Err blankError\n\n    (typeToConverters negativeInt).fromString \"five\" == Err (syntaxError \"five\")\n\n","type":"Field.Advanced.Type (Field.Advanced.Error e) Basics.Int"},{"name":"nonBlankString","comment":" Any non-blank trimmed `String` is accepted.\n\n    (typeToConverters nonBlankString).fromString \"Hello\" == Ok \"Hello\"\n\n    (typeToConverters nonBlankString).fromString \" Hello \" == Ok \"Hello\"\n\n    (typeToConverters nonBlankString).fromString \"\" == Err blankError\n\n    (typeToConverters nonBlankString).fromString \" \\n\\t \" == Err blankError\n\n","type":"Field.Advanced.Type (Field.Advanced.Error e) String.String"},{"name":"nonEmptyString","comment":" Any `String` except the empty string is accepted. The string is not trimmed.\n\n    (typeToConverters nonEmptyString).fromString \"Hello\" == Ok \"Hello\"\n\n    (typeToConverters nonEmptyString).fromString \" Hello \" == Ok \" Hello \"\n\n    (typeToConverters nonEmptyString).fromString \"\" == Err blankError\n\n    (typeToConverters nonEmptyString).fromString \" \\n\\t \" == Ok \" \\n\\t \"\n\n","type":"Field.Advanced.Type (Field.Advanced.Error e) String.String"},{"name":"nonNegativeFloat","comment":" Any `Float`, `f`, that can be parsed from a trimmed string using `String.toFloat` such that `f >= 0`.\n\n    (typeToConverters nonNegativeFloat).fromString \"-0.1\" == Err (validationError \"-0.1\")\n\n    (typeToConverters nonNegativeFloat).fromString \"0\" == Ok 0\n\n    (typeToConverters nonNegativeFloat).fromString \"1.1\" == Ok 1.1\n\n    (typeToConverters nonNegativeFloat).fromString \" 3.14 \" == Ok 3.14\n\n    (typeToConverters nonNegativeFloat).fromString \"\" == Err blankError\n\n    (typeToConverters nonNegativeFloat).fromString \"pi\" == Err (syntaxError \"pi\")\n\n","type":"Field.Advanced.Type (Field.Advanced.Error e) Basics.Float"},{"name":"nonNegativeInt","comment":" Any `Int`, `n`, that can be parsed from a trimmed string using `String.toInt` such that `n >= 0`.\n\n    (typeToConverters nonNegativeInt).fromString \"-1\" == Err (validationError \"-1\")\n\n    (typeToConverters nonNegativeInt).fromString \"0\" == Ok 0\n\n    (typeToConverters nonNegativeInt).fromString \"1\" == Ok 1\n\n    (typeToConverters nonNegativeInt).fromString \" 5 \" == Ok 5\n\n    (typeToConverters nonNegativeInt).fromString \"\" == Err blankError\n\n    (typeToConverters nonNegativeInt).fromString \"five\" == Err (syntaxError \"five\")\n\n","type":"Field.Advanced.Type (Field.Advanced.Error e) Basics.Int"},{"name":"nonPositiveFloat","comment":" Any `Float`, `f`, that can be parsed from a trimmed string using `String.toFloat` such that `f <= 0`.\n\n    (typeToConverters nonPositiveFloat).fromString \"-0.1\" == Ok -0.1\n\n    (typeToConverters nonPositiveFloat).fromString \"0\" == Ok 0\n\n    (typeToConverters nonPositiveFloat).fromString \"1.1\" == Err (validationError \"1.1\")\n\n    (typeToConverters nonPositiveFloat).fromString \" 3.14 \" == Err (validationError \"3.14\")\n\n    (typeToConverters nonPositiveFloat).fromString \"\" == Err blankError\n\n    (typeToConverters nonPositiveFloat).fromString \"pi\" == Err (syntaxError \"pi\")\n\n","type":"Field.Advanced.Type (Field.Advanced.Error e) Basics.Float"},{"name":"nonPositiveInt","comment":" Any `Int`, `n`, that can be parsed from a trimmed string using `String.toInt` such that `n <= 0`.\n\n    (typeToConverters nonPositiveInt).fromString \"-1\" == Ok -1\n\n    (typeToConverters nonPositiveInt).fromString \"0\" == Ok 0\n\n    (typeToConverters nonPositiveInt).fromString \"1\" == Err (validationError \"1\")\n\n    (typeToConverters nonPositiveInt).fromString \" 5 \" == Err (validationError \"5\")\n\n    (typeToConverters nonPositiveInt).fromString \"\" == Err blankError\n\n    (typeToConverters nonPositiveInt).fromString \"five\" == Err (syntaxError \"five\")\n\n","type":"Field.Advanced.Type (Field.Advanced.Error e) Basics.Int"},{"name":"optional","comment":" Make any field type optional.\n\n    maybePositiveInt = optional positiveInt\n\n    (typeToConverters maybePositiveInt).fromString \"-1\" == Err (validationError \"-1\")\n\n    (typeToConverters maybePositiveInt).fromString \"0\" == Err (validationError \"0\")\n\n    (typeToConverters maybePositiveInt).fromString \"1\" == Ok (Just 1)\n\n    (typeToConverters maybePositiveInt).fromString \" 5 \" == Ok (Just 5)\n\n    (typeToConverters maybePositiveInt).fromString \"\" == Ok Nothing\n\n    (typeToConverters maybePositiveInt).fromString \"five\" == Err (syntaxError \"five\")\n\n","type":"Field.Advanced.Type (Field.Advanced.Error e) a -> Field.Advanced.Type (Field.Advanced.Error e) (Maybe.Maybe a)"},{"name":"positiveFloat","comment":" Any `Float`, `f`, that can be parsed from a trimmed string using `String.toFloat` such that `f > 0`.\n\n    (typeToConverters positiveFloat).fromString \"-0.1\" == Err (validationError \"-0.1\")\n\n    (typeToConverters positiveFloat).fromString \"0\" == Err (validationError \"0\")\n\n    (typeToConverters positiveFloat).fromString \"1.1\" == Ok 1.1\n\n    (typeToConverters positiveFloat).fromString \" 3.14 \" == Ok 3.14\n\n    (typeToConverters positiveFloat).fromString \"\" == Err blankError\n\n    (typeToConverters positiveFloat).fromString \"pi\" == Err (syntaxError \"pi\")\n\n","type":"Field.Advanced.Type (Field.Advanced.Error e) Basics.Float"},{"name":"positiveInt","comment":" Any `Int`, `n`, that can be parsed from a trimmed string using `String.toInt` such that `n > 0`.\n\n    (typeToConverters positiveInt).fromString \"-1\" == Err (validationError \"-1\")\n\n    (typeToConverters positiveInt).fromString \"0\" == Err (validationError \"0\")\n\n    (typeToConverters positiveInt).fromString \"1\" == Ok 1\n\n    (typeToConverters positiveInt).fromString \" 5 \" == Ok 5\n\n    (typeToConverters positiveInt).fromString \"\" == Err blankError\n\n    (typeToConverters positiveInt).fromString \"five\" == Err (syntaxError \"five\")\n\n","type":"Field.Advanced.Type (Field.Advanced.Error e) Basics.Int"},{"name":"setCustomError","comment":"\n\n    field = empty int\n\n    error = customError \"Not an integer\"\n\n    toResult (setCustomError \"Not an integer\" field) == Err [ error ]\n\n","type":"e -> Field.Advanced.Field (Field.Advanced.Error e) a -> Field.Advanced.Field (Field.Advanced.Error e) a"},{"name":"setCustomErrors","comment":" ","type":"e -> List.List e -> Field.Advanced.Field (Field.Advanced.Error e) a -> Field.Advanced.Field (Field.Advanced.Error e) a"},{"name":"setError","comment":"\n\n    field = empty int\n\n    error = customError \"Not an integer\"\n\n    toResult (setError error field) == Err [ error ]\n\n","type":"e -> Field.Advanced.Field e a -> Field.Advanced.Field e a"},{"name":"setErrors","comment":" ","type":"e -> List.List e -> Field.Advanced.Field e a -> Field.Advanced.Field e a"},{"name":"setFromString","comment":"\n\n    field = empty positiveInt\n\n    toResult field == Err [ blankError ]\n\n    toResult (setFromString \"-1\" field) == Err [ validationError \"-1\" ]\n\n    toResult (setFromString \"0\" field) == Err [ validationError \"0\" ]\n\n    toResult (setFromString \"1\" field) == Ok 1\n\n    toResult (setFromString \" 5 \" field) == Ok 5\n\n    toResult (setFromString \"   \" field) == Err [ blankError ]\n\n    toResult (setFromString \"five\" field) == Err [ syntaxError \"five\" ]\n\n","type":"String.String -> Field.Advanced.Field e a -> Field.Advanced.Field e a"},{"name":"setFromValue","comment":"\n\n    field = empty (optional positiveInt)\n\n    toResult field == Ok Nothing\n\n    toResult (setFromValue (Just -1) field) == Err [ validationError \"-1\" ]\n\n    toResult (setFromValue (Just 0) field) == Err [ validationError \"0\" ]\n\n    toResult (setFromValue (Just 1) field) == Ok (Just 1)\n\n    toResult (setFromValue (Just 5) field) == Ok (Just 5)\n\n    toResult (setFromValue Nothing field) == Ok Nothing\n\n","type":"a -> Field.Advanced.Field e a -> Field.Advanced.Field e a"},{"name":"string","comment":" Any trimmed `String` is accepted. It never fails.\n\n    (typeToConverters string).fromString \"Hello\" == Ok \"Hello\"\n\n    (typeToConverters string).fromString \" Hello \" == Ok \"Hello\"\n\n    (typeToConverters string).fromString \"\" == Ok \"\"\n\n    (typeToConverters string).fromString \" \\n\\t \" == Ok \"\"\n\n","type":"Field.Advanced.Type e String.String"},{"name":"subsetOfChar","comment":" Any `Char`, `c`, that can be parsed from a string of exactly length one such that `isGood c` is `True`. The string is not trimmed.\n\n    digit = subsetOfChar Char.isDigit\n\n    (typeToConverters digit).fromString \"a\" == Err (validationError \"a\")\n\n    (typeToConverters digit).fromString \"A\" == Err (validationError \"A\")\n\n    (typeToConverters digit).fromString \"8\" == Ok '8'\n\n    (typeToConverters digit).fromString \"\\n\" == Err (validationError \"\\n\")\n\n    (typeToConverters digit).fromString \"\" == Err blankError\n\n    (typeToConverters digit).fromString \" \" == Err (validationError \" \")\n\n    (typeToConverters digit).fromString \"  \" == Err blankError\n\n    (typeToConverters digit).fromString \"aA\" == Err (syntaxError \"aA\")\n\n    (typeToConverters digit).fromString \" 2 \" == Err (syntaxError \" 2 \")\n\n","type":"(Char.Char -> Basics.Bool) -> Field.Advanced.Type (Field.Advanced.Error e) Char.Char"},{"name":"subsetOfFloat","comment":" Any `Float`, `f`, that can be parsed from a trimmed string using `String.toFloat` such that `isGood f` is `True`.\n\n    roundsToTwo = subsetOfFloat (round >> (==) 2)\n\n    (typeToConverters roundsToTwo).fromString \"1.3\" == Err (validationError \"1.3\")\n\n    (typeToConverters roundsToTwo).fromString \"1.5\" == Ok 1.5\n\n    (typeToConverters roundsToTwo).fromString \"1.8\" == Ok 1.8\n\n    (typeToConverters roundsToTwo).fromString \"2.0\" == Ok 2.0\n\n    (typeToConverters roundsToTwo).fromString \"2.3\" == Ok 2.3\n\n    (typeToConverters roundsToTwo).fromString \"2.5\" == Err (validationError \"2.5\")\n\n    (typeToConverters roundsToTwo).fromString \"3.14\" == Err (validationError \"3.14\")\n\n    (typeToConverters roundsToTwo).fromString \"\" == Err blankError\n\n    (typeToConverters roundsToTwo).fromString \"pi\" == Err (syntaxError \"pi\")\n\n","type":"(Basics.Float -> Basics.Bool) -> Field.Advanced.Type (Field.Advanced.Error e) Basics.Float"},{"name":"subsetOfInt","comment":" Any `Int`, `n`, that can be parsed from a trimmed string using `String.toInt` such that `isGood n` is `True`.\n\n    evens = subsetOfInt (modBy 2 >> (==) 0)\n\n    (typeToConverters evens).fromString \"-2\" == Ok -2\n\n    (typeToConverters evens).fromString \"-1\" == Err (validationError \"-1\")\n\n    (typeToConverters evens).fromString \"0\" == Ok 0\n\n    (typeToConverters evens).fromString \"1\" == Err (validationError \"1\")\n\n    (typeToConverters evens).fromString \" 2 \" == Ok 2\n\n    (typeToConverters evens).fromString \"\" == Err blankError\n\n    (typeToConverters evens).fromString \"five\" == Err (syntaxError \"five\")\n\n","type":"(Basics.Int -> Basics.Bool) -> Field.Advanced.Type (Field.Advanced.Error e) Basics.Int"},{"name":"subsetOfNonBlankString","comment":" Any non-blank trimmed `String`, `s`, is accepted if `isGood s` is `True`.\n\n    atMost3 = subsetOfNonBlankString (String.length >> (>=) 3)\n\n    (typeToConverters atMost3).fromString \"p\" == Ok \"p\"\n\n    (typeToConverters atMost3).fromString \"pi\" == Ok \"pi\"\n\n    (typeToConverters atMost3).fromString \"pie\" == Ok \"pie\"\n\n    (typeToConverters atMost3).fromString \" pie \" == Ok \"pie\"\n\n    (typeToConverters atMost3).fromString \"Hello\" == Err (validationError \"Hello\")\n\n    (typeToConverters atMost3).fromString \" Hello \" == Err (validationError \"Hello\")\n\n    (typeToConverters atMost3).fromString \"\" == Err blankError\n\n    (typeToConverters atMost3).fromString \" \\n\\t \" == Err blankError\n\n","type":"(String.String -> Basics.Bool) -> Field.Advanced.Type (Field.Advanced.Error e) String.String"},{"name":"subsetOfNonEmptyString","comment":" Any non-empty `String`, `s`, is only accepted if `isGood s` is `True`. The string is not trimmed.\n\n    hello = subsetOfNonEmptyString ((==) \"Hello\")\n\n    (typeToConverters hello).fromString \"Hello\" == Ok \"Hello\"\n\n    (typeToConverters hello).fromString \" Hello \" == Err (validationError \" Hello \")\n\n    (typeToConverters hello).fromString \"\" == Err blankError\n\n    (typeToConverters hello).fromString \" \\n\\t \" == Err (validationError \" \\n\\t \")\n\n","type":"(String.String -> Basics.Bool) -> Field.Advanced.Type (Field.Advanced.Error e) String.String"},{"name":"subsetOfString","comment":" Any trimmed `String`, `s`, is accepted if `isGood s` is `True`.\n\n    atMost3 = subsetOfString (String.length >> (>=) 3)\n\n    (typeToConverters atMost3).fromString \"p\" == Ok \"p\"\n\n    (typeToConverters atMost3).fromString \"pi\" == Ok \"pi\"\n\n    (typeToConverters atMost3).fromString \"pie\" == Ok \"pie\"\n\n    (typeToConverters atMost3).fromString \" pie \" == Ok \"pie\"\n\n    (typeToConverters atMost3).fromString \"Hello\" == Err (validationError \"Hello\")\n\n    (typeToConverters atMost3).fromString \" Hello \" == Err (validationError \"Hello\")\n\n    (typeToConverters atMost3).fromString \"\" == Ok \"\"\n\n    (typeToConverters atMost3).fromString \" \\n\\t \" == Ok \"\"\n\n","type":"(String.String -> Basics.Bool) -> Field.Advanced.Type (Field.Advanced.Error e) String.String"},{"name":"subsetOfType","comment":" Accept a subset of the values accepted by the given type.\n\n    positiveEvens = subsetOfType (modBy 2 >> (==) 0) positiveInt\n\n    (typeToConverters positiveEvens).fromString \" 2 \" == Ok 2\n\n    (typeToConverters positiveEvens).fromString \"-2\" == Err (validationError \"-2\")\n\n    (typeToConverters positiveEvens).fromString \"-1\" == Err (validationError \"-1\")\n\n    (typeToConverters positiveEvens).fromString \"0\" == Err (validationError \"0\")\n\n    (typeToConverters positiveEvens).fromString \"1\" == Err (validationError \"1\")\n\n    (typeToConverters positiveEvens).fromString \"\" == Err blankError\n\n    (typeToConverters positiveEvens).fromString \"five\" == Err (syntaxError \"five\")\n\n","type":"(a -> Basics.Bool) -> Field.Advanced.Type (Field.Advanced.Error e) a -> Field.Advanced.Type (Field.Advanced.Error e) a"},{"name":"succeed","comment":" Useful to use with [`applyValidation`](#applyValidation).\n\nLet `f` represent a function that takes `N >= 1` arguments. Then,\n\n    succeed f\n        |> applyValidation field1\n        |> applyValidation field2\n        |> ...\n        |> applyValidation fieldN\n\napplies `f` to `N` arguments as long as no field has an error.\n\n","type":"a -> Field.Advanced.Validation e a"},{"name":"syntaxError","comment":" Indicates that the user's input string cannot be converted to the desired type.\n\n    toResult (fromString positiveInt \"five\") == Err [ syntaxError \"five\" ]\n\nThe string used in the syntax error is the trimmed user's input string that caused the error.\n\n    toResult (fromString positiveInt \" five\\n \\t\") == Err [ syntaxError \"five\" ]\n\n","type":"String.String -> Field.Advanced.Error e"},{"name":"toConverters","comment":" ","type":"Field.Advanced.Field e a -> Field.Advanced.Converters e a"},{"name":"toMaybe","comment":"\n\n    toMaybe (empty int) == Nothing\n\n    toMaybe (fromString int \"5\") == Just 5\n\n","type":"Field.Advanced.Field e a -> Maybe.Maybe a"},{"name":"toRawString","comment":"\n\n    toRawString (empty int) == \"\"\n\n    toRawString (fromString int \" \\n5  \\t \\n\") == \" \\n5  \\t \\n\"\n\n","type":"Field.Advanced.Field e a -> String.String"},{"name":"toResult","comment":"\n\n    toResult (empty int) == Err [ blankError ]\n\n    toResult (fromString int \"5\") == Ok 5\n\n","type":"Field.Advanced.Field e a -> Result.Result (List.List e) a"},{"name":"toState","comment":" ","type":"Field.Advanced.Field e a -> Field.Advanced.State e a"},{"name":"toString","comment":"\n\n    toString (empty int) == \"\"\n\n    toString (fromString int \" \\n5  \\t \\n\") == \"5\"\n\n","type":"Field.Advanced.Field e a -> String.String"},{"name":"toType","comment":" Recover the type information for a field.\n","type":"Field.Advanced.Field e a -> Field.Advanced.Type e a"},{"name":"toValidation","comment":"\n\n    import Validation as V\n\n    toValidation (empty int) == V.fail blankError\n\n    toValidation (fromString int \"5\") == V.succeed 5\n\n","type":"Field.Advanced.Field e a -> Field.Advanced.Validation e a"},{"name":"trim","comment":" Get rid of whitespace on both sides of a string.\n\nIf the trimmed string is empty return [`blankError`](#blankError),\notherwise apply the given function to the trimmed string.\n\nIt is useful when you're defining a custom field type.\n\n    type Username = Username String\n\n    username : Type (Error String) Username\n    username =\n        customType\n            { fromString =\n                trim\n                    (\\s ->\n                        let\n                            len =\n                                String.length s\n                        in\n                        if len < 3 then\n                            Err <| customError \"The username must have at least 3 characters\"\n                        else if len > 25 then\n                            Err <| customError \"The username must have at most 25 characters\"\n                        else\n                            Ok (Username s)\n                    )\n            , toString =\n                \\(Username s) -> s\n            }\n\n\n    toResult (fromString username \"abc\") == Ok (Username \"abc\")\n\n    toResult (fromString username \"ab\") == Err [ customError \"The username must have at least 3 characters\" ]\n\n    toResult (fromString username \"abcdefghijklmnopqrstuvwxyz\") == Err [ customError \"The username must have at most 25 characters\" ]\n\n","type":"(String.String -> Result.Result (Field.Advanced.Error e) a) -> String.String -> Result.Result (Field.Advanced.Error e) a"},{"name":"true","comment":" Any case-insensitive [`defaultTruthy`](#defaultTruthy) trimmed string.\n\n    (typeToConverters true).fromString \"true\" == Ok True\n\n    (typeToConverters true).fromString \"TrUe\" == Ok True\n\n    (typeToConverters true).fromString \"false\" == Err (validationError \"false\")\n\n    (typeToConverters true).fromString \"fAlSe\" == Err (validationError \"false\")\n\n    (typeToConverters true).fromString \" 1 \" == Ok True\n\n    (typeToConverters true).fromString \" 0 \" == Err (validationError \"false\")\n\n    (typeToConverters true).fromString \"\" == Err blankError\n\n    (typeToConverters true).fromString \"not\" == Err (syntaxError \"not\")\n\n","type":"Field.Advanced.Type (Field.Advanced.Error e) Basics.Bool"},{"name":"typeToConverters","comment":" ","type":"Field.Advanced.Type e a -> Field.Advanced.Converters e a"},{"name":"validate","comment":" Apply a function to the processed value of a field. If the field is valid,\nthe value will be converted. If the field is invalid, the same error will be\npropagated.\n\n    import Validation as V\n\n    validate sqrt (fromString float \"4.0\") == V.succeed 2.0\n\n    validate sqrt (fromString float \"\") == V.fail blankError\n\n","type":"(a -> value) -> Field.Advanced.Field x a -> Field.Advanced.Validation x value"},{"name":"validate2","comment":" Apply a function if both fields are valid. If not, the errors will be accumulated\nin order of failure.\n\n    import Validation as V\n\n    validate2 max (fromString int \"42\") (fromString int \"13\") == V.succeed 42\n\n    validate2 max (fromString int \"x\") (fromString int \"13\") == V.fail (syntaxError \"x\")\n\n    validate2 max (fromString int \"42\") (fromString int \"y\") == V.fail (syntaxError \"y\")\n\n    validate2 max (fromString int \"x\") (fromString int \"y\") == V.failWithErrors (syntaxError \"x\") [ syntaxError \"y\" ]\n\n","type":"(a -> b -> value) -> Field.Advanced.Field x a -> Field.Advanced.Field x b -> Field.Advanced.Validation x value"},{"name":"validate3","comment":" Apply a function if all three fields are valid. If not, the errors will be accumulated\nin order of failure.\n\n    validate3 (\\a b c -> a + b + c) (fromString int \"1\") (fromString int \"2\") (fromString int \"3\") == V.succeed 6\n\n    validate3 (\\a b c -> a + b + c) (fromString int \"1\") (fromString int \"y\") (fromString int \"3\") == V.fail (syntaxError \"y\")\n\n    validate3 (\\a b c -> a + b + c) (fromString int \"x\") (fromString int \"2\") (fromString int \"z\") == V.failWithErrors (syntaxError \"x\") [ syntaxError \"z\" ]\n\n    validate3 (\\a b c -> a + b + c) (fromString int \"x\") (fromString int \"y\") (fromString int \"z\") == V.failWithErrors (syntaxError \"x\") [ syntaxError \"y\", syntaxError \"z\" ]\n\n","type":"(a -> b -> c -> value) -> Field.Advanced.Field x a -> Field.Advanced.Field x b -> Field.Advanced.Field x c -> Field.Advanced.Validation x value"},{"name":"validate4","comment":" ","type":"(a -> b -> c -> d -> value) -> Field.Advanced.Field x a -> Field.Advanced.Field x b -> Field.Advanced.Field x c -> Field.Advanced.Field x d -> Field.Advanced.Validation x value"},{"name":"validate5","comment":" ","type":"(a -> b -> c -> d -> e -> value) -> Field.Advanced.Field x a -> Field.Advanced.Field x b -> Field.Advanced.Field x c -> Field.Advanced.Field x d -> Field.Advanced.Field x e -> Field.Advanced.Validation x value"},{"name":"validationError","comment":" Indicates that the user's input string was successfully converted to a value of the desired type but\nthat the value wasn't contained in the subset of values under consideration.\n\n    toResult (fromString positiveInt \"0\") == Err [ validationError \"0\" ]\n\n    toResult (fromString positiveInt \"-1\") == Err [ validationError \"-1\" ]\n\nLet `v` represent the value to which the user's input string was successfully converted. The string used\nin the validation error is the string returned by the `toString` function of the field's type when it's\napplied to `v`.\n\n    v : Int\n    v = -1\n\n    field : Field (Error e) Int\n    field = fromString positiveInt \" -1 \\n \\t\"\n\n    negativeOne : String\n    negativeOne = (toConverters field).toString v\n\n    toResult field == Err [ validationError negativeOne ]\n\nIn the above example, the user's input string, `\" -1 \\n \\t\"`, would be successfully converted to the\nvalue, `-1`, but `-1` is not a positive integer. Hence, the string representation of `-1` as determined\nby `(toConverters field).toString` is used in the validation error.\n\n","type":"String.String -> Field.Advanced.Error e"},{"name":"validationToResult","comment":" Convert from a `Validaton` to a `Result` for convenience.\n\nUseful to use with [`applyValidation`](#applyValidation).\n\nLet `f` represent a function that takes `N >= 1` arguments. Then,\n\n    succeed f\n        |> applyValidation field1\n        |> applyValidation field2\n        |> ...\n        |> applyValidation fieldN\n        |> validationToResult\n\napplies `f` to `N` arguments as long as no field has an error.\n\n","type":"Field.Advanced.Validation e a -> Result.Result (List.List e) a"}],"binops":[]}]