dwayne/elm-validation/1.0.0

Validation

A Validation represents either success or failure.

type Validation error value

It can fail with one or more errors. The major difference between Validation and Result is that when validations are composed their errors accumulate.

Construct

succeed : a -> Validation e a
fail : e -> Validation e a
failWithErrors : e -> List e -> Validation e a
fromResult : Result e a -> Validation e a
fromResult (Ok 5) == succeed 5


fromResult (Err "x") == fail "x"
fromMaybe : e -> Maybe a -> Validation e a
fromMaybe "x" (Just 5) == succeed 5


fromMaybe "x" Nothing == fail "x"

Query

isValid : Validation e a -> Bool
isValid (succeed 5) == True


isValid (fail "x") == False
isInvalid : Validation e a -> Bool
isInvalid (succeed 5) == False


isInvalid (fail "x") == True

Map

map : (a -> value) -> Validation x a -> Validation x value

Apply a function to a validation. If the validation is a success, the value will be converted. If the validation is a failure, the same error will be propagated.

map sqrt (succeed 4.0) == succeed 2.0


map sqrt (fail "bad input") == fail "bad input"
(a -> b -> value)
-> Validation x a
-> Validation x b
-> Validation x value

Apply a function if both validations are a success. If not, the errors will be accumulated in order of failure.

map2 max (succeed 42) (succeed 13) == succeed 42


map2 max (fail "x") (succeed 13) == fail "x"


map2 max (succeed 42) (fail "y") == fail "y"


map2 max (fail "x") (fail "y") == failWithErrors "x" [ "y" ]
(a -> b -> c -> value)
-> Validation x a
-> Validation x b
-> Validation x c
-> Validation x value

Apply a function if all three validations are a success. If not, the errors will be accumulated in order of failure.

map3 (\a b c -> a + b + c) (succeed 1) (succeed 2) (succeed 3) == succeed 6


map3 (\a b c -> a + b + c) (succeed 1) (fail "y") (succeed 3) == fail "y"


map3 (\a b c -> a + b + c) (fail "x") (succeed 2) (fail "z") == failWithErrors "x" [ "z" ]


map3 (\a b c -> a + b + c) (fail "x") (fail "y") (fail "z") == failWithErrors "x" [ "y", "z" ]
(a -> b -> c -> d -> value)
-> Validation x a
-> Validation x b
-> Validation x c
-> Validation x d
-> Validation x value
(a -> b -> c -> d -> e -> value)
-> Validation x a
-> Validation x b
-> Validation x c
-> Validation x d
-> Validation x e
-> Validation x value
mapError : (x -> y) -> Validation x a -> Validation y a

Apply

apply : Validation x a -> Validation x (a -> b) -> Validation x b

Adds support for an applicative style of programming.

Practically, it means that when you need to go beyond map5 you can use this function together with succeed to achieve it. For e.g.

succeed (\a b c d e f g h i j k -> ...)
    |> apply va
    |> apply vb
    |> apply vc
    |> apply vd
    |> apply ve
    |> apply vf
    |> apply vg
    |> apply vh
    |> apply vi
    |> apply vj
    |> apply vk

Chain

andThen : (a -> Validation x b) -> Validation x a -> Validation x b

Chain together a sequence of validations that may fail.

We only continue with the callback if things are going well.

toInt : String -> Validation String Int
toInt rawString =
    fromMaybe "cannot convert to an Int" (String.toInt rawString)


toMonthFromInt : Int -> Validation String Int
toMonthFromInt anyInt =
    if anyInt >= 1 && anyInt <= 12 then
        succeed anyInt


    else
        fail "months must be between 1 and 12"


toMonthFromString : String -> Validation String Int
toMonthFromString rawString =
    toInt rawString
        |> andThen toMonthFromInt


-- toMonthFromString "4" == succeed 4
-- toMonthFromString "9" == succeed 9
-- toMonthFromString "a" == fail "cannot convert to an Int"
-- toMonthFromString "0" == fail "months must be between 1 and 12"

Convert

withDefault : a -> Validation e a -> a
withDefault 0 (succeed 5) == 5


withDefault 0 (fail "x") == 0
toResult : Validation e a -> Result (List e) a
toResult (succeed 5) == Ok 5


toResult (fail "x") == Err [ "x" ]


toResult (failWithErrors "x" [ "y" ]) == Err [ "x", "y" ]
toMaybe : Validation e a -> Maybe a
toMaybe (succeed 5) == Just 5


toMaybe (fail "x") == Nothing


toMaybe (failWithErrors "x" [ "y" ]) == Nothing

Handle Errors

firstError : Validation e a -> Maybe e
firstError (succeed 5) == Nothing


firstError (fail "x") == Just "x"


firstError (failWithErrors "x" [ "y", "z" ]) == Just "x"
lastError : Validation e a -> Maybe e
lastError (succeed 5) == Nothing


lastError (fail "x") == Just "x"


lastError (failWithErrors "x" [ "y", "z" ]) == Just "z"
allErrors : Validation e a -> List e
allErrors (succeed 5) == []


allErrors (fail "x") == [ "x" ]


allErrors (failWithErrors "x" [ "y", "z" ]) == [ "x", "y", "z" ]