h$       2017@present Mark Karpov BSD 3 clause$Mark Karpov  experimentalportableNone /5>formaThe type function computes a  which is satisfied when its first argument is contained in its second argument. Otherwise a friendly type error is displayed.forma names" represents a non-empty vector of  components that serve as a path to some field in a JSON structure. Every component is guaranteed to be in the names, which is a set of strings on type level. The purpose if this type is to avoid typos and to force users to update field names everywhere when they decide to change them. The only way to obtain a value of the type  is by using OverloadedLabels.. Note that you can combine field names using ( ). showFieldName (#login_form <> #username) = "login_form.username"forma5The type represents the parser that you can run on a ! with help of . The only way for the user of the library to create a parser is via the   function and its friends, see below. Users can combine existing parsers using applicative notation.( is parametrized by four type variables:names@collection of field names we can use in a form to be parsed with this parser.e@type of validation errors.m@underlying monad,  is not a monad itself, so it's not a monad transformer, but validation can make use of the m monad.a@result of parsing.5 is not a monad because it's not possible to write a " instance with the properties that we want (validation errors should not lead to short-cutting behavior).formaResult of parsing. names, is the collection of allowed field names, e' is the type of validation errors, and a is the type of parsing result.formaParsing of JSON failed, this is fatal, we shut down and report the parsing error. The first component specifies the path to a problematic field and the second component is the text of error message.formaValidation of a field failed. This is also fatal but we still try to validate other branches (fields) to collect as many validation errors as possible.forma&Success, we've got a result to return.formaProject field path from a .forma2Project textual representation of path to a field. forma1Construct a parser for a field. Combine multiple  $s using applicative syntax like so: type LoginFields = '["username", "password", "remember_me"] data LoginForm = LoginForm { loginUsername :: Text , loginPassword :: Text , loginRememberMe :: Bool } loginForm :: Monad m => FormParser LoginFields Text m LoginForm loginForm = LoginForm <$> field #username notEmpty <*> field #password notEmpty <*> field' #remember_me notEmpty :: Monad m => Text -> ExceptT Text m Text notEmpty txt = if T.null txt then throwError "This field cannot be empty" else return txt4Referring to the types in the function's signature, s is extracted from JSON !! for you automatically using its # instance. The field value is taken in assumption that top level ! is a dictionary, and field name is a key in that dictionary. So for example a valid JSON input for the form shown above could be this: { "username": "Bob", "password": "123", "remember_me": true }Once the value of type s is extracted, the validation phase beings. The supplied checker (you can easily compose them with ($)1, as they are Kleisli arrows) is applied to the s4 value and validation either succeeds producing an a- value, or we collect an error as a value of e type.To run a form composed from  s, see . field fieldName check = withCheck fieldName check (field' fieldName) forma The same as  !, but does not require a checker. ,field' fieldName = subParser fieldName value forma/Interpret the current field as a value of type a. formaUse a given parser to parse a field. Suppose that you have a parser  loginForm' that parses a structure like this one: { "username": "Bob", "password": "123", "remember_me": true }Then subParser #login loginForm will parse this: { "login": { "username": "Bob", "password": "123", "remember_me": true } } forma5Transform a form by applying a checker on its result. passwordsMatch (a, b) = do if a == b then return a else throwError "Passwords don't match!" passwordForm = withCheck #password_confirmation passwordsMatch ((,) <$> field #password notEmpty <*> field #password_confirmation notEmpty)Note that you must specify the field name on which to add a validation error message in case the check fails. The field name should be relative and point to a field in the argument parser, not full path from top-level of the form. For example this form: 2biggerForm = subParser #password_form passwordForm,will report validation error for the field %"password_form.password_confirmation" if the check fails (note that "password_form"+ is correctly prepended to the field path).formaRun a parser on given input.formaRun form purely. formaName of the fieldformaChecker that performs validation and possibly transformation of the field value formaName of the field formaField name to descend toforma SubparserformaWrapped parser forma#Field to assign validation error toformaThe check to performformaOriginal parserformaParser with the check attachedformaThe form parser to runformaInput for the parserformaThe result of parsingformaThe form parser to runformaInput for the parserformaThe result of parsing  %      !"#$%&'()*+&',)-.&/01"forma-1.2.0-9vfc7O8PFZdG7MjJxTILcR Web.FormaInSet FieldName FormParser FormResult ParsingFailedValidationFailed Succeeded unFieldName showFieldNamefieldfield'value subParser withCheckrunForm runFormPure$fToJSONFieldName$fSemigroupFieldName$fApplicativeFormResult$fToJSONFormResult$fAlternativeFormParser$fApplicativeFormParser$fFunctorFormParser$fIsLabelnameFieldName$fEqFormResult$fShowFormResult$fFunctorFormResult $fEqFieldName$fOrdFieldName$fShowFieldNameghc-prim GHC.Types Constraint text-1.2.3.2Data.Text.InternalTextbaseGHC.Base<>$aeson-2.0.1.0-IpdJi8HKI9m4tx2sYbLjJZData.Aeson.Types.InternalValueMonadData.Aeson.Types.FromJSONFromJSON Control.Monad>=>