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
Either
instances 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 aRight
containing information about the problem rathar than by uninformativeNone
. In particular, a left-biasedEither
can be used directly in a for comprehension. Unlike a LeftProjection, a left-biasedEither
supports 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
Right
object 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-biasedEither
here), we'll let good values arrive asLeft
values and embed our error codes inRight
objects.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
Either
offers 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.