javascalautils.Either Maven / Gradle / Ivy
/**
* Copyright 2015 Peter Nerg
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package javascalautils;
import java.util.function.Function;
/**
* Represents a value of one of two possible types.
* Instances of {@link Either} are either an instance of {@link Left} or {@link Right}.
* This is what is called a disjoint union, meaning that the Either will never contain both types only one of them.
* This is the biggest difference from a tuple that would contain both values.
* Examples of creating an {@link Either} of the type {@link Right}.
*
* Either<InputStream, String> either = new Right<>("Right is not Left");
*
* In contrast to {@link Try} and {@link Option} the {@link Either} cannot directly be used as a collection (i.e iterate over it).
* This is due to that {@link Either} is unbiased as to which of {@link Left}, {@link Right} it represents.
* To get access to the data represented by the {@link Either} you as a developer have to decide to work with either the {@link Left} or {@link Right} side.
*
* Consider the {@link Either} ({@link Right}) instance exemplified above.
* To get hold of the data it represents you need to decide which side (Left, Right) to work with.
* Easiest way is to first decide which side the instance represents.
* The methods {@link #isLeft()} and {@link #isRight()} will help you decide which side is represented.
* Invoking either {@link #left()} or {@link #right()} will yield a biased projection for that side.
*
* RightProjection<InputStream, String> projection = either.right();
*
* @author Peter Nerg
* @since 1.1
* @param
* The type for the {@link Left} side
* @param
* The type for the {@link Right} side
*/
public interface Either {
/**
* Returnstrue
if this instance is {@link Right}, else false
.
*
* @return true
if this instance is {@link Right}.
*/
boolean isRight();
/**
* Returnstrue
if this instance is {@link Left}, else false
*
* @return true
if this instance is {@link Left}.
*/
default boolean isLeft() {
return !isRight();
}
/**
* Applies func_left
if this is a {@link Left} or func_right
if this is a {@link Right}
*
* @param
* The type to return from func_left/func_right
* @param func_left
* The function to apply in case this is a {@link Left}
* @param func_right
* The function to apply in case this is a {@link Right}
* @return The result from applying either func_left or func_right
*/
T fold(Function func_left, Function func_right);
/**
* Returns a {@link RightProjection} for this instance.
*
* @return The projection
*/
default RightProjection right() {
return new RightProjection<>(this);
}
/**
* Returns a {@link LeftProjection} for this instance.
*
* @return The projection
*/
default LeftProjection left() {
return new LeftProjection<>(this);
}
/**
* If this is a {@link Left}, then return the left value in {@link Right} or vice versa.
*
* @return The swapped version of this instance
*/
Either swap();
}