Class: Either

Either

The Either type is intended for handling disjointed, but related values such as the result or exceptional behavior of some function. It is a disjunction similar to Validation. The key difference of the Either type is the focus on the single error as opposed to aggregating many errors. Much like Validation, Either is right-biased.

new Either(value){Either}

Name Type Description
value * Value to wrap.
Returns:
Type Description
Either Either wrapped value.
Examples

Via new

const v1 = new Right(value);
const v2 = new Left(otherValue);

Via function

const v3 = Right.from(value);
const v4 = Left.from(otherValue);

Via Either function

const fs = require("fs");
const Either = require("lodash-fantasy/data/Either");

function readFileSyncSafe(filePath, options) {
  let result = null;

  try {
    result = Either.Right.from(fs.readFileSync(filePath, options));
  } catch (error) {
    result = Either.Left.from(error);
  }

  return result;
}

module.exports = getValue;

Members

staticEither.all

Returns a Either that resolves all of the eithers in the collection into a single Either.
Example
const e1 = fs.readFileSync(filePath1);
// => Right(contents1)

const e2 = fs.readFileSync(filePath2);
// => Right(contents2)

const e3 = fs.readFileSync(filePath3);
// => Left(error3)

const e4 = fs.readFileSync(filePath4);
// => Left(error4)

Either.all([e1, e2]);
// => Right([contents1, contents2])

Either.all([e1, e2, e3]);
// => Left(error3)

Either.all([e1, e2, e3, e4]);
// => Left(error3)

staticEither.any

Returns the first Right in the collection or finally a Left.
Example
const e1 = fs.readFileSync(filePath1);
// => Right(contents1)

const e2 = fs.readFileSync(filePath2);
// => Right(contents2)

const e3 = fs.readFileSync(filePath3);
// => Left(error3)

const e4 = fs.readFileSync(filePath4);
// => Left(error4)

Either.any([e1, e2]);
// => Right(contents1)

Either.any([e2, e3]);
// => Right(contents2)

Either.any([e3, e4]);
// => Left(error3)

staticEither.each

Iterates over a collection of eithers and invokes the iteratee for each Either. The iteratee is invoked with one argument: (value). Iteratee functions may exit iteration early by explicitly returning a Left.
Example
const optionalValues = [
  getValue(path1, source), // => Right(value1)
  getValue(path2, source), // => Right(value2)
  getValue(path3, source), // => Left()
  getValue(path4, source) // => Left()
];

Either.each(eitherValue => eitherValue.ifRight(console.log), optionalValues);
// => Right(value1)
// => Right(value2)

staticEither.equals

Determines whether or not the other is equal in value to the current (this). This is not a reference check.
Examples

Reflexivity

Either.equals(v1, v1) === true;
// => true

Symmetry

Either(v1, v2) === Either.equals(v2, v1);
// => true

Transitivity

(Either.equals(v1, v2) === Either.equals(v2, v3)) && Either.equals(v1, v3)
// => true

staticEither.filter

Iterates over a collection of values, returning an array of all values the predicate for which returns truthy. The predicate is invoked with one argument: (value).
Example

Filter and log failures

const optionalValues = [
  getValue(path1, config), // => Right(value1)
  getValue(path2, config), // => Right(value2)
  getValue(path3, config), // => Left()
  getValue(path4, config) // => Left()
];

Either.filter(Either.isRight, optionalValues);
// => [Right(value1), Right(value2)]

staticEither.from

Creates a new Either from a value. If the value is already a Either instance, the value is returned unchanged. Otherwise, a new Right is made with the value.

staticEither.isEither

Determines whether or not the value is a Either.
Example
isEither();
// => false

isEither(Right.from());
// => true

isEither(Left.from(error));
// => true

staticEither.isLeft

Determines whether or not the value is a Left.
Example
isLeft();
// => false

isLeft(Left.from(error));
// => true

isLeft(Right.from());
// => false

staticEither.isRight

Determines whether or not the value is a Right.
Example
isRight();
// => false

isRight(Right.from());
// => true

isRight(Left.from(error));
// => false

staticEither.Left

Properties:
Name Type Description
Left Left Either left.

staticEither.map

Creates an array of values by running each Either in collection through the iteratee. The iteratee is invoked with one argument: (value).
Example

Mapping all values to promises

const optionalValues = [
  getValue(path1, config), // => Right(value1)
  getValue(path2, config), // => Right(value2)
  getValue(path3, config), // => Left(error1)
  getValue(path4, config) // => Left(error2)
];

Either.map(Either.toPromise, optionalValues);
// => [Promise.resolve(price1), Promise.resolve(price2), Promise.reject(error1), Promise.reject(error2)]

staticEither.mapIn

Creates an array of values by invoking Either#map with the iteratee for each Either in the collection. The iteratee is invoked with one argument: (value).
Example

Mapping each Either's value

const optionalValues = [
  getValue(path1, config), // => Right(1.5)
  getValue(path2, config), // => Right(2.25)
  getValue(path3, config), // => Left(error1)
  getValue(path4, config) // => Left(error2)
];

Either.mapIn(Math.floor, optionalValues);
// => [Right(1), Right(2), Left(error1), Left(error2)]

staticEither.of

Wraps the value in a Right. No parts of value are checked.
Example
Either.of();
// => Right()

Either.of(true);
// => Right(true)

Either.of(Right.from(value));
// => Right(Right(value))

Either.of(Left.from(error));
// => Right(Left(error))

staticEither.reduce

Reduces collection to a value which is the accumulated result of running each value in the values collection through the iteratee, where each successive invocation is supplied the return value of the previous. The iteratee is invoked with two arguments: (accumulator, value).
Example
const eitherValues = [
  getValue(path1, config), // => Right(value1)
  getValue(path2, config), // => Right(value2)
  getValue(path3, config), // => Left(error1)
  getValue(path4, config) // => Left(error2)
];

// Using lodash/fp/concat
Either.reduce(
  (result, value) => value.isRight() ? concat(result, value.get()) : result,
  [],
  eitherValues
);
// => [value1, value2]

staticEither.Right

Properties:
Name Type Description
Right Right Either right.

staticEither.toMaybe

Converts a Either to a Maybe. Right becomes a Just and Left becomes Nothing.
Examples

Right to Just

Either.toMaybe(Maybe, Right.from(value));
// => Maybe.Just(value);

Left to Nothing

Either.toMaybe(Maybe, Left.from(error));
// => Maybe.Nothing();

staticEither.toPromise

Converts a validation to a Promise using the provided Promise implementation.
Example

Convert with bluebird's implementation of Promise

const toBluebird = Either.toPromise(require("bluebird"));

toBluebird(Right.from(value));
// => Promise.resolve(value);

toBluebird(Left.from(error));
// => Promise.reject(error);

staticEither.toValidation

Converts a Either to a Validation. Right becomes a Success and Left becomes Failure.
Examples

Right to Success

Either.toValidation(Validation, Right.from(value));
// => Validation.Success(value);

Left to Failure

Either.toValidation(Validation, Left.from(error));
// => Validation.Failure();

staticEither.try

Tries to invoke a supplier. The result of the supplier is returned in a Right. If an exception is thrown, the error is returned in a Left. The function takes no arguments.
Example
Either.try(normalFunction);
// => Right(returnValue)

Either.try(throwableFunction);
// => Left(error)

Methods

abstractap(other){Either}

Applies the function contained in the instance of a Right to the value contained in the provided Right, producing a Right containing the result. If the instance is a Left, the result is the Left instance. If the instance is a Right and the provided Either is Left, the result is the provided Left.
Name Type Description
other Either Value to apply to the function wrapped in the Right.
Returns:
Type Description
Either Right wrapped applied function or Left.
Example

Right#ap

const findPerson = curryN(3, Person.find); // Person.find(name, birthdate, address)

Right.from(findPerson) // => Right(findPerson)
  .ap(Right.try(getName())) // => Right(name)
  .ap(Right.try(getBirthdate())) // => Right(birthdate)
  .ap(Right.try(getAddress())) // => Right(address)
  .ifRight(console.log); // => Log Person.find() response

abstractbimap(failureMap, successMap){Either}

Transforms a Either by applying the first function to the contained value for a Left or the second function for a Right. The result of each map is wrapped in the corresponding type.
Name Type Description
failureMap function Map to apply to the Left.
successMap function Map to apply to the Right.
Returns:
Type Description
Either Either wrapped value mapped with the corresponding mapping function.
Example
// Using lodash/fp/get
Either.try(loadFile)
  .bimap(get("message"), parseFile)
  // ... other actions in workflow

abstractchain(method){Either}

Applies the provided function to the value contained for a Right. The function should return the value wrapped in a Either. If the instance is a Left, the function is ignored and then instance is returned unchanged.
Name Type Description
method Chain.<Either> The function to invoke with the value.
Returns:
Type Description
Either Either wrapped value returned by the provided method.
Example

Right#chain

// Using lodash/fp/curry and getOr
const getConfigOption = curry((path, config) => Either.Right.from(getOr(
  Either.Left.from(`Value not found at "${path}"`),
  path,
  config
)));

Either.of(config)
  .chain(getConfigOption("path.to.option"))

equals(other){Boolean}

Determines whether or not the other is equal in value to the current (this). This is not a reference check.
Name Type Description
other * Other value to check.
Returns:
Type Description
Boolean true if the two Eithers are equal; false if not equal.
Examples

Reflexivity

v1.equals(v1) === true;
// => true

Symmetry

v1.equals(v2) === v2.equals(v1);
// => true

Transitivity

(v1.equals(v2) === v2.equals(v3)) && v1.equals(v3)
// => true

abstractextend(){Either}

Extends the Either. This is used for workflow continuation where the context has shifted.
Type Description
Extend.<Either> method - The function to invoke with the value.
Returns:
Type Description
Either
Example

Workflow continuation

// Workflow from makeRequest.js
const makeRequest = requestOptions => requestAsPromise(requestOptions)
  .then(Right.from)
  .catch(Left.from);

// Workflow from savePerson.js
const savePerson = curry((requestOptions, eitherPerson) => eitherPerson
  .map(Person.from)
  .map(person => set("body", person, requestOptions))
  .map(makeRequest)
);

// Workflow from processResponse.js
const processResponse = eitherResponse => eitherResponse
  .ifLeft(console.error)
  .ifRight(console.log);

Either.of(person)
  .extend(savePerson({ method: "POST" }))
  .extend(processResponse);
Returns the value if the instance is a Right otherwise the null.
Returns:
Type Description
*
Examples

Right#get

Right.from(value).get();
// => value

Left#get

Left.from(error).get();
// => null

abstractifLeft(method){Either}

Applies the provided function to the value contain for a Left. Any return value from the function is ignored. If the instance is a Right, the function is ignored and the instance is returned.
Name Type Description
method Consumer The function to invoke with the value.
Returns:
Type Description
Either Current instance.
Examples

Right#ifLeft

Right.from(value).ifLeft(doSomething); // void
// => Right(value)

Left#ifLeft

Left.from(error).ifLeft(doSomething); // doSomething(error)
// => Left(error)

abstractifRight(method){Either}

Applies the provided function to the value contain for a Right. Any return value from the function is ignored. If the instance is a Left, the function is ignored and the instance is returned.
Name Type Description
method Consumer The function to invoke with the value.
Returns:
Type Description
Either Current instance.
Examples

Right#ifRight

Right.from(value).ifRight(doSomething); // doSomething(value)
// => Right(value)

Left#ifRight

Left.from(error).ifRight(doSomething); // void
// => Left(error)

isLeft(){Boolean}

Determines whether or not the instance is a Left.
Returns:
Type Description
Boolean true if the instance is a Left; false is not.
Examples

Right#isLeft

Right.from(value).isLeft();
// => false

Left#isLeft

Left.from(error).isLeft();
// => true

isRight(){Boolean}

Determines whether or not the instance is a Right.
Returns:
Type Description
Boolean true if the instance is a Right; false is not.
Examples

Right

Right.from(value).isLeft();
// => true

Left#isRight

Left.from(error).isLeft();
// => false

abstractmap(method){Either}

Applies the provided function to the value contained for a Right which is, in turn, wrapped in a Right. If the instance is a Left, the function is ignored and then instance is returned unchanged.
Name Type Description
method function The function to invoke with the value.
Returns:
Type Description
Either Either wrapped value mapped with the provided method.
Example
// Using lodash/fp/flow and sort
Right.from([1, 3, 2]).map(flow(sort, join(", ")));
// => Right("1, 2, 3")

Left.from(error).map(flow(sort, join(", ")));
// => Left(error)
See:

abstractorElse(method){*}

Returns the value if the instance is a Right otherwise returns the value supplied if the instance is a Left.
Name Type Description
method Consumer The function to invoke with the value.
Returns:
Type Description
*
Examples

Right#orElse

Right.from(value).orElse(otherValue);
// => value

Left#orElse

Left.from(error).orElse(otherValue);
// => otherValue

abstractorElseGet(method){*}

Return the value if the instance is a Right otherwise returns the value from the function provided.
Name Type Description
method Supplier The function supplying the optional value.
Returns:
Type Description
*
Examples

Right#orElseGet

Right.from(value).orElseGet(getOtherValue);
// => value

Left#orElseGet

Left.from(error).orElse(getOtherValue);
// => otherValue

abstractorElseThrow(method){*}

Returns the value if the instance is a Right otheriwse throws the Error supplied by the function provided. The function receives the value of the Left as its argument.
Name Type Description
method function The function to invoke with the value.
Throws:
returned by the provided function.
Type
Error
Returns:
Type Description
*
Examples

Right#orElseThrow

Right.from(value).orElseThrow(createException);
// => value

Left#orElseThrow

Left.from(error).orElseThrow(createException); // throw createException(error)

abstracttoMaybe(maybe){Maybe}

Converts the Either to a Maybe. Right becomes Just and Left becomes Nothing.
Name Type Description
maybe Maybe Maybe implementation.
Returns:
Type Description
Maybe Maybe wrapped value.
Examples

Right#toMaybe

Right.from(value).toMaybe(Maybe);
// => Maybe.Just(value);

Left#toMaybe

Left.from(error).toMaybe(Maybe);
// => Maybe.Nothing();

abstracttoPromise(promise){Promise}

Converts the Either to a Promise using the provided Promise implementation.
Name Type Description
promise Promise Promise implementation.
Returns:
Type Description
Promise Promise wrapped value.
Examples

Right#toPromise

const Bluebird = require("bluebird");

Right.from(value).toPromise(Bluebird);
// => Promise.resolve(value);

Left#toPromise

const Bluebird = require("bluebird");

Left.from(error).toPromise(Bluebird);
// => Promise.reject(error);

abstracttoString(){String}

Returns a String representation of the Either.
Returns:
Type Description
String String representation.
Examples

Right#toString

Right.from(1).toString();
// => "Either.Right(1)"

Left#toString

Left.from(error).toString();
// => "Either.Left(error)"

abstracttoValidation(validation){Validation}

Converts the Either to a Validation. Right becomes Success and Left becomes Failure.
Name Type Description
validation Validation Validation implementation.
Returns:
Type Description
Validation Validation wrapped value.
Examples

Right#toValidation

Right.from(value).toValidation(Validation);
// => Validation.Success(value);

Left#toValidation

Left.from(error).toValidation(Validation);
// => Validation.Failure();