May be extended by classes, objects, traits, and packages (via package objects).
May be extended by classes, objects, traits, and packages (via package objects).
Within entities that extend this class
objects of type Either will be left-biased, and have
the full-suite of left-biased operations (including operations suitable to for
comprehensions) automatically made available.
Empty Either values will be represented by Right values containing the token
of type R passed to the superclass constructor.
If you are using polymorphic error types, be sure to specify the type
argument to Base, as too narrow a type may be inferred from a token
of a derived type.
In English, this means you should extend Either.LeftBias.Base[Error]( Error.Empty ), not just Either.LeftBias.Base( Error.Empty ).
Note: Entities that do not need to extend another class can extend the abstract class Either.LeftBias.Base, which allows defining the Empty token in the superclass constructor rather than overriding EmptyTokenDefinition.
For more information, please see LeftBias
class Clown extends Either.LeftBias.Base[Clown.Error]( Clown.Error.Empty ) { import Clown.{Cash,Laugh,Error}; // use Either values directly in for comprehensions def perform : Either[Cash,Error] = { for { laugh <- makeFunny money <- begForCash( laugh ) if laugh.loudness > 2 } yield money } def makeFunny : Either[Laugh,Error] = ??? def begForCash( laugh : Laugh ) : Either[Cash,Error] = ??? } object Clown { final object Error { case object Empty extends Error; case object JokeBombed extends Error; case object NoAudience extends Error; case object Cheapskates extends Error; } sealed trait Error; case class Laugh( loudness : Int ); case class Cash( quantity : Int, currencyCode : String ); }
A value class implementing the operations of a left-biased Either,
which throws a java.util.NoSuchElementException if a filter operation
or pattern match results in empty.
A value class implementing the operations of a left-biased Either,
which throws a java.util.NoSuchElementException if a filter operation
or pattern match results in empty.
Typical use
import Either.LeftBias._For documentation of the operations, please see LeftBias.withEmptyToken.Ops
For more, please see LeftBias.
A typeclass instance which implements the operations of a left-biased Either.
A typeclass instance which implements the operations of a left-biased Either.
An unsuccessful filter or pattern match will result in a Right containing a specified empty token of type E.
Typical use
val LeftBias = Either.LeftBias.withEmptyToken(-1); //suitable for Either[A,Int] import LeftBias._
For more, please see LeftBias.
Test two objects for inequality.
Test two objects for inequality.
true if !(this == that), false otherwise.
Equivalent to x.hashCode except for boxed numeric types and null.
Equivalent to x.hashCode except for boxed numeric types and null.
For numerics, it returns a hash value which is consistent
with value equality: if two value type instances compare
as true, then ## will produce the same hash value for each
of them.
For null returns a hashcode where null.hashCode throws a
NullPointerException.
a hash value consistent with ==
The expression x == that is equivalent to if (x eq null) that eq null else x.equals(that).
The expression x == that is equivalent to if (x eq null) that eq null else x.equals(that).
the object to compare against this object for equality.
true if the receiver object is equivalent to the argument; false otherwise.
Cast the receiver object to be of type T0.
Cast the receiver object to be of type T0.
Note that the success of a cast at runtime is modulo Scala's erasure semantics.
Therefore the expression 1.asInstanceOf[String] will throw a ClassCastException at
runtime, while the expression List(1).asInstanceOf[List[String]] will not.
In the latter example, because the type argument is erased as part of compilation it is
not possible to check whether the contents of the list are of the requested type.
the receiver object.
ClassCastException if the receiver object is not an instance of the erasure of type T0.
Create a copy of the receiver object.
Tests whether the argument (arg0) is a reference to the receiver object (this).
Tests whether the argument (arg0) is a reference to the receiver object (this).
The eq method implements an equivalence relation on
non-null instances of AnyRef, and has three additional properties:
x and y of type AnyRef, multiple invocations of
x.eq(y) consistently returns true or consistently returns false.x of type AnyRef, x.eq(null) and null.eq(x) returns false.null.eq(null) returns true. When overriding the equals or hashCode methods, it is important to ensure that their behavior is
consistent with reference equality. Therefore, if two objects are references to each other (o1 eq o2), they
should be equal to each other (o1 == o2) and they should hash to the same value (o1.hashCode == o2.hashCode).
true if the argument is a reference to the receiver object; false otherwise.
The equality method for reference types.
Called by the garbage collector on the receiver object when there are no more references to the object.
Called by the garbage collector on the receiver object when there are no more references to the object.
The details of when and if the finalize method is invoked, as
well as the interaction between finalize and non-local returns
and exceptions, are all platform dependent.
A representation that corresponds to the dynamic class of the receiver object.
A representation that corresponds to the dynamic class of the receiver object.
The nature of the representation is platform dependent.
a representation that corresponds to the dynamic class of the receiver object.
not specified by SLS as a member of AnyRef
The hashCode method for reference types.
Test whether the dynamic type of the receiver object is T0.
Test whether the dynamic type of the receiver object is T0.
Note that the result of the test is modulo Scala's erasure semantics.
Therefore the expression 1.isInstanceOf[String] will return false, while the
expression List(1).isInstanceOf[List[String]] will return true.
In the latter example, because the type argument is erased as part of compilation it is
not possible to check whether the contents of the list are of the specified type.
true if the receiver object is an instance of erasure of type T0; false otherwise.
Equivalent to !(this eq that).
Equivalent to !(this eq that).
true if the argument is not a reference to the receiver object; false otherwise.
Wakes up a single thread that is waiting on the receiver object's monitor.
Wakes up a single thread that is waiting on the receiver object's monitor.
not specified by SLS as a member of AnyRef
Wakes up all threads that are waiting on the receiver object's monitor.
Wakes up all threads that are waiting on the receiver object's monitor.
not specified by SLS as a member of AnyRef
Creates a String representation of this object.
Creates a String representation of this object. The default representation is platform dependent. On the java platform it is the concatenation of the class name, "@", and the object's hashcode in hexadecimal.
a String representation of the object.
A factory for a typeclass instance which implements the operations of a left-biased Either.
A factory for a typeclass instance which implements the operations of a left-biased Either.
An unsuccessful filter or pattern match will result in a Right containing a specified empty token of type E.
Typical use
val LeftBias = Either.LeftBias.withEmptyToken(-1); //suitable for Either[A,Int] import LeftBias._
For more, please see LeftBias.
This object contains utilities for defining an environment in which
Eitherinstances are "left-biased".Left-biased means instances of
Either[A,B]can be operated upon via methods that render thme quite analogous to anOption[A], except that failures are represented by aRightcontaining information about the problem rathar than by uninformativeNone. In particular, a left-biasedEithercan be used directly in a for comprehension. Unlike a LeftProjection, a left-biasedEithersupports all features of a for comprehension, including pattern matching, filtering, and variable assignment.Left-biasing decorates vanilla
Either[A,B]with the following API.For the full documentation, plase see Ops.
To enable left-biasing, you first define a bias, typically via the Either.LeftBias.withEmptyToken factory.
The specified "empty token" will define the value in the
Rightobject that will be used to indicate when a filter or pattern-match of a left-side object fails.If you don't wish to specify an empty token, you may use the more convenient
import Either.LeftBias._However, if you do not specify an empty token, filter operations or pattern match failures that would leave the left-side empty will result in the raising of a
java.util.NoSuchElementException.You may also create a left-biased environment within a trait, class, object, or package by having the entity extend the trait LeftBias or the abstract base class LeftBias.Base.
A Detailed example
Consider a hypothetical process that must read some binary data from a URL, parse the data into a
Record, ensure that record's year is no older than 2011, and then operate upon the data via one of several external services, depending on theopCode, ultimately producing aResult. Things that can go wrong include network errors on loading, parsing problems, failure of the timestamp condition, and failures with the external service.With
Option, one might define a process like:That's fine, but if anything goes wrong, clients will receive a value
None, and have no specific information about what the problem was. Instead of option, we might try to use Either, defining error codes for things that can go wrong. Unconventionally (since we are considering left-biasedEitherhere), we'll let good values arrive asLeftvalues and embed our error codes inRightobjects.Unfortunately, this fails to compile, because scala.util.Either.LeftProjection does not support pattern-matching (used to extract
opCode,data, andyear) or filtering (which we perform based onyear).Instead, we can left-bias the
Either:There is a problem:
Error.Empty, would be the result of the year filter failing, when it should beError.BadYear.The most general and straightforward wat to fix this is to replace empty tokens as they arrive with more informative errors. For this purpose, biased
Eitheroffers a method called LeftBias.Ops.replaceIfEmpty:The scope of the left-bias is the scope of the import. An alternative way to ensure empty tokens yield meaningful information is to define separate biases for separate contexts.