I know this is heresy, but I tried to translate the examples from http://www.haskell.org/haskellwiki/Memoization to Java. So far I have:
public abstract class F<A,B> {
public abstract B f(A a);
}
...
public static <A, B> F<A, B> memoize(final F<A, B> fn) {
return new F<A, B>() {
private final Map<A, B> map = new HashMap<A, B>();
public B f(A a) {
B b = map.get(a);
if (b == null) {
b = fn.f(a);
map.put(a, b);
}
return b;
}
};
}
//usage:
private class Cell<X> {
public X value = null;
}
...
final Cell<F<Integer, BigInteger>> fibCell = new Cell<F<Integer, BigInteger>>();
fibCell.value = memoize(new F<Integer, BigInteger>() {
public BigInteger f(Integer a) {
return a <= 1 ? BigInteger.valueOf(a) : fibCell.value.f(a - 1).add(fibCell.value.f(a - 2));
}
});
System.out.println(fibCell.value.f(1000));
That works fine. Now I tried to implement the memoFix combinator defined as
memoFix :: ((a -> b) -> (a -> b)) -> a -> b
memoFix f =
let mf = memoize (f mf) in mf
But I got stuck. Does this even make sense in Java, especially concerning its inherent lack of lazyness?
The Guava library actually implements something similar with its MapMaker:
final Map<Integer, String> memoizingMap = new MapMaker().makeComputingMap(
new Function<Integer, String>() {
#Override
public String apply(final Integer input) {
System.out.println("Calculating ...");
return Integer.toHexString(input.intValue());
}
});
System.out.println(memoizingMap.get(1));
System.out.println(memoizingMap.get(100));
System.out.println(memoizingMap.get(100000));
System.out.println("The following should not calculate:");
System.out.println(memoizingMap.get(1));
Output:
Calculating ...
1
Calculating ...
64
Calculating ...
186a0
The following should not calculate:
1
The nice thing is that you can fine-tune the generated map for different aspects as expiration, concurrency level etc.
Okay, this has convinced me that functional programming is ususally a bad idea with Java. Lack of laziness can be worked around using a reference object (which essentially implements laziness). Here's a solution:
public static class FunctionRef<A, B> {
private F<A, B> func;
public void set(F<A, B> f) { func = f; }
public F<A, B> get() { return func; }
}
public static class Pair<A, B> {
public final A first; public final B second;
public Pair(A a, B b) {
this.first = a; this.second = b;
}
}
public static <A, B> F<A, B> memoFix(final F<Pair<FunctionRef<A, B>, A>, B> func) {
final FunctionRef<A, B> y = new FunctionRef<A, B>();
y.set(
memoize(new F<A, B>() {
#Override
public B f(A a) {
return func.f(new Pair<FunctionRef<A, B>, A>(y, a));
}
})
);
return y.get();
}
//Test that it works
public static void main(String[] args) {
F<Pair<FunctionRef<Integer, Integer>,Integer>, Integer> fib = new F<Pair<FunctionRef<Integer, Integer>,Integer>, Integer>() {
#Override
public Integer f(Pair<FunctionRef<Integer, Integer>, Integer> a) {
int value = a.second;
System.out.println("computing fib of " + value);
if (value == 0) return 0;
if (value == 1) return 1;
return a.first.get().f(value - 2) + a.first.get().f(value - 1);
}
};
F<Integer, Integer> memoized = memoFix(fib);
System.out.println(memoized.f(10));
}
Note that when the program is run, it only outputs "computing fib of" once for each value!
The memoFix solution by Joe K was really impressive :-)
For practical purposes, this seems to be the most elegant solution for recursive (and non-recursive) functions, as it avoids the need for some reference variable:
import java.util.HashMap;
import java.util.Map;
public abstract class MemoF<A,B> extends F<A,B> {
private final Map<A, B> map = new HashMap<A, B>();
#Override
public B f(A a) {
B b = map.get(a);
if (b == null) {
b = func(a);
map.put(a, b);
}
return b;
}
public abstract B func(A a);
}
Now you have to implement func as usual, except that you never call it recursively, but call f instead:
F<Integer, BigInteger> memoFib = new MemoF<Integer, BigInteger>(){
public BigInteger func(Integer a) {
return a <= 1 ? BigInteger.valueOf(a) : f(a - 1).add(f(a - 2));
}
};
System.out.println(memoFib.f(100));
//--> 354224848179261915075
Why are you stuck? It looks like you're done.
You've successfully memoized calls to a function using a Map.
Here is a snippet from my recent solution for the exact same problem:
private final static class MutableFunction<A, B> implements Function<A, B> {
public Function<A, B> f;
#Override
public B apply(A argument) {
return f.apply(argument);
}
}
/**
* Computes the fixed point of function f.
* Only terminates successfully if f is non-strict (that is returns without calling its argument).
*/
public static <A, B, R extends Function<A,B>> R fix(final Function<? super Function<A, B>, ? extends R> f) {
MutableFunction<A, B> mutable = new MutableFunction<A, B>();
R result = f.apply(mutable);
mutable.f = result;
return result;
}
Memofix of f is just a fix(composition(memo, f)) then!
Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 1 year ago.
Improve this question
I have a class like below.
public class Fig implements SomeThing {
private BiPredicate<List<A>, B> predicate;
private BiPredicate<Set<X>, Y> otherpredicate;
private SomeThing something;
private SomeThing somethingElse;
public Fig(BiPredicate<List<A>, B> p, SomeThing something, SomeThing somethingElse) {
this.predicate = p;
this.something = something;
this.somethingElse = somethingElse;
}
public Fig(BiPredicate<Set<X>, Y> p, SomeThing something, SomeThing somethingElse) {
this.otherpredicate = p;
this.something = something;
this.somethingElse = somethingElse;
}
#Override
public List<String> apply(List<A> a, B b) {
if (predicate.test(a, b))
return something.call(a, b);
else
return somethingElse.call(a, b);
}
#Override
public List<String> applyAnother(Set<X> a, Y b) {
if (otherpredicate.test(a, b))
return something.call(a, b);
else
return somethingElse.call(a, b);
}
}
It seems one of the predicate would have null value. And it doesn't seem correct me.
In other places I would create concrete instance of Fig and call the apply methods depending on the parameters. How to refractor this sort of code?
None of the alphabets are generic and are just representation for concrete classes.
You only set one predicate by your constructors in each case, the other is not set.
You have to set both predicates within each constructor because you will use only one constructor to create your instance.
It is not a problem of java but of your implementation. I would use Collection (extended by List and Set) or create two Classes.
public class Fig implements SomeThing {
private BiPredicate<Collection<A>, B> predicate;
private SomeThing something;
private SomeThing somethingElse;
public Fig(BiPredicate<Collection<A>, B> p, SomeThing something, SomeThing somethingElse) {
this.predicate = p;
this.something = something;
this.somethingElse = somethingElse;
}
#Override
public Collection<String> apply(Collection<A> a, B b) {
if (predicate.test(a, b))
return something.call(a, b);
else
return somethingElse.call(a, b);
}
}
Or
public class FigList implements SomeThing {
private BiPredicate<List<A>, B> predicate;
private SomeThing something;
private SomeThing somethingElse;
public Fig(BiPredicate<List<A>, B> p, SomeThing something, SomeThing somethingElse) {
this.predicate = p;
this.something = something;
this.somethingElse = somethingElse;
}
#Override
public List<String> apply(List<A> a, B b) {
if (predicate.test(a, b))
return something.call(a, b);
else
return somethingElse.call(a, b);
}
}
public class FigSet implements SomeThing {
private BiPredicate<Set<A>, B> predicate;
private SomeThing something;
private SomeThing somethingElse;
public Fig(BiPredicate<Set<A>, B> p, SomeThing something, SomeThing somethingElse) {
this.predicate = p;
this.something = something;
this.somethingElse = somethingElse;
}
#Override
public List<String> apply(Set<A> a, B b) {
if (predicate.test(a, b))
return something.call(a, b);
else
return somethingElse.call(a, b);
}
}
ADDED
Using both predicates within same class
public class Fig implements SomeThing {
private BiPredicate<List<A>, B> predicate;
private BiPredicate<Set<X>, Y> otherpredicate;
private SomeThing something;
private SomeThing somethingElse;
public Fig(BiPredicate<List<A>, B> p1, BiPredicate<Set<X>, Y> p2, SomeThing something, SomeThing somethingElse) {
predicate = p1;
otherpredicate = p2;
this.something = something;
this.somethingElse = somethingElse;
}
#Override
public List<String> apply(List<A> a, B b) {
if (predicate.test(a, b)) {
return something.call(a, b);
} else {
return somethingElse.call(a, b);
}
}
#Override
public List<String> applyAnother(Set<X> a, Y b) {
if (otherpredicate.test(a, b)) {
return something.call(a, b);
} else {
return somethingElse.call(a, b);
}
}
#Override
public List<String> call(List<A> pA, B pB) {
// TODO Auto-generated method stub
return null;
}
#Override
public List<String> call(Set<X> pA, Y pB) {
// TODO Auto-generated method stub
return null;
}
}
I assume the arguments of type Something are related to each other. So it would be nice to pack them together:
class SomeThings {
private SomeThing something;
private SomeThing somethingElse;
public SomeThings(SomeThing someThing, SomeThing someThingElse) {
this.something = someThing;
this.somethingElse = someThingElse;
}
public SomeThing get() {
return something;
}
public SomeThing getElse() {
return somethingElse;
}
}
If you want to use one class (if you use many containers like List, Stack, Map and don't want to write a class for each one) you could use generics:
class Fig1<S, T extends Collection<? extends Object>> implements SomeThing {
private BiPredicate<T, S> predicate;
private SomeThings somethings;
public Fig1(BiPredicate<T, S> p, SomeThings someThings) {
this.predicate = p;
this.somethings = someThings;
}
public void setPredicate(BiPredicate<T, S> predicate) {
this.predicate = predicate;
}
public BiPredicate<T, S> getPredicate() {
return predicate;
}
public SomeThings getSomethings() {
return somethings;
}
#Override
public List<String> apply(T a, S b) {
if (getPredicate().test(a, b))
return somethings.get().call(a, b);
else
return somethings.getElse().call(a, b);
}
}
Usage:
SomeThings someThings = new SomeThings(new SomeThing(), new SomeThing());
BiPredicate<List<String>, Integer> p1 = (strings, integer) -> false;
BiPredicate<Stack<String>, Integer> p2 = (strings, integer) -> false;
Fig1<Integer, List<String>> fList = new Fig1<>(p1, someThings);
Fig1<Integer, Stack<String>> fStack = new Fig1<>(p2, someThings);
However, if you want to use only two containers just write two classes like #Michael Katt described. It's cleaner.
I'm trying to understand how Either is implemented. I've gotten stuck at chaining together multiple functions in a way that allows returning a different Left value during flatMap. I can't work out how it is possible within the type system.
Minimal Either example code:
public class Either<A,B> {
public final A left;
public final B right;
private Either(A a, B b) {
left = a;
right = b;
}
public static <A, B> Either<A, B> left(A a) {
return new Either<>(a, null);
}
public static <A, B> Either<A, B> right(B b) {
return new Either<>(null, b);
}
public <C> Either<A, C> flatMap(Function<B, Either<A,C>> f) {
if (this.isRight()) return f.apply(this.right);
else return Either.left(this.left);
}
// map and other useful functions....
I originally thought I'd be able to map to different Left values, which would allow returning the relevant error at each point.
So, for instance, given these functions:
public static Either<Foo, String> doThing() {
return Either.right("foo");
}
public static Either<Bar, String> doThing2(String text) {
return (text.equals("foo"))
? Either.right("Yay!")
: Either.left(new Bar("Grr..."));
}
public static Either<Baz, String> doThing3() {
return (text.equals("Yay!"))
? Either.right("Hooray!")
: Either.left(new Baz("Oh no!!"));
}
I thought I'd be able to do
doThing().flatMap(x -> doThing2()).flatMap(y -> doThing3())
However, the compiler flags this as impossible.
After some studying of the code, I realized that it's due to my <A,B> generic parameters.
flatMap has two different cases:
the case where we map the right side
the case where we pass through the left value
So, if my goal is to enable sometimes returning different Left values from flatMap, then my two generic variables <A,B> don't work, because if case 1 executes and my function changes A, then case 2 is invalid, because A != A'. The act of applying a function to the right side may have changed the Left side to a different type.
All this leads me to these questions:
Is my expectation for the behavior of the Either type incorrect?
Is it possible to return different Left types during a flatMap operation?
if so, how do you get the types to work out?
There isn't a sensible flatMap() function like you want, due to parametricity. Consider:
Either<Foo, String> e1 = Either.left(new Foo());
Either<Bar, String> e2 = foo.flatMap(x -> doThing2());
Bar bar = e2.left; // Where did this come from???
flatMap() itself would have had to invent a Bar instance somehow. If you start writing a flatMap() that can change both types, you'll see the issue more clearly:
public <C, D> Either<C, D> flatMap(Function<B, Either<C, D>> f) {
if (this.isRight()) {
return f.apply(this.right);
} else {
// Error: can't convert A to C
return Either.left(this.left);
}
}
You can, but your old Left has to be a subtype of or equal to the new Left, so it can be cast up. I'm not very familiar with Java's syntax, but the Scala implementation looks like:
def flatMap[A1 >: A, B1](f: B => Either[A1, B1]): Either[A1, B1] = this match {
case Right(b) => f(b)
case _ => this.asInstanceOf[Either[A1, B1]]
}
Here the A1 >: A designates A as a subtype of A1. I know Java has an <A extends A1> syntax, but I'm not sure it can be used to describe the constraint on A1, as we need in this case.
Regarding your usage of Either (doThing(...)) it seems your flat mapping isn't sufficient. I assume you want your flat mapping work like for Optional<T>.
The mapper ofOptional.flatMap takes a value of kind of T and returns an Optional<U> where U is a generic type parameter of this method. But Optional has one generic type parameter T whereas Either has two: A and B. So if you want to flat map an Either<A,B> either it isn't sufficient to use one mapping.
One mapping what should it map? "The value which isn't null" you would say - wouldn't you? Ok but you know that first at runtime. Your flatMap method is defined at compile time. Therefore you have to provide a mapping for each case.
You choose <C> Either<A, C> flatMap(Function<B, Either<A, C>> f). This mapping uses a value of type B as input. That means if the mapped Either either is !either.isRight() all following mappings would return an Either.left(a) where a is the value of the very first Either.left(a). So actually only an Either either where either.isRight() could be mapped to another value. And it has to be either.isRight() from the beginning. This means also that once an Either<A,B> either is created all flat mappings will result in a kind of Either<A,?>. So the current flatMap restricts an Either either to keep its left generic type. Is this what you supposed to do?
If you want to flat map an Either either without restrictions you need mappings for both cases: either.isRight() and !either.isRight(). This will allow you to continue the flat mapping in both directions.
I did it this way:
public class Either<A, B> {
public final A left;
public final B right;
private Either(A a, B b) {
left = a;
right = b;
}
public boolean isRight() {
return right != null;
}
#Override
public String toString() {
return isRight() ?
right.toString() :
left.toString();
}
public static <A, B> Either<A, B> left(A a) {
return new Either<>(a, null);
}
public static <A, B> Either<A, B> right(B b) {
return new Either<>(null, b);
}
public <C, D> Either<C, D> flatMap(Function<A, Either<C, D>> toLeft, Function<B, Either<C, D>> toRight) {
if (this.isRight()) {
return toRight.apply(this.right);
} else {
return toLeft.apply(this.left);
}
}
public static void main(String[] args) {
Either<String, String> left = Either.left(new Foo("left"))
.flatMap(l -> Either.right(new Bar(l.toString() + ".right")), r -> Either.left(new Baz(r.toString() + ".left")))
.flatMap(l -> Either.left(l.toString() + ".left"), r -> Either.right(r.toString() + ".right"));
System.out.println(left); // left.right.right
Either<String, String> right = Either.right(new Foo("right"))
.flatMap(l -> Either.right(new Bar(l.toString() + ".right")), r -> Either.left(new Baz(r.toString() + ".left")))
.flatMap(l -> Either.left(l.toString() + ".left"), r -> Either.right(r.toString() + ".right"))
.flatMap(l -> Either.right(l.toString() + ".right"), r -> Either.left(r.toString() + ".left"));
System.out.println(right); // right.left.left.right
}
private static class Foo {
private String s;
public Foo(String s) {
this.s = s;
}
#Override
public String toString() {
return s;
}
}
private static class Bar {
private String s;
public Bar(String s) {
this.s = s;
}
#Override
public String toString() {
return s;
}
}
private static class Baz {
private String s;
public Baz(String s) {
this.s = s;
}
#Override
public String toString() {
return s;
}
}
}
Answering your question: Yes it is possible to construct an Either returning a different left value. But I think your intent was to know how to get a proper working Either.
I have been learning how to do composition of lambda expressions using the andThen and compose functions, for example:
Function<SceneObject> transform = scaleX2.andThen(scaleY2).andThen(rotateZ45);
Is there a way to remove one of the steps in the resulting function?
So, in the above example transform.decompose(scaleY2) would result in transform = scaleX2.andThen(rotateZ45).
Not with that code. Function.andThen is implemented by constructing a lambda expression, which completely hides the details of the two functions used to construct it.
An alternative approach would be to use your own type, say Transform<T, R> which can wrap the equivalent function, and can then support a decompose operation.
import java.util.Optional;
#FunctionalInterface
public interface Transform<T, R> {
class AndThen<T, R, S> implements Transform<T, S> {
final Transform<T, R> first;
final Transform<R, S> second;
AndThen(Transform<T, R> first, Transform<R, S> second) {
this.first = first;
this.second = second;
}
#Override
public S apply(T t) {
return second.apply(first.apply(t));
}
#Override
public <U> Optional<Transform<T, U>> decomposeFst() {
return Optional.of((Transform<T, U>)first);
}
#Override
public <U> Optional<Transform<U, S>> decomposeSnd() {
return Optional.of((Transform<U, S>)second);
}
}
default <S> Transform<T, S> andThen(Transform<R, S> next) {
return new AndThen<T, R, S>(this, next);
}
R apply(T t);
default <S> Optional<Transform<T, S>> decomposeFst() {
return Optional.empty();
}
default <S> Optional<Transform<S, R>> decomposeSnd() {
return Optional.empty();
}
static void main(String[] args) {
final Transform<Double, String> f = Object::toString;
final Transform<String, Integer> g = String::length;
final Transform<Double, Integer> h = f.andThen(g);
final int i = h.apply(1.234);
final Optional<Transform<Double, String>> f2 = h.<String>decomposeFst();
final Optional<Transform<String, Integer>> g2 = h.<String>decomposeSnd();
final String s = f2.get().apply(1.234);
final int j = g2.get().apply(s);
System.out.println(s + " : " + j);
}
}
I ask for something which I see impossible and I'll delete question if it is.
I have got method:
public Object convertBy(Function... functions) {
}
and those functions are :
interface FLines extends Function {
#Override
default Object apply(Object t) {
return null;
};
public List<String> getLines(String fileName);
}
interface Join extends Function {
#Override
default Object apply(Object t) {
return null;
};
public String join(List<String> lines);//lines to join
}
interface CollectInts extends Function {
#Override
default Object apply(Object t) {
return null;
};
public List<Integer> collectInts(String s);
}
interface Sum<T, R> extends Function<T, R> {
#Override
default Object apply(Object t) {
return null;
};
public R sum(T list);//list of Integers
}
Abstract methods in those interfaces return values of different types. I pass lambdas to my convertBy method.
I would like to set convertBy return type the same as return type of functions[functions.length - 1].
Is this is possible?
EDIT:
I've changed the signature of the method and the signature of the methods inside the interface. It works but only if I do cast in the marked places in the main posted below. The weird things it needs cast only in 3 out of 4 method's invocations, I would like to get rid of casts at all in the main.
import java.util.List;
import java.util.function.Function;
public class InputConverter<T> {
private T value;
public InputConverter(T value) {
this.value = value;
}
public <T, R> R convertBy(Function<T, R> special, Function... functions) {
if (functions.length == 0) {
FLines flines = (FLines) special;
return (R) flines.getLines((value instanceof String) ? (String) value : null);
} else if (functions.length == 1) {
FLines flines = (FLines) functions[0];
Join join = (Join) special;
return (R) join.join(flines.getLines((String) value));
} else if (functions.length == 2) {
if (functions[0] instanceof FLines) {
FLines flines = (FLines) functions[0];
Join join = (Join) functions[1];
CollectInts collectInts = (CollectInts) special;
return (R) collectInts.collectInts(join.join(flines.getLines((String) value)));
} else {
Join join = (Join) functions[0];
CollectInts collectInts = (CollectInts) functions[1];
Sum sum = (Sum) special;
return (R) sum.sum(collectInts.collectInts(join.join((List<String>) value)));
}
} else {
FLines flines = (FLines) functions[0];
Join join = (Join) functions[1];
CollectInts collectInts = (CollectInts) functions[2];
Sum sum = (Sum) special;
return (R) sum.sum(collectInts.collectInts(join.join(flines.getLines((String) value))));
}
}
/* public Integer convertBy(Join join, CollectInts collectInts, Sum sum) {
return sum.sum(collectInts.collectInts(join.join((List<String>) value)));
}*/
}
interface FLines<T, R> extends Function {
#Override
default Object apply(Object t) {
return null;
};
public R getLines(T fileName);
// public List<String> getLines(String fileName);
}
interface Join<T,R> extends Function {
#Override
default Object apply(Object t) {
return null;
};
public R join(T lines);//lines to join
// public String join(List<String> lines);//lines to join
}
interface CollectInts<T, R> extends Function {
#Override
default Object apply(Object t) {
return null;
};
public R collectInts(T t);
// public List<Integer> collectInts(String s);
}
interface Sum<T, R> extends Function<T, R> {
#Override
default Object apply(Object t) {
return null;
};
public R sum(T list);//list of Integers
}
The main method:
FLines<String, List<String>> flines ....
Join<List<String>, String> join ...
CollectInts<String, List<Integer>> collectInts ...
Sum<List<Integer>, Integer> sum ...
String fname =/* System.getProperty("user.home") + "/*/ "LamComFile.txt";
InputConverter<String> fileConv = new InputConverter<>(fname);
List<String> lines = fileConv.convertBy(flines);//cannot cast from Object to List<String>
String text = fileConv.convertBy( join, flines);//cannot cast from Object to String
List<Integer> ints = fileConv.convertBy(collectInts,flines, join);//cannot cast from Object to List<Integer>
Integer sumints = fileConv.convertBy(sum, flines, join, collectInts);//works without cast!
I don't understand why compiler understands what sum returns but don't infer what for instance collectInts returns.
It seems, you have some misunderstanding about generic type hierarchies. When you want to extend a generic type, you have to make a fundamental decision about the actual types of the extended class or interface. You may specify exact types like in
interface StringTransformer extends Function<String,String> {}
(here we create a type that extends a generic type but is not generic itself)
or you can create a generic type which uses its own type parameter for specifying the actual type argument of the super class:
interface NumberFunc<N extends Number> extends Function<N,N> {}
Note, how we create a new type parameter N with its own constraints and use it to parametrize the superclass to require its type parameters to match ours.
In contrast, when you declare a class like
interface FLines<T, R> extends Function
you are extending the raw type Function and create new type parameters <T, R> which are entirely useless in your scenario.
To stay at the above examples, you may implement them as
StringTransformer reverse = s -> new StringBuilder(s).reverse().toString();
NumberFunc<Integer> dbl = i -> i*2;
and since they inherit properly typed methods, you may use these to combine the functions:
Function<String,Integer> f = reverse.andThen(Integer::valueOf).andThen(dbl);
System.out.println(f.apply("1234"));
Applying this to your scenario, you could define the interfaces like
interface FLines extends Function<String,List<String>> {
#Override default List<String> apply(String fileName) {
return getLines(fileName);
}
public List<String> getLines(String fileName);
}
interface Join extends Function<List<String>,String> {
#Override default String apply(List<String> lines) {
return join(lines);
}
public String join(List<String> lines);
}
interface CollectInts extends Function<String,List<Integer>> {
#Override default List<Integer> apply(String s) {
return collectInts(s);
}
public List<Integer> collectInts(String s);
}
interface Sum extends Function<List<Integer>, Integer> {
#Override default Integer apply(List<Integer> list) {
return sum(list);
}
public Integer sum(List<Integer> list);
}
and redesign your InputConverter to accept only one function which may be a combined function:
public class InputConverter<T> {
private T value;
public InputConverter(T value) {
this.value = value;
}
public <R> R convertBy(Function<? super T, ? extends R> f) {
return f.apply(value);
}
}
This can be used in a type safe manner:
FLines flines = name -> {
try { return Files.readAllLines(Paths.get(name)); }
catch(IOException ex) { throw new UncheckedIOException(ex); }
};
Join join = list -> String.join(",", list);
CollectInts collectInts=
s -> Arrays.stream(s.split(",")).map(Integer::parseInt).collect(Collectors.toList());
Sum sum = l -> l.stream().reduce(0, Integer::sum);
InputConverter<String> fileConv = new InputConverter<>("LamComFile.txt");
List<String> lines = fileConv.convertBy(flines);
String text = fileConv.convertBy(flines.andThen(join));
List<Integer> ints = fileConv.convertBy(flines.andThen(join).andThen(collectInts));
Integer sumints = fileConv.convertBy(
flines.andThen(join).andThen(collectInts).andThen(sum)
);
You have to change the method signature and inline the last vararg value as a separate parameter.
If you have this parameter as the last one, then you won't be able a use vararg parameter, as it has always to be last one and must be represented as an array in case it's not the last one:
public <T, R> R convertBy(Function[] functions, Function<T, R> special) { }
If you, however, insist to use varargs, then you can move the "special" Function as first parameter:
public <T, R> R convertBy(Function<T, R> special, Function... functions) { }
Thank all of you who elaborated on the subject, your solutions are much better in real world.
As the author I would like to post my solution that enabled not changing the invocations of convertBy() int the main() one bit. It is very short and ugly, but works.
Main:
Function<String, List<String>> flines ... lambda here
Function<List<String>, String> join ... lambda here
Function<String, List<Integer>> collectInts ... lambda here
Function<List<Integer>, Integer> sum ... lambda here
String fname = System.getProperty("user.home") + "/LamComFile.txt";
InputConverter<String> fileConv = new InputConverter<>(fname);
List<String> lines = fileConv.convertBy(flines);
String text = fileConv.convertBy(flines, join);
List<Integer> ints = fileConv.convertBy(flines, join, collectInts);
Integer sumints = fileConv.convertBy(flines, join, collectInts, sum);
System.out.println(lines);
System.out.println(text);
System.out.println(ints);
System.out.println(sumints);
List<String> arglist = Arrays.asList(args);
InputConverter<List<String>> slistConv = new InputConverter<>(arglist);
sumints = slistConv.convertBy(join, collectInts, sum);
System.out.println(sumints);
The InputConverter class:
public class InputConverter<T> {
private T value;
public InputConverter(T value) {
this.value = value;
}
public <T, R> R convertBy(Function... functions) {
Object result = value;
for (int i = 0; i < functions.length; i++) {
result = functions[i].apply(result);
}
return (R) result;
}
}
How can I write a typesafe Java method that returns either something of class a or something of class b? For example:
public ... either(boolean b) {
if (b) {
return new Integer(1);
} else {
return new String("hi");
}
}
What is the cleanest way?
( The only thing that comes to my mind is using exceptions which is obviously bad, as it is abusing a error-handling mechanism for a general language feature ...
public String either(boolean b) throws IntException {
if (b) {
return new String("test");
} else {
throw new IntException(new Integer(1));
}
}
)
My general formula for simulating algebraic data types is:
The type is an abstract base class, and the constructors are subclasses of that
The data for each constructor are defined in each subclass. (This allows constructors with different numbers of data to work correctly. It also removes the need to maintain invariants like only one variable is non-null or stuff like that).
The constructors of the subclasses serve to construct the value for each constructor.
To deconstruct it, one uses instanceof to check the constructor, and downcast to the appropriate type to get the data.
So for Either a b, it would be something like this:
abstract class Either<A, B> { }
class Left<A, B> extends Either<A, B> {
public A left_value;
public Left(A a) { left_value = a; }
}
class Right<A, B> extends Either<A, B> {
public B right_value;
public Right(B b) { right_value = b; }
}
// to construct it
Either<A, B> foo = new Left<A, B>(some_A_value);
Either<A, B> bar = new Right<A, B>(some_B_value);
// to deconstruct it
if (foo instanceof Left) {
Left<A, B> foo_left = (Left<A, B>)foo;
// do stuff with foo_left.a
} else if (foo instanceof Right) {
Right<A, B> foo_right = (Right<A, B>)foo;
// do stuff with foo_right.b
}
Here is a statically checked type-safe solution; this means you cannot create runtime errors. Please read the previous sentence in the way it is meant. Yes, you can provoke exceptions in some way or the other...
It's pretty verbose, but hey, it's Java!
public class Either<A,B> {
interface Function<T> {
public void apply(T x);
}
private A left = null;
private B right = null;
private Either(A a,B b) {
left = a;
right = b;
}
public static <A,B> Either<A,B> left(A a) {
return new Either<A,B>(a,null);
}
public static <A,B> Either<A,B> right(B b) {
return new Either<A,B>(null,b);
}
/* Here's the important part: */
public void fold(Function<A> ifLeft, Function<B> ifRight) {
if(right == null)
ifLeft.apply(left);
else
ifRight.apply(right);
}
public static void main(String[] args) {
Either<String,Integer> e1 = Either.left("foo");
e1.fold(
new Function<String>() {
public void apply(String x) {
System.out.println(x);
}
},
new Function<Integer>() {
public void apply(Integer x) {
System.out.println("Integer: " + x);
}
});
}
}
You might want to look at Functional Java and Tony Morris' blog.
Here is the link to the implementation of Either in Functional Java. The fold in my example is called either there. They have a more sophisticated version of fold, that is able to return a value (which seems appropriate for functional programming style).
You can have a close correspondence with Haskell by writing a generic class Either, parametric on two types L and R with two constructors (one taking in an L, and one taking in an R) and two methods L getLeft() and R getRight() such that they either return the value passed when constructing, or throw an exception.
The suggestions already provided, although feasible, are not complete as they rely on some null references and effectively make "Either" masquerade as a tuple of values. A disjoint sum is obviously one type or the other.
I'd suggest having a look at the implementation of FunctionalJava's Either as an example.
The big thing is not to try to write in one language whilst writing in another. Generally in Java you want to put the behaviour in the object, rather than having a "script" running outside with encapsulation destroyed by get methods. There is no context for making that kind of suggestion here.
One safe way of dealing with this particular little fragment is to write it as a callback. Similar to a very simple visitor.
public interface Either {
void string(String value);
void integer(int value);
}
public void either(Either handler, boolean b) throws IntException {
if (b) {
handler.string("test");
} else {
handler.integer(new Integer(1));
}
}
You may well want to implement with pure functions and return a value to the calling context.
public interface Either<R> {
R string(String value);
R integer(int value);
}
public <R> R either(Either<? extends R> handler, boolean b) throws IntException {
return b ?
handler.string("test") :
handler.integer(new Integer(1));
}
(Use Void (capital 'V') if you want to get back to being uninterested in the return value.)
I've implemented it in a Scala-like fashion in the following way. It's a little verbose (it is Java, after all :)) but it's type safe.
public interface Choice {
public enum Type {
LEFT, RIGHT
}
public Type getType();
interface Get<T> {
T value();
}
}
public abstract class Either<A, B> implements Choice {
private static class Base<A, B> extends Either<A, B> {
#Override
public Left leftValue() {
throw new UnsupportedOperationException();
}
#Override
public Right rightValue() {
throw new UnsupportedOperationException();
}
#Override
public Type getType() {
throw new UnsupportedOperationException();
}
}
public abstract Left leftValue();
public abstract Right rightValue();
public static <A, B> Either<A, B> left(A value) {
return new Base<A, B>().new Left(value);
}
public static <A, B> Either<A, B> right(B value) {
return new Base<A, B>().new Right(value);
}
public class Left extends Either<A, B> implements Get<A> {
private A value;
public Left(A value) {
this.value = value;
}
#Override
public Type getType() {
return Type.LEFT;
}
#Override
public Left leftValue() {
return Left.this;
}
#Override
public Right rightValue() {
return null;
}
#Override
public A value() {
return value;
}
}
public class Right extends Either<A, B> implements Get<B> {
private B value;
public Right(B value) {
this.value = value;
}
#Override
public Left leftValue() {
return null;
}
#Override
public Right rightValue() {
return this;
}
#Override
public Type getType() {
return Type.RIGHT;
}
#Override
public B value() {
return value;
}
}
}
Then you can pass Either<A,B> instances around on your code. The Type enum is mainly used on switch statements.
Creating Either values is simple as:
Either<A, B> underTest;
A value = new A();
underTest = Either.left(value);
assertEquals(Choice.Type.LEFT, underTest.getType());
assertSame(underTest, underTest.leftValue());
assertNull(underTest.rightValue());
assertSame(value, underTest.leftValue().value());
Or, in the typical situation where it is used instead of exceptions,
public <Error, Result> Either<Error,Result> doSomething() {
// pseudo code
if (ok) {
Result value = ...
return Either.right(value);
} else {
Error errorMsg = ...
return Either.left(errorMsg);
}
}
// somewhere in the code...
Either<Err, Res> result = doSomething();
switch(result.getType()) {
case Choice.Type.LEFT:
// Handle error
Err errorValue = result.leftValue().value();
break;
case Choice.Type.RIGHT:
// Process result
Res resultValue = result.rightValue().value();
break;
}
Hope it helps.
From http://blog.tmorris.net/posts/maybe-in-java/ I learned that you can make the outer class's constructor private so only nested classes can subclass it. This trick is just as type safe as the best above, but much less verbose, works for any ADT you want like Scala's case class.
public abstract class Either<A, B> {
private Either() { } // makes this a safe ADT
public abstract boolean isRight();
public final static class Left<L, R> extends Either<L, R> {
public final L left_value;
public Left(L l) { left_value = l; }
public boolean isRight() { return false; }
}
public final static class Right<L, R> extends Either<L, R> {
public final R right_value;
public Right(R r) { right_value = r; }
public boolean isRight() { return true; }
}
}
(started from top answer's code and style)
Note that:
The finals on the subclass are optional. Without them you can subtype Left and Right, but still not Either directly. Thus without the finals Either has limited width but unbounded depth.
With ADTs like this, I see no reason to jump on the whole anti-instanceof bandwagon. A boolean works for Maybe or Either, but in general instanceof is your best and only option.
Thanks to Derive4J algebraic data types are now very easy in Java. All you have to do is create the following class:
import java.util.function.Function;
#Data
public abstract class Either<A, B> {
Either(){}
/**
* The catamorphism for either. Folds over this either breaking into left or right.
*
* #param left The function to call if this is left.
* #param right The function to call if this is right.
* #return The reduced value.
*/
public abstract <X> X either(Function<A, X> left, Function<B, X> right);
}
And Derive4J will take care of creating constructors for the left and rights cases, as well as a pattern matching syntax alla Haskell, mapper methods for each sides, and more.
There is a stand-alone implementation of Either for Java 8 in a small library, "ambivalence": http://github.com/poetix/ambivalence
It is closest to the Scala standard implementation - for example, it provides left and right projections for map and hashMap operations.
There is no direct access to the left or right values; rather, you join the two types by providing lambdas to map them into a single result type:
Either<String, Integer> either1 = Either.ofLeft("foo");
Either<String, Integer> either2 = Either.ofRight(23);
String result1 = either1.join(String::toUpperCase, Object::toString);
String result2 = either2.join(String::toUpperCase, Object::toString);
You can get it from Maven central:
<dependency>
<groupId>com.codepoetics</groupId>
<artifactId>ambivalence</artifactId>
<version>0.2</version>
</dependency>
You don't need to settle with the instanceof checks or redundant fields. Surprisingly enough, Java's type system provides enough features to simulate the sum types cleanly.
Background
First of all, do you know that any data type can be encoded with just functions? It's called Church encoding. E.g., using the Haskell signature, the Either type could be defined as follows:
type Either left right =
forall output. (left -> output) -> (right -> output) -> output
You can interpret it as "given a function on the left value and a function on the right value, produce the result of either of them".
Definition
Expanding on this idea, in Java we can define an interface called Matcher, which includes both functions and then define the Sum type in terms of how to pattern-match on it. Here's the complete code:
/**
* A sum class which is defined by how to pattern-match on it.
*/
public interface Sum2<case1, case2> {
<output> output match(Matcher<case1, case2, output> matcher);
/**
* A pattern-matcher for 2 cases.
*/
interface Matcher<case1, case2, output> {
output match1(case1 value);
output match2(case2 value);
}
final class Case1<case1, case2> implements Sum2<case1, case2> {
public final case1 value;
public Case1(case1 value) {
this.value = value;
}
public <output> output match(Matcher<case1, case2, output> matcher) {
return matcher.match1(value);
}
}
final class Case2<case1, case2> implements Sum2<case1, case2> {
public final case2 value;
public Case2(case2 value) {
this.value = value;
}
public <output> output match(Matcher<case1, case2, output> matcher) {
return matcher.match2(value);
}
}
}
Usage
And then you can use it like this:
import junit.framework.TestCase;
public class Test extends TestCase {
public void testSum2() {
assertEquals("Case1(3)", longOrDoubleToString(new Sum2.Case1<>(3L)));
assertEquals("Case2(7.1)", longOrDoubleToString(new Sum2.Case2<>(7.1D)));
}
private String longOrDoubleToString(Sum2<Long, Double> longOrDouble) {
return longOrDouble.match(new Sum2.Matcher<Long, Double, String>() {
public String match1(Long value) {
return "Case1(" + value.toString() + ")";
}
public String match2(Double value) {
return "Case2(" + value.toString() + ")";
}
});
}
}
With this approach you can even find a direct resemblance of pattern-matching in such languages as Haskell and Scala.
Library
This code is distributed as part of my library of composite types (Sums and Products, aka Unions and Tuples) of multiple arities. It's on GitHub:
https://github.com/nikita-volkov/composites.java
Since you've tagged Scala, I'll give a Scala answer. Just use the existing Either class. Here's an example usage:
def whatIsIt(flag: Boolean): Either[Int,String] =
if(flag) Left(123) else Right("hello")
//and then later on...
val x = whatIsIt(true)
x match {
case Left(i) => println("It was an int: " + i)
case Right(s) => println("It was a string: " + s)
}
This is completely type-safe; you won't have problems with erasure or anything like that...
And if you simply can't use Scala, at least use this as an example of how you can implement your own Either class.
The closest I can think of is a wrapper around both values that lets you check which value is set and retrieve it:
class Either<TLeft, TRight> {
boolean isLeft;
TLeft left;
TRight right;
Either(boolean isLeft, TLeft left1, TRight right) {
isLeft = isLeft;
left = left;
this.right = right;
}
public boolean isLeft() {
return isLeft;
}
public TLeft getLeft() {
if (isLeft()) {
return left;
} else {
throw new RuntimeException();
}
}
public TRight getRight() {
if (!isLeft()) {
return right;
} else {
throw new RuntimeException();
}
}
public static <L, R> Either<L, R> newLeft(L left, Class<R> rightType) {
return new Either<L, R>(true, left, null);
}
public static <L, R> Either<L, R> newRight(Class<L> leftType, R right) {
return new Either<L, R>(false, null, right);
}
}
class Main {
public static void main(String[] args) {
Either<String,Integer> foo;
foo = getString();
foo = getInteger();
}
private static Either<String, Integer> getInteger() {
return Either.newRight(String.class, 123);
}
private static Either<String, Integer> getString() {
return Either.newLeft("abc", Integer.class);
}
}
Based on the answer by Riccardo, following code snippet worked for me:
public class Either<L, R> {
private L left_value;
private R right_value;
private boolean right;
public L getLeft() {
if(!right) {
return left_value;
} else {
throw new IllegalArgumentException("Left is not initialized");
}
}
public R getRight() {
if(right) {
return right_value;
} else {
throw new IllegalArgumentException("Right is not initialized");
}
}
public boolean isRight() {
return right;
}
public Either(L left_v, Void right_v) {
this.left_value = left_v;
this.right = false;
}
public Either(Void left_v, R right_v) {
this.right_value = right_v;
right = true;
}
}
Usage:
Either<String, Integer> onlyString = new Either<String, Integer>("string", null);
Either<String, Integer> onlyInt = new Either<String, Integer>(null, new Integer(1));
if(!onlyString.isRight()) {
String s = onlyString.getLeft();
}
Change your design so that you don't need this rather absurd feature. Anything you'd do with the return value would require some sort of if/else construct. It would just be very, very ugly.
From a quick Googling, it seems to me that the only thing Haskell's Either is commonly used for is error reporting anyway, so it looks like exceptions are actually to correct replacement.