fe v0.1.5 FE.Review View Source

FE.Review is a data type similar to FE.Result, made for representing output of a computation that either succeed (accepted) or fail (rejected), but that might continue despite of issues encountered (issues).

One could say that the type is a specific implementation of a writer monad, that collects issues encountered during some computation.

For instance, it might be used for validation of a user input, when we don’t want to stop the process of validation when we encounter the first mistake, but rather we would like to collect all the user’s mistakes before returning feedback to her.

Link to this section Summary

Functions

Creates a FE.Review representing a successful output of a computation

Applies accepted value of a FE.Review to a provided function. Returns its return value, that should be of FE.Review type

Works like fold/3, except that the first element of the provided list is removed from it, converted to an accepted FE.Review and treated as the initial accumulator

Folds over provided list of elements applying it and current accumulator to the provided function

Creates a FE.Review representing a problematic output of a computation that there were some issues with

Transforms a successful or a problematic value in a FE.Review using a provided function

Transform issues stored in a FE.Review using a provided function

Creates a FE.Review representing an errornous output of a computation with a list of issues encountered during the computation

Returns the accepted value stored in a FE.Review, raises an FE.Review.Error if either rejected or value with issues is passed

Returns the accepted value stored in a FE.Review or a provided default if either rejected or value with issues is passed

Link to this section Types

Link to this type t(a, b) View Source
t(a, b) :: {:accepted, a} | {:issues, a, [b]} | {:rejected, [b]}

Link to this section Functions

Link to this function accepted(value) View Source
accepted(a) :: t(a, any()) when a: var

Creates a FE.Review representing a successful output of a computation.

Link to this function and_then(review, f) View Source
and_then(t(a, b), (a -> t(c, b))) :: t(c, b) when a: var

Applies accepted value of a FE.Review to a provided function. Returns its return value, that should be of FE.Review type.

Applies value with issues of a FE.Review to a provided function. If accepted value is returned, then the value is replaced, but the issues remain the same. If new value with issues is returned, then the value is replaced and the issues are appended to the list of current issues. If rejected is returned, then the issues are appended to the list of current issues, if issues were passed.

Useful for chaining together a computation consisting of multiple steps, each of which takes either a success value or value with issues wrapped in FE.Review as an argument and returns a FE.Review.

Examples

iex> FE.Review.and_then(
...>  FE.Review.rejected(["foo"]),
...>  &FE.Review.accepted(String.length(&1)))
FE.Review.rejected(["foo"])

iex> FE.Review.and_then(
...>  FE.Review.issues("foo", ["bar", "baz"]),
...>  &FE.Review.accepted(String.length(&1)))
FE.Review.issues(3, ["bar", "baz"])

iex> FE.Review.and_then(
...>  FE.Review.issues("foo", ["bar", "baz"]),
...>  &FE.Review.issues(String.length(&1), ["qux"]))
FE.Review.issues(3, ["bar", "baz", "qux"])

iex> FE.Review.and_then(FE.Review.accepted(1), &FE.Review.issues(&1, [:one]))
FE.Review.issues(1, [:one])
Link to this function fold(list, f) View Source
fold([c], (c, a -> t(a, b))) :: t(a, b) when c: var, a: var

Works like fold/3, except that the first element of the provided list is removed from it, converted to an accepted FE.Review and treated as the initial accumulator.

Then, fold is executed over the remainder of the provided list.

Examples

iex> FE.Review.fold([1], fn _, _ -> FE.Review.rejected([:foo]) end)
FE.Review.accepted(1)

iex> FE.Review.fold([1, 2, 3], &FE.Review.accepted(&1 + &2))
FE.Review.accepted(6)

iex> FE.Review.fold([1, 2, 3], &FE.Review.issues(&1 + &2, [&2]))
FE.Review.issues(6, [1, 3])

iex> FE.Review.fold([1, 2, 3, 4], fn
...>   _, 6 -> FE.Review.rejected(["six"])
...>   x, y -> FE.Review.issues(x + y, [y])
...> end)
FE.Review.rejected([1, 3, "six"])

iex> FE.Review.fold([1, 2, 3, 4], fn
...>   x, 6 -> FE.Review.issues(x + 6, ["six"])
...>   x, y -> FE.Review.accepted(x + y)
...> end)
FE.Review.issues(10, ["six"])
Link to this function fold(review, elems, f) View Source
fold(t(a, b), [c], (c, a -> t(a, b))) :: t(a, b) when c: var, a: var

Folds over provided list of elements applying it and current accumulator to the provided function.

The next accumulator is the same as the result of calling and_then with the current accumulator and the provided function.

The provided FE.Review is initial accumulator.

Examples

iex> FE.Review.fold(FE.Review.rejected([:error]), [],
...>  &FE.Review.accepted(&1 + &2))
FE.Review.rejected([:error])

iex> FE.Review.fold(FE.Review.accepted(5), [1, 2, 3],
...>   &FE.Review.accepted(&1 * &2))
FE.Review.accepted(30)

iex> FE.Review.fold(FE.Review.accepted(5), [1, 2, 3],
...>   &FE.Review.issues(&1 * &2, [&1]))
FE.Review.issues(30, [1, 2, 3])

iex> FE.Review.fold(FE.Review.issues(5, [:five]), [1, 2, 3],
...>   &FE.Review.accepted(&1 * &2))
FE.Review.issues(30, [:five])

iex> FE.Review.fold(FE.Review.accepted(5), [1, 2, 3], fn
...>   x, 10 -> FE.Review.issues(x * 10, ["it's a ten!"])
...>   x, y -> FE.Review.accepted(x * y)
...> end)
FE.Review.issues(30, ["it's a ten!"])

iex> FE.Review.fold(FE.Review.accepted(5), [1, 2, 3], fn
...>   _, 10 -> FE.Review.rejected(["it's a ten!"])
...>   x, y -> FE.Review.accepted(x * y)
...> end)
FE.Review.rejected(["it's a ten!"])
Link to this function issues(value, issues) View Source
issues(a, b) :: t(a, b) when a: var, b: var

Creates a FE.Review representing a problematic output of a computation that there were some issues with.

Link to this function map(review, f) View Source
map(t(a, b), (a -> c)) :: t(c, b) when a: var, c: var

Transforms a successful or a problematic value in a FE.Review using a provided function.

Examples

iex> FE.Review.map(FE.Review.rejected(["foo"]), &String.length/1)
FE.Review.rejected(["foo"])

iex> FE.Review.map(FE.Review.issues("foo", ["b", "ar"]), &String.length/1)
FE.Review.issues(3, ["b", "ar"])

iex> FE.Review.map(FE.Review.accepted("baz"), &String.length/1)
FE.Review.accepted(3)
Link to this function map_issues(review, f) View Source
map_issues(t(a, b), (b -> c)) :: t(a, c) when b: var, c: var

Transform issues stored in a FE.Review using a provided function.

Examples

iex> FE.Review.map_issues(FE.Review.accepted("ack!"), &String.length/1)
FE.Review.accepted("ack!")

iex> FE.Review.map_issues(FE.Review.issues("a", ["bb", "ccc"]), &String.length/1)
FE.Review.issues("a", [2, 3])

iex> FE.Review.map_issues(FE.Review.rejected(["dddd", "eeeee"]), &String.length/1)
FE.Review.rejected([4, 5])
Link to this function rejected(issues) View Source
rejected([b]) :: t(any(), b) when b: var

Creates a FE.Review representing an errornous output of a computation with a list of issues encountered during the computation.

Link to this function to_maybe(review) View Source
to_maybe(t(a, any())) :: FE.Maybe.t(a)

Transforms FE.Review to a FE.Maybe.

Any accepted value of a FE.Review becomes a FE.Maybe with the same value.

If there are any issues either in a rejected FE.Review or coupled with a value, a FE.Maybe without a value is returned.

Examples

iex> FE.Review.to_maybe(FE.Review.issues(1, [2, 3]))
FE.Maybe.nothing()

iex> FE.Review.to_maybe(FE.Review.accepted(4))
FE.Maybe.just(4)

iex> FE.Review.to_maybe(FE.Review.rejected([5, 6, 7]))
FE.Maybe.nothing()
Link to this function to_result(review) View Source
to_result(t(a, b)) :: FE.Result.t(a, [b])

Transforms FE.Review to a FE.Result.

Any accepted value of a FE.Review becomes a successful value of a FE.Result.

If there are any issues either in a rejected FE.Review or coupled with a value, all the issues become a errornous output of the output FE.Result.

Examples

iex> FE.Review.to_result(FE.Review.issues(1, [2, 3]))
FE.Result.error([2, 3])

iex> FE.Review.to_result(FE.Review.accepted(4))
FE.Result.ok(4)

iex> FE.Review.to_result(FE.Review.rejected([5, 6, 7]))
FE.Result.error([5, 6, 7])
Link to this function unwrap!(review) View Source
unwrap!(t(a, any())) :: a when a: var

Returns the accepted value stored in a FE.Review, raises an FE.Review.Error if either rejected or value with issues is passed

Examples

iex> FE.Review.unwrap!(FE.Review.accepted("foo"))
"foo"
Link to this function unwrap_or(review, default) View Source
unwrap_or(t(a, any()), a) :: a when a: var

Returns the accepted value stored in a FE.Review or a provided default if either rejected or value with issues is passed

Examples

iex> FE.Review.unwrap_or(FE.Review.rejected(["no", "way"]), :default)
:default

iex> FE.Review.unwrap_or(FE.Review.issues(1, ["no", "way"]), :default)
:default

iex> FE.Review.unwrap_or(FE.Review.accepted(123), :default)
123