Class Either<L,R>
- java.lang.Object
-
- com.jnape.palatable.lambda.adt.Either<L,R>
-
- Type Parameters:
L- The left parameter typeR- The right parameter type
- All Implemented Interfaces:
CoProduct2<L,R,Either<L,R>>,Applicative<R,Either<L,?>>,Bifunctor<L,R,Either<?,?>>,BoundedBifunctor<L,R,java.lang.Object,java.lang.Object,Either<?,?>>,Functor<R,Either<L,?>>,Monad<R,Either<L,?>>,MonadError<L,R,Either<L,?>>,MonadRec<R,Either<L,?>>,Traversable<R,Either<L,?>>
- Direct Known Subclasses:
Either.Left,Either.Right
public abstract class Either<L,R> extends java.lang.Object implements CoProduct2<L,R,Either<L,R>>, MonadError<L,R,Either<L,?>>, MonadRec<R,Either<L,?>>, Traversable<R,Either<L,?>>, Bifunctor<L,R,Either<?,?>>
The binary tagged union, implemented as a specializedCoProduct2. General semantics tend to connote "success" values via the right value and "failure" values via the left values.Eithers are bothMonads andTraversables over their right value and areBifunctors over both values.
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description private static classEither.Left<L,R>private static classEither.Right<L,R>
-
Constructor Summary
Constructors Modifier Constructor Description privateEither()
-
Method Summary
All Methods Static Methods Instance Methods Abstract Methods Concrete Methods Deprecated Methods Modifier and Type Method Description <L2,R2>
Either<L2,R2>biMap(Fn1<? super L,? extends L2> leftFn, Fn1<? super R,? extends R2> rightFn)Dually map covariantly over both the left and right parameters.<L2> Either<L2,R>biMapL(Fn1<? super L,? extends L2> fn)Covariantly map over the left parameter.<R2> Either<L,R2>biMapR(Fn1<? super R,? extends R2> fn)Covariantly map over the right parameter.Either<L,R>catchError(Fn1<? super L,? extends Monad<R,Either<L,?>>> recoveryFn)<R2> Either<L,R2>discardL(Applicative<R2,Either<L,?>> appB)Sequence both thisApplicativeandappB, discarding thisApplicative'sresult and returningappB.<R2> Either<L,R>discardR(Applicative<R2,Either<L,?>> appB)Sequence both thisApplicativeandappB, discardingappB'sresult and returning thisApplicative.<C> Choice3<L,R,C>diverge()Diverge this coproduct by introducing another possible type that it could represent.Either<L,R>filter(Fn1<? super R,? extends java.lang.Boolean> pred, Fn0<L> leftFn0)If this is a right value, applypredto it.Either<L,R>filter(Fn1<? super R,? extends java.lang.Boolean> pred, Fn1<? super R,? extends L> leftFn)If this is a right value, applypredto it.<R2> Either<L,R2>flatMap(Fn1<? super R,? extends Monad<R2,Either<L,?>>> rightFn)If a right value, unwrap it and apply it torightFn, returning the resultingEither<L ,R>.<R2> Either<L,R2>fmap(Fn1<? super R,? extends R2> fn)Covariantly transmute this functor's parameter using the given mapping function.Lforfeit(Fn1<? super R,? extends L> forfeitFn)Inverse of recover.static <L,R>
Either<L,R>fromMaybe(Maybe<R> maybe, Fn0<L> leftFn0)Convert aMaybe<R> into anEither<L, R>, supplying the left value fromleftFnin the case ofMaybe.nothing().Either<R,L>invert()Swap the type parameters.<R2> Lazy<Either<L,R2>>lazyZip(Lazy<? extends Applicative<Fn1<? super R,? extends R2>,Either<L,?>>> lazyAppFn)Given alazyinstance of this applicative over a mapping function, "zip" the two instances together using whatever application semantics the current applicative supports.static <L,R>
Either<L,R>left(L l)Static factory method for creating a left value.abstract <V> Vmatch(Fn1<? super L,? extends V> leftFn, Fn1<? super R,? extends V> rightFn)Given two mapping functions (one from anLto aV, one from anRto aV), unwrap the value stored in thisEither, apply the appropriate mapping function, and return the result.Either<L,R>merge(Fn2<? super L,? super L,? extends L> leftFn, Fn2<? super R,? super R,? extends R> rightFn, Either<L,R>... others)Given two binary operators over L and R, merge multipleEither<L, R>s into a singleEither<L, R>.Ror(R defaultValue)Return the value wrapped by thisEitherif it's a right value; otherwise, return defaultValue.<T extends java.lang.Throwable>
RorThrow(Fn1<? super L,? extends T> throwableFn)Return the wrapped value if this is a right; otherwise, map the wrapped left value to aTand throw it.Either<L,R>peek(Fn1<? super L,? extends IO<?>> leftEffect, Fn1<? super R,? extends IO<?>> rightEffect)Either<L,R>peek(Fn1<? super R,? extends IO<?>> effect)<R2> Either<L,R2>pure(R2 r2)Lift the valuebinto this applicative functor.static <L> Pure<Either<L,?>>pureEither()Rrecover(Fn1<? super L,? extends R> recoveryFn)"Recover" from a left value by applying a recoveryFn to the wrapped value and returning it in the case of a left value; otherwise, return the wrapped right value.static <L,R>
Either<L,R>right(R r)Static factory method for creating a right value.Either<L,R>throwError(L l)Throw an error value of typeEinto themonad.Maybe<R>toMaybe()In the left case, returns aMaybe.nothing(); otherwise, returnsMaybe.maybe(A)around the right value.<B> Either<L,B>trampolineM(Fn1<? super R,? extends MonadRec<RecursiveResult<R,B>,Either<L,?>>> fn)Given some operation yielding aRecursiveResultinside thisMonadRec, internally trampoline the operation until it yields aterminationinstruction.<R2,App extends Applicative<?,App>,TravB extends Traversable<R2,Either<L,?>>,AppTrav extends Applicative<TravB,App>>
AppTravtraverse(Fn1<? super R,? extends Applicative<R2,App>> fn, Fn1<? super TravB,? extends AppTrav> pure)Applyfnto each element of this traversable from left to right, and collapse the results into a single resulting applicative, potentially with the assistance of the applicative's pure function.static <R> Either<java.lang.Throwable,R>trying(Fn0<? extends R> fn0)Attempt to execute theFn0, returning its result in a right value.static <L,R>
Either<L,R>trying(Fn0<? extends R> fn0, Fn1<? super java.lang.Throwable,? extends L> leftFn)Attempt to execute theFn0, returning its result in a right value.static Either<java.lang.Throwable,Unit>trying(SideEffect sideEffect)Attempt to execute theSideEffect, returningUnitin a right value.static <L> Either<L,Unit>trying(SideEffect sideEffect, Fn1<? super java.lang.Throwable,? extends L> leftFn)Attempt to execute theSideEffect, returningUnitin a right value.<R2> Either<L,R2>zip(Applicative<Fn1<? super R,? extends R2>,Either<L,?>> appFn)Given another instance of this applicative over a mapping function, "zip" the two instances together using whatever application semantics the current applicative supports.-
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
-
Methods inherited from interface com.jnape.palatable.lambda.adt.coproduct.CoProduct2
embed, project, projectA, projectB
-
-
-
-
Method Detail
-
or
public final R or(R defaultValue)
Return the value wrapped by thisEitherif it's a right value; otherwise, return defaultValue.- Parameters:
defaultValue- the value to return if this is a left- Returns:
- the value wrapped by this Either if right; otherwise, defaultValue
-
recover
public final R recover(Fn1<? super L,? extends R> recoveryFn)
"Recover" from a left value by applying a recoveryFn to the wrapped value and returning it in the case of a left value; otherwise, return the wrapped right value.- Parameters:
recoveryFn- a function from L to R- Returns:
- either the wrapped value (if right) or the result of the left value applied to recoveryFn
-
forfeit
public final L forfeit(Fn1<? super R,? extends L> forfeitFn)
Inverse of recover. If this is a right value, apply the wrapped value toforfeitFnand return it; otherwise, return the wrapped left value.- Parameters:
forfeitFn- a function from R to L- Returns:
- either the wrapped value (if left) or the result of the right value applied to forfeitFn
-
orThrow
public final <T extends java.lang.Throwable> R orThrow(Fn1<? super L,? extends T> throwableFn) throws T extends java.lang.Throwable
Return the wrapped value if this is a right; otherwise, map the wrapped left value to aTand throw it.- Type Parameters:
T- the left parameter type (the throwable type)- Parameters:
throwableFn- a function from L to T- Returns:
- the wrapped value if this is a right
- Throws:
T- the result of applying the wrapped left value to throwableFn, if this is a leftT extends java.lang.Throwable
-
filter
public final Either<L,R> filter(Fn1<? super R,? extends java.lang.Boolean> pred, Fn0<L> leftFn0)
If this is a right value, applypredto it. If the result istrue, return the same value; otherwise, return the result ofleftSupplierwrapped as a left value.If this is a left value, return it.
- Parameters:
pred- the predicate to apply to a right valueleftFn0- the supplier of a left value if pred fails- Returns:
- this if a left value or a right value that pred matches; otherwise, the result of leftSupplier wrapped in a left
-
filter
public final Either<L,R> filter(Fn1<? super R,? extends java.lang.Boolean> pred, Fn1<? super R,? extends L> leftFn)
If this is a right value, applypredto it. If the result istrue, return the same value; otherwise, return the results of applying the right value toleftFnwrapped as a left value.- Parameters:
pred- the predicate to apply to a right valueleftFn- the function from the right value to a left value if pred fails- Returns:
- this is a left value or a right value that pred matches; otherwise, the result of leftFn applied to the right value, wrapped in a left
-
flatMap
public <R2> Either<L,R2> flatMap(Fn1<? super R,? extends Monad<R2,Either<L,?>>> rightFn)
If a right value, unwrap it and apply it torightFn, returning the resultingEither<L ,R>. Otherwise, return the left value.Note that because this monadic form of
flatMaponly supports mapping over a theoretical right value, the resultingEithermust be invariant on the same left value to flatten properly.- Specified by:
flatMapin interfaceMonad<L,R>- Specified by:
flatMapin interfaceMonadError<L,R,Either<L,?>>- Specified by:
flatMapin interfaceMonadRec<L,R>- Type Parameters:
R2- the new right parameter type- Parameters:
rightFn- the function to apply to a right value- Returns:
- the Either resulting from applying rightFn to this right value, or this left value if left
-
trampolineM
public <B> Either<L,B> trampolineM(Fn1<? super R,? extends MonadRec<RecursiveResult<R,B>,Either<L,?>>> fn)
Given some operation yielding aRecursiveResultinside thisMonadRec, internally trampoline the operation until it yields aterminationinstruction.Stack-safety depends on implementations guaranteeing that the growth of the call stack is a constant factor independent of the number of invocations of the operation. For various examples of how this can be achieved in stereotypical circumstances, see the referenced types.
- Specified by:
trampolineMin interfaceMonadRec<L,R>- Type Parameters:
B- the ultimate resulting carrier type- Parameters:
fn- the function to internally trampoline- Returns:
- the trampolined
MonadRec - See Also:
for a basic implementation,for a implementation,for an implementation leveraging an already stack-safe,for a implementation
-
invert
public final Either<R,L> invert()
Description copied from interface:CoProduct2Swap the type parameters.
-
merge
@SafeVarargs public final Either<L,R> merge(Fn2<? super L,? super L,? extends L> leftFn, Fn2<? super R,? super R,? extends R> rightFn, Either<L,R>... others)
Given two binary operators over L and R, merge multipleEither<L, R>s into a singleEither<L, R>. Note thatmergebiases towards left values; that is, if any left value exists, the result will be a left value, such that only unanimous right values result in an ultimate right value.- Parameters:
leftFn- the binary operator for LrightFn- the binary operator for Rothers- the other Eithers to merge into this one- Returns:
- the merged Either
-
peek
@Deprecated public Either<L,R> peek(Fn1<? super R,? extends IO<?>> effect)
Perform side-effects against a wrapped right value, returning back theEitherunaltered.- Parameters:
effect- the effecting consumer- Returns:
- the Either, unaltered
-
peek
@Deprecated public Either<L,R> peek(Fn1<? super L,? extends IO<?>> leftEffect, Fn1<? super R,? extends IO<?>> rightEffect)
Perform side-effects against a wrapped right or left value, returning back theEitherunaltered.- Parameters:
leftEffect- the effecting consumer for left valuesrightEffect- the effecting consumer for right values- Returns:
- the Either, unaltered
-
match
public abstract <V> V match(Fn1<? super L,? extends V> leftFn, Fn1<? super R,? extends V> rightFn)
Given two mapping functions (one from anLto aV, one from anRto aV), unwrap the value stored in thisEither, apply the appropriate mapping function, and return the result.
-
diverge
public <C> Choice3<L,R,C> diverge()
Diverge this coproduct by introducing another possible type that it could represent. As no morphisms can be provided mapping current types to the new type, this operation merely acts as a convenience method to allow the use of a more convergent coproduct with a more divergent one; that is, if aCoProduct3<String, Integer, Boolean>is expected, aCoProduct2<String, Integer>should suffice.Generally, we use inheritance to make this a non-issue; however, with coproducts of differing magnitudes, we cannot guarantee variance compatibility in one direction conveniently at construction time, and in the other direction, at all. A
CoProduct2could not be aCoProduct3without specifying all type parameters that are possible for aCoProduct3- more specifically, the third possible type - which is not necessarily known at construction time, or even useful if never used in the context of aCoProduct3. The inverse inheritance relationship -CoProduct3<CoProduct2- is inherently unsound, as aCoProduct3cannot correctly implementCoProduct2.match(com.jnape.palatable.lambda.functions.Fn1<? super A, ? extends R>, com.jnape.palatable.lambda.functions.Fn1<? super B, ? extends R>), given that the third typeCis always possible.For this reason, there is a
divergemethod supported between allCoProducttypes of single magnitude difference.- Specified by:
divergein interfaceCoProduct2<L,R,Either<L,R>>- Type Parameters:
C- the additional possible type of this coproduct- Returns:
- a
CoProduct3<A, B, C>
-
fmap
public final <R2> Either<L,R2> fmap(Fn1<? super R,? extends R2> fn)
Covariantly transmute this functor's parameter using the given mapping function. Generally this method is specialized to return an instance of the class implementing Functor.- Specified by:
fmapin interfaceApplicative<L,R>- Specified by:
fmapin interfaceFunctor<L,R>- Specified by:
fmapin interfaceMonad<L,R>- Specified by:
fmapin interfaceMonadError<L,R,Either<L,?>>- Specified by:
fmapin interfaceMonadRec<L,R>- Specified by:
fmapin interfaceTraversable<L,R>- Type Parameters:
R2- the new parameter type- Parameters:
fn- the mapping function- Returns:
- a functor over B (the new parameter type)
-
biMapL
public final <L2> Either<L2,R> biMapL(Fn1<? super L,? extends L2> fn)
Covariantly map over the left parameter.- Specified by:
biMapLin interfaceBifunctor<L,R,Either<?,?>>- Specified by:
biMapLin interfaceBoundedBifunctor<L,R,java.lang.Object,java.lang.Object,Either<?,?>>- Type Parameters:
L2- the new left parameter type- Parameters:
fn- the mapping function- Returns:
- a bifunctor over C (the new left parameter) and B (the same right parameter)
-
biMapR
public final <R2> Either<L,R2> biMapR(Fn1<? super R,? extends R2> fn)
Covariantly map over the right parameter. For all bifunctors that are also functors, it should hold thatbiMapR(f) == fmap(f).- Specified by:
biMapRin interfaceBifunctor<L,R,Either<?,?>>- Specified by:
biMapRin interfaceBoundedBifunctor<L,R,java.lang.Object,java.lang.Object,Either<?,?>>- Type Parameters:
R2- the new right parameter type- Parameters:
fn- the mapping function- Returns:
- a bifunctor over A (the same left parameter) and C (the new right parameter)
-
biMap
public final <L2,R2> Either<L2,R2> biMap(Fn1<? super L,? extends L2> leftFn, Fn1<? super R,? extends R2> rightFn)
Dually map covariantly over both the left and right parameters. This is isomorphic tobiMapL(lFn).biMapR(rFn).- Specified by:
biMapin interfaceBifunctor<L,R,Either<?,?>>- Specified by:
biMapin interfaceBoundedBifunctor<L,R,java.lang.Object,java.lang.Object,Either<?,?>>- Type Parameters:
L2- the new left parameter typeR2- the new right parameter type- Parameters:
leftFn- the left parameter mapping functionrightFn- the right parameter mapping function- Returns:
- a bifunctor over C (the new left parameter type) and D (the new right parameter type)
-
pure
public final <R2> Either<L,R2> pure(R2 r2)
Lift the valuebinto this applicative functor.- Specified by:
purein interfaceApplicative<L,R>- Specified by:
purein interfaceMonad<L,R>- Specified by:
purein interfaceMonadError<L,R,Either<L,?>>- Specified by:
purein interfaceMonadRec<L,R>- Type Parameters:
R2- the type of the returned applicative's parameter- Parameters:
r2- the value- Returns:
- an instance of this applicative over b
-
zip
public final <R2> Either<L,R2> zip(Applicative<Fn1<? super R,? extends R2>,Either<L,?>> appFn)
Given another instance of this applicative over a mapping function, "zip" the two instances together using whatever application semantics the current applicative supports.- Specified by:
zipin interfaceApplicative<L,R>- Specified by:
zipin interfaceMonad<L,R>- Specified by:
zipin interfaceMonadError<L,R,Either<L,?>>- Specified by:
zipin interfaceMonadRec<L,R>- Type Parameters:
R2- the resulting applicative parameter type- Parameters:
appFn- the other applicative instance- Returns:
- the mapped applicative
-
lazyZip
public <R2> Lazy<Either<L,R2>> lazyZip(Lazy<? extends Applicative<Fn1<? super R,? extends R2>,Either<L,?>>> lazyAppFn)
Given alazyinstance of this applicative over a mapping function, "zip" the two instances together using whatever application semantics the current applicative supports. This is useful for applicatives that support lazy evaluation and early termination.- Specified by:
lazyZipin interfaceApplicative<L,R>- Specified by:
lazyZipin interfaceMonad<L,R>- Specified by:
lazyZipin interfaceMonadError<L,R,Either<L,?>>- Specified by:
lazyZipin interfaceMonadRec<L,R>- Type Parameters:
R2- the resulting applicative parameter type- Parameters:
lazyAppFn- the lazy other applicative instance- Returns:
- the mapped applicative
- See Also:
Maybe,Either
-
discardL
public final <R2> Either<L,R2> discardL(Applicative<R2,Either<L,?>> appB)
Sequence both thisApplicativeandappB, discarding thisApplicative'sresult and returningappB. This is generally useful for sequentially performing side-effects.- Specified by:
discardLin interfaceApplicative<L,R>- Specified by:
discardLin interfaceMonad<L,R>- Specified by:
discardLin interfaceMonadError<L,R,Either<L,?>>- Specified by:
discardLin interfaceMonadRec<L,R>- Type Parameters:
R2- the type of the returned Applicative's parameter- Parameters:
appB- the other Applicative- Returns:
- appB
-
discardR
public final <R2> Either<L,R> discardR(Applicative<R2,Either<L,?>> appB)
Sequence both thisApplicativeandappB, discardingappB'sresult and returning thisApplicative. This is generally useful for sequentially performing side-effects.- Specified by:
discardRin interfaceApplicative<L,R>- Specified by:
discardRin interfaceMonad<L,R>- Specified by:
discardRin interfaceMonadError<L,R,Either<L,?>>- Specified by:
discardRin interfaceMonadRec<L,R>- Type Parameters:
R2- the type of appB's parameter- Parameters:
appB- the other Applicative- Returns:
- this Applicative
-
throwError
public Either<L,R> throwError(L l)
Throw an error value of typeEinto themonad.- Specified by:
throwErrorin interfaceMonadError<L,R,Either<L,?>>- Parameters:
l- the error type- Returns:
- the
monad
-
catchError
public Either<L,R> catchError(Fn1<? super L,? extends Monad<R,Either<L,?>>> recoveryFn)
- Specified by:
catchErrorin interfaceMonadError<L,R,Either<L,?>>- Parameters:
recoveryFn- the catch function- Returns:
- the recovered
Monad
-
traverse
public final <R2,App extends Applicative<?,App>,TravB extends Traversable<R2,Either<L,?>>,AppTrav extends Applicative<TravB,App>> AppTrav traverse(Fn1<? super R,? extends Applicative<R2,App>> fn, Fn1<? super TravB,? extends AppTrav> pure)
Applyfnto each element of this traversable from left to right, and collapse the results into a single resulting applicative, potentially with the assistance of the applicative's pure function.- Specified by:
traversein interfaceTraversable<L,R>- Type Parameters:
R2- the resulting element typeApp- the result applicative typeTravB- this Traversable instance over BAppTrav- the full inferred resulting type from the traversal- Parameters:
fn- the function to applypure- the applicative pure function- Returns:
- the traversed Traversable, wrapped inside an applicative
-
toMaybe
public final Maybe<R> toMaybe()
In the left case, returns aMaybe.nothing(); otherwise, returnsMaybe.maybe(A)around the right value.- Returns:
- Maybe the right value
-
fromMaybe
public static <L,R> Either<L,R> fromMaybe(Maybe<R> maybe, Fn0<L> leftFn0)
Convert aMaybe<R> into anEither<L, R>, supplying the left value fromleftFnin the case ofMaybe.nothing().- Type Parameters:
L- the left parameter typeR- the right parameter type- Parameters:
maybe- the maybeleftFn0- the supplier to use for left values- Returns:
- a right value of the contained maybe value, or a left value of leftFn's result
-
trying
public static <L,R> Either<L,R> trying(Fn0<? extends R> fn0, Fn1<? super java.lang.Throwable,? extends L> leftFn)
Attempt to execute theFn0, returning its result in a right value. If the supplier throws an exception, apply leftFn to it, wrap it in a left value and return it.- Type Parameters:
L- the left parameter typeR- the right parameter type- Parameters:
fn0- the supplier of the right valueleftFn- a function mapping E to L- Returns:
- the supplier result as a right value, or leftFn's mapping result as a left value
-
trying
public static <R> Either<java.lang.Throwable,R> trying(Fn0<? extends R> fn0)
Attempt to execute theFn0, returning its result in a right value. If the supplier throws an exception, wrap it in a left value and return it.- Type Parameters:
R- the right parameter type- Parameters:
fn0- the supplier of the right value- Returns:
- the supplier result as a right value, or a left value of the thrown exception
-
trying
public static <L> Either<L,Unit> trying(SideEffect sideEffect, Fn1<? super java.lang.Throwable,? extends L> leftFn)
Attempt to execute theSideEffect, returningUnitin a right value. If the runnable throws an exception, applyleftFnto it, wrap it in a left value, and return it.- Type Parameters:
L- the left parameter type- Parameters:
sideEffect- the runnableleftFn- a function mapping E to L- Returns:
Unitas a right value, or leftFn's mapping result as a left value
-
trying
public static Either<java.lang.Throwable,Unit> trying(SideEffect sideEffect)
Attempt to execute theSideEffect, returningUnitin a right value. If the runnable throws exception, wrap it in a left value and return it.- Parameters:
sideEffect- the runnable- Returns:
Unitas a right value, or a left value of the thrown exception
-
left
public static <L,R> Either<L,R> left(L l)
Static factory method for creating a left value.- Type Parameters:
L- the left parameter typeR- the right parameter type- Parameters:
l- the wrapped value- Returns:
- a left value of l
-
right
public static <L,R> Either<L,R> right(R r)
Static factory method for creating a right value.- Type Parameters:
L- the left parameter typeR- the right parameter type- Parameters:
r- the wrapped value- Returns:
- a right value of r
-
-