
org.organicdesign.fp.oneOf.package.html Maven / Gradle / Ivy
Show all versions of Paguro Show documentation
This approximates union types for Java - for when something (like a return type) can be
exactly one of a few different things. This is NOT variance or inheritance
(Cars and Trucks are Vehicles), this is one un-related thing or another (a set of things that
are either Trucks, Happiness, or Timestamps).
Java has specifically avoided union types in favor of defining a super-type and making those
other two types extend the new parent. But sometimes you don't have control of the two types to
make them inherit from a common ancestor (like Trucks and Happiness). Sometimes, one hierarchy
makes sense in one context and another hierarchy makes sense in another.
Really, we want to move to a type system where types are sets. ML had this in 1990.
Haskell took it from there. Then Object Oriented programming took the world by storm and types
without Objects waned. In retrospect, we may have missed something.
If you like Paguro and are interested in a new JVM and maybe compile-to-JavaScript language
with Union and Intersection types instead of Object Oriented hierarchies, take a look at the
evolving spec for the
Cymling programming
language. It may need some help to become reality.
This package has Option which has Some() and None() which is useful for indicating "Not-Found"
or "End-of-stream/file". It also has Or which has Good() and Bad() for functional error
handling. A third option is to roll-your own union-type wrappers. Here's an example using
OneOf2:
// You need to subclass a OneOf class with your own class like this:
static class Str_Int extends OneOf2 {
// Constructor
private Str_Int(Object o, int n) { super(o, String.class, Integer.class, n); }
// Static factory methods
// Make sure to use consecutive integers starting from zero
// for the second constructor argument. These ints represent
// indices that select the classes you passed to the call to
// super() above. So String uses index 0:
static Str_Int ofStr(String o) { return new Str_Int(o, 0); }
// Integer uses index 1:
static Str_Int ofInt(Integer o) { return new Str_Int(o, 1); }
}
// Now create a new instance with your constructor
Str_Int oota = Str_Int.ofInt(57);
// Here's how to use your new instance. Notice that this forces you
// to account for all cases of what the union type could contain.
// The return types of the match() function is the same as the return
// type of the lambdas you pass to it (they all have to match). In this
// case, that type is String.
oota.match(str -> "This is a string: " + str,
i -> "This is an integer: " + i));