package fj;
import fj.control.parallel.Promise;
import fj.data.Array;
import fj.data.IterableW;
import fj.data.List;
import fj.data.NonEmptyList;
import fj.data.Option;
import fj.data.Set;
import fj.data.Stream;
import fj.data.Tree;
import fj.data.TreeZipper;
import fj.data.Zipper;
import static fj.data.Tree.node;
import static fj.P.p;
import static fj.data.IterableW.wrap;
import static fj.data.Set.iterableSet;
import static fj.data.TreeZipper.treeZipper;
import static fj.data.Zipper.zipper;
/**
* A transformation function of arity-2 from A and B to C.
* This type can be represented using the Java 7 closure syntax.
*
* @version %build.number%
*/
public abstract class F2 {
/**
* Transform A and B to C.
*
* @param a The A to transform.
* @param b The B to transform.
* @return The result of the transformation.
*/
public abstract C f(A a, B b);
/**
* Partial application.
*
* @param a The A to which to apply this function.
* @return The function partially applied to the given argument.
*/
public final F f(final A a) {
return new F() {
public C f(final B b) {
return F2.this.f(a, b);
}
};
}
/**
* Curries this wrapped function to a wrapped function of arity-1 that returns another wrapped function.
*
* @return a wrapped function of arity-1 that returns another wrapped function.
*/
public final F> curry() {
return new F>() {
public F f(final A a) {
return new F() {
public C f(final B b) {
return F2.this.f(a, b);
}
};
}
};
}
/**
* Flips the arguments of this function.
*
* @return A new function with the arguments of this function flipped.
*/
public final F2 flip() {
return new F2() {
public C f(final B b, final A a) {
return F2.this.f(a, b);
}
};
}
/**
* Uncurries this function to a function on tuples.
*
* @return A new function that calls this function with the elements of a given tuple.
*/
public final F, C> tuple() {
return new F, C>() {
public C f(final P2 p) {
return F2.this.f(p._1(), p._2());
}
};
}
/**
* Promotes this function to a function on Arrays.
*
* @return This function promoted to transform Arrays.
*/
public final F2, Array, Array> arrayM() {
return new F2, Array, Array>() {
public Array f(final Array a, final Array b) {
return a.bind(b, F2.this.curry());
}
};
}
/**
* Promotes this function to a function on Promises.
*
* @return This function promoted to transform Promises.
*/
public final F2, Promise, Promise> promiseM() {
return new F2, Promise, Promise>() {
public Promise f(final Promise a, final Promise b) {
return a.bind(b, F2.this.curry());
}
};
}
/**
* Promotes this function to a function on Iterables.
*
* @return This function promoted to transform Iterables.
*/
public final F2, Iterable, IterableW> iterableM() {
return new F2, Iterable, IterableW>() {
public IterableW f(final Iterable a, final Iterable b) {
return IterableW.liftM2(F2.this.curry()).f(a).f(b);
}
};
}
/**
* Promotes this function to a function on Lists.
*
* @return This function promoted to transform Lists.
*/
public final F2, List, List> listM() {
return new F2, List, List>() {
public List f(final List a, final List b) {
return List.liftM2(F2.this.curry()).f(a).f(b);
}
};
}
/**
* Promotes this function to a function on non-empty lists.
*
* @return This function promoted to transform non-empty lists.
*/
public final F2, NonEmptyList, NonEmptyList> nelM() {
return new F2, NonEmptyList, NonEmptyList>() {
public NonEmptyList f(final NonEmptyList as, final NonEmptyList bs) {
return NonEmptyList.fromList(as.toList().bind(bs.toList(), F2.this)).some();
}
};
}
/**
* Promotes this function to a function on Options.
*
* @return This function promoted to transform Options.
*/
public final F2