bellroy / elm-parse-dont-validate / Parse.Dont.Validate.Parser

This library provides a bunch of parser combinators and could be used for Web form validation.

It follows ideas described here: https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validateBy/


type alias Parser inp err out =
inp -> Result (Cons err) out

Parser type

inp Input type (what is parsed/validated) err Error type (Could be your custom error type) out Output type (Could be your domain type)

all : Cons (Parser inp err a) -> inp -> Result (Cons err) (Cons a)

Given a non-empty list of uniform parsers returns a parser that produces a non empty list of their results. If any of the provided parsers fails - resulting parser also fails.

andThen : Parser a err b -> Parser inp err a -> inp -> Result (Cons err) b

Parser composition: result produced by second parser is fed to the first

by : (inp1 -> inp0) -> Parser inp0 err out -> Parser inp1 err (out -> b) -> Parser inp1 err b

Useful for a "pipeline" style:

example : Parser { bar : String, baz : String } Error Foo
example =
    succeed (\a b -> Foo a b)
        |> by .bar parseBar
        |> by .baz parseBaz

contramap : (inp1 -> inp0) -> Parser inp0 err out -> Parser inp1 err out

Maps over Parser input

fail : err -> Result (Cons err) out

Returns error

fromReader : (inp -> Maybe out) -> err -> Parser inp err out

Create Parser from function of type inp -> Maybe out

map : (out0 -> out1) -> Parser inp err out0 -> Parser inp err out1

Maps over parser result

mapError : (err0 -> err1) -> Parser inp err0 out -> Parser inp err1 out

Maps over parser error

merge : (a -> b -> c) -> Parser inp err a -> Parser inp err b -> inp -> Result (Cons err) c

When given a function that merges parsing results and two parsers producing such results - returns a parser that produces a result of that function.

ok : out -> Result (Cons err) out

Returns successfully parsed value

run : Parser input err out -> input -> Result (Cons err) out

Syntactic abstraction: applies parser to its input

succeed : out -> Parser input err out

Useful for a "pipeline" style:

example : Parser { bar : String, baz : String } Error Foo
example =
    succeed (\a b -> Foo a b)
        |> by .bar parseBar
        |> by .baz parseBaz
        |> validateBy identity barBazParser

validateBy : (inp1 -> inp0) -> Parser inp0 err () -> Parser inp1 err b -> Parser inp1 err b

Useful for a "pipeline" style when validator emits an error message but reurns () in order not to consume constructor argument:

example : Parser { bar: String, baz: String } Error Foo
example =
    succeed (\bar baz -> Foo bar baz)
        |> by .bar parseBar
        |> by .baz parseBaz
        |> validateBy identity barBazParser

barBazParser : { bar: String, baz: String } Error Unit
barBazParser { bar, baz } =
    if bar /= baz
        then Parser.fail "Bar != Baz"
        else Parser.ok ()

fromPredicate : (inp -> Basics.Bool) -> err -> (inp -> out) -> inp -> Result (Cons err) out

Create Parser from predicate function that returns a wrapped input value. Parser fails with provided error in case if predicate evaluates to False.

zip : Parser inp err a -> Parser inp err b -> Parser inp err ( a, b )

Given 2 parsers, feeds same input into both of them and returns results as tuple

note : err -> Parser inp () out -> Parser inp err out

Given a parser without error decorates it with an error provided