diff --git a/core/src/main/java/fj/data/NonEmptyList.java b/core/src/main/java/fj/data/NonEmptyList.java
index 4073476d..6f0ced7b 100644
--- a/core/src/main/java/fj/data/NonEmptyList.java
+++ b/core/src/main/java/fj/data/NonEmptyList.java
@@ -1,14 +1,12 @@
package fj.data;
import fj.*;
-import fj.function.Effect1;
+import fj.control.Trampoline;
import java.util.Collection;
import java.util.Iterator;
-import static fj.Function.flip;
-import static fj.Function.identity;
-import static fj.Function.uncurryF2;
+import static fj.Function.*;
import static fj.data.Option.some;
import static fj.data.Option.somes;
@@ -35,12 +33,26 @@ public Iterator iterator() {
/**
* The first element of this linked list.
*/
- public A head() { return head; }
+ public A head() {
+ return head;
+ }
/**
* This list without the first element.
*/
- public List tail() { return tail; }
+ public List tail() {
+ return tail;
+ }
+
+ public List init()
+ {
+ return toList().init();
+ }
+
+ public A last()
+ {
+ return toList().last();
+ }
private NonEmptyList(final A head, final List tail) {
this.head = head;
@@ -72,7 +84,9 @@ public NonEmptyList snoc(final A a) {
*
* @return The length of this list.
*/
- public int length() { return 1 + tail.length(); }
+ public int length() {
+ return 1 + tail.length();
+ }
/**
* Appends the given list to this list.
@@ -99,40 +113,6 @@ public NonEmptyList append(final NonEmptyList as) {
return nel(head, bb);
}
- /**
- * Performs a right-fold reduction across this list. This function uses O(length) stack space.
- */
- public final A foldRight1(final F> f) {
- return reverse().foldLeft1(flip(f));
- }
-
- /**
- * Performs a right-fold reduction across this list. This function uses O(length) stack space.
- */
- public final A foldRight1(final F2 f) {
- return reverse().foldLeft1(flip(f));
- }
-
- /**
- * Performs a left-fold reduction across this list. This function runs in constant space.
- */
- public final A foldLeft1(final F> f) {
- return foldLeft1(uncurryF2(f));
- }
-
- /**
- * Performs a left-fold reduction across this list. This function runs in constant space.
- */
- public final A foldLeft1(final F2 f) {
- A x = head;
-
- for (List xs = tail; !xs.isEmpty(); xs = xs.tail()) {
- x = f.f(x, xs.head());
- }
-
- return x;
- }
-
/**
* Maps the given function across this list.
*
@@ -155,9 +135,9 @@ public NonEmptyList bind(final F> f) {
b.snoc(p.head);
b.append(p.tail);
tail.foreachDoEffect(a -> {
- final NonEmptyList p1 = f.f(a);
- b.snoc(p1.head);
- b.append(p1.tail);
+ final NonEmptyList p1 = f.f(a);
+ b.snoc(p1.head);
+ b.append(p1.tail);
});
final List bb = b.toList();
return nel(bb.head(), bb.tail());
@@ -170,8 +150,8 @@ public NonEmptyList bind(final F> f) {
*/
public NonEmptyList> sublists() {
return fromList(
- somes(toList().toStream().substreams()
- .map(F1Functions.o(NonEmptyList::fromList, Conversions.Stream_List())).toList())).some();
+ somes(toList().toStream().substreams()
+ .map(F1Functions.o(NonEmptyList::fromList, Conversions.Stream_List())).toList())).some();
}
/**
@@ -226,7 +206,7 @@ public NonEmptyList sort(final Ord o) {
return nel(list.head(), list.tail());
}
-
+
/**
* Returns the minimum element in this non empty list according to the given ordering.
*
@@ -236,7 +216,7 @@ public NonEmptyList sort(final Ord o) {
public final A minimum(final Ord o) {
return foldLeft1(o::min);
}
-
+
/**
* Returns the maximum element in this non empty list according to the given ordering.
*
@@ -246,8 +226,8 @@ public final A minimum(final Ord o) {
public final A maximum(final Ord o) {
return foldLeft1(o::max);
}
-
-
+
+
/**
* Zips this non empty list with the given non empty list to produce a list of pairs. If this list and the given list
* have different lengths, then the longer list is normalised so this function never fails.
@@ -355,7 +335,8 @@ public static NonEmptyList nel(final A head, final List tail) {
* @param tail The elements to construct a list's tail with.
* @return A non-empty list with the given elements.
*/
- @SafeVarargs public static NonEmptyList nel(final A head, final A... tail) {
+ @SafeVarargs
+ public static NonEmptyList nel(final A head, final A... tail) {
return nel(head, List.list(tail));
}
@@ -376,8 +357,8 @@ public static F> nel() {
*/
public static Option> fromList(final List as) {
return as.isEmpty() ?
- Option.none() :
- some(nel(as.head(), as.tail()));
+ Option.none() :
+ some(nel(as.head(), as.tail()));
}
/**
@@ -386,7 +367,9 @@ public static Option> fromList(final List as) {
* @param o The non empty list of non empty lists to join.
* @return A new non empty list that is the concatenation of the given lists.
*/
- public static NonEmptyList join(final NonEmptyList> o) { return o.bind(identity()); }
+ public static NonEmptyList join(final NonEmptyList> o) {
+ return o.bind(identity());
+ }
/**
* Perform an equality test on this list which delegates to the .equals() method of the member instances.
@@ -395,13 +378,540 @@ public static Option> fromList(final List as) {
* @param obj the other object to check for equality against.
* @return true if this list is equal to the provided argument
*/
- @Override public boolean equals( final Object obj ) {
+ @Override
+ public boolean equals(final Object obj) {
return Equal.equals0(NonEmptyList.class, this, obj, () -> Equal.nonEmptyListEqual(Equal.anyEqual()));
}
- @Override public int hashCode() {
+ @Override
+ public int hashCode() {
return Hash.nonEmptyListHash(Hash.anyHash()).hash(this);
}
- @Override public String toString() { return Show.nonEmptyListShow(Show.anyShow()).showS(this); }
+ @Override
+ public String toString() {
+ return Show.nonEmptyListShow(Show.anyShow()).showS(this);
+ }
+
+ /**
+ * Fold the list, from right to left.
+ *
+ * @param combine the combine function
+ * @return the output
+ */
+ public final A foldRight1(
+ final F> combine) {
+ return foldRightN(combine, identity());
+ }
+
+ /**
+ * Fold the list, from right to left.
+ *
+ * @param combine the combine function
+ * @return the output
+ */
+ public final A foldRight1(
+ final F2 combine) {
+ return foldRightN(combine, identity());
+ }
+
+ /**
+ * Fold the list, from left to right.
+ *
+ * @param combine the combine function
+ * @return the output
+ */
+ public final A foldLeft1(
+ final F> combine) {
+ return foldLeftN(combine, identity());
+ }
+
+ /**
+ * Fold the list, from left to right.
+ *
+ * @param combine the combine function
+ * @return the output
+ */
+ public final A foldLeft1(
+ final F2 combine) {
+ return foldLeftN(combine, identity());
+ }
+
+ /**
+ * Fold the list, from right to left, using one function to transform the last and another function to combine the
+ * output.
+ *
+ * @param combine the combine function
+ * @param transform the transform function
+ * @param the type of the output
+ * @return the output
+ */
+ public final B foldRightN(
+ final F> combine,
+ final F transform) {
+ return tail().isEmpty() ?
+ transform.f(head()) :
+ init().foldRight(combine, transform.f(last()));
+ }
+
+ /**
+ * Fold the list, from right to left, using one function to transform the last and another function to combine the
+ * output.
+ *
+ * @param combine the combine function
+ * @param transform the transform function
+ * @param the type of the output
+ * @return the output
+ */
+ public final B foldRightN(
+ final F2 combine,
+ final F transform) {
+ return tail().isEmpty() ?
+ transform.f(head()) :
+ init().foldRight(combine, transform.f(last()));
+ }
+
+ /**
+ * Fold the list, from left to right, using one function to transform the head and another function to combine the
+ * output.
+ *
+ * @param combine the combine function
+ * @param transform the transform function
+ * @param the type of the output
+ * @return the output
+ */
+ public final B foldLeftN(
+ final F> combine,
+ final F transform) {
+ return tail().isEmpty() ?
+ transform.f(head()) :
+ tail().foldLeft(combine, transform.f(head()));
+ }
+
+ /**
+ * Fold the list, from left to right, using one function to transform the head and another function to combine the
+ * output.
+ *
+ * @param combine the combine function
+ * @param transform the transform function
+ * @param the type of the output
+ * @return the output
+ */
+ public final B foldLeftN(
+ final F2 combine,
+ final F transform) {
+ return tail().isEmpty() ?
+ transform.f(head()) :
+ tail().foldLeft(combine, transform.f(head()));
+ }
+
+ /**
+ * Sequence the given nonEmptyList and collect the output on the right side of an either.
+ *
+ * @param nonEmptyList the given nonEmptyList
+ * @param the type of the right value
+ * @param the type of the left value
+ * @return the either
+ */
+ public static Either> sequenceEither(
+ final NonEmptyList> nonEmptyList) {
+ return nonEmptyList.traverseEither(identity());
+ }
+
+ /**
+ * Sequence the given nonEmptyList and collect the output on the left side of an either.
+ *
+ * @param nonEmptyList the given nonEmptyList
+ * @param the type of the right value
+ * @param the type of the left value
+ * @return the either
+ */
+ public static Either, R> sequenceEitherLeft(
+ final NonEmptyList> nonEmptyList) {
+ return nonEmptyList.traverseEitherLeft(identity());
+ }
+
+ /**
+ * Sequence the given nonEmptyList and collect the output on the right side of an either.
+ *
+ * @param nonEmptyList the given nonEmptyList
+ * @param the type of the right value
+ * @param the type of the left value
+ * @return the either
+ */
+ public static Either> sequenceEitherRight(
+ final NonEmptyList> nonEmptyList) {
+ return nonEmptyList.traverseEitherRight(identity());
+ }
+
+ /**
+ * Sequence the given nonEmptyList and collect the output as a function.
+ *
+ * @param nonEmptyList the given nonEmptyList
+ * @param the type of the input value
+ * @param the type of the output value
+ * @return the either
+ */
+ public static F> sequenceF(
+ final NonEmptyList> nonEmptyList) {
+ return nonEmptyList.traverseF(identity());
+ }
+
+ /**
+ * Sequence the given nonEmptyList and collect the output as an IO.
+ *
+ * @param nonEmptyList the given nonEmptyList
+ * @param the type of the IO value
+ * @return the IO
+ */
+ public static IO> sequenceIO(
+ final NonEmptyList> nonEmptyList) {
+ return nonEmptyList.traverseIO(identity());
+ }
+
+ /**
+ * Sequence the given nonEmptyList and collect the output as a list.
+ *
+ * @param nonEmptyList the given nonEmptyList
+ * @param the type of the list value
+ * @return the list
+ */
+ public static List> sequenceList(
+ final NonEmptyList> nonEmptyList) {
+ return nonEmptyList.traverseList(identity());
+ }
+
+ /**
+ * Sequence the given nonEmptyList and collect the output as a nonEmptyList.
+ *
+ * @param nonEmptyList the given nonEmptyList
+ * @param the type of the nonEmptyList value
+ * @return the nonEmptyList
+ */
+ public static NonEmptyList> sequenceNonEmptyList(
+ final NonEmptyList> nonEmptyList) {
+ return nonEmptyList.traverseNonEmptyList(identity());
+ }
+
+ /**
+ * Sequence the given nonEmptyList and collect the output as an nonEmptyList.
+ *
+ * @param nonEmptyList the given nonEmptyList
+ * @param the type of the option value
+ * @return the nonEmptyList
+ */
+ public static Option> sequenceOption(
+ final NonEmptyList