diff src/main/java/fj/data/NonEmptyList.java @ 0:fe80c1edf1be

add getLoop
author tatsuki
date Fri, 20 Mar 2015 21:04:03 +0900
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/fj/data/NonEmptyList.java	Fri Mar 20 21:04:03 2015 +0900
@@ -0,0 +1,218 @@
+package fj.data;
+
+import fj.F;
+import fj.F1Functions;
+import fj.function.Effect1;
+
+import static fj.data.Option.some;
+import static fj.data.Option.somes;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+/**
+ * Provides an in-memory, immutable, singly linked list with total <code>head</code> and <code>tail</code>.
+ *
+ * @version %build.number%
+ */
+public final class NonEmptyList<A> implements Iterable<A> {
+  /**
+   * Returns an iterator for this non-empty list. This method exists to permit the use in a <code>for</code>-each loop.
+   *
+   * @return A iterator for this non-empty list.
+   */
+
+  public Iterator<A> iterator() {
+    return toCollection().iterator();
+  }
+
+  /**
+   * The first element of this linked list.
+   */
+  @SuppressWarnings({"PublicField", "ClassEscapesDefinedScope"})
+  public final A head;
+
+  /**
+   * This list without the first element.
+   */
+  @SuppressWarnings({"PublicField"})
+  public final List<A> tail;
+
+  private NonEmptyList(final A head, final List<A> tail) {
+    this.head = head;
+    this.tail = tail;
+  }
+
+  /**
+   * Prepend the given value to this list.
+   *
+   * @param a The value to prepend.
+   * @return A non-empty list with an extra element.
+   */
+  public NonEmptyList<A> cons(final A a) {
+    return nel(a, tail.cons(head));
+  }
+
+  /**
+   * Appends the given list to this list.
+   *
+   * @param as The list to append.
+   * @return A new list with the given list appended.
+   */
+  public NonEmptyList<A> append(final NonEmptyList<A> as) {
+    final List.Buffer<A> b = new List.Buffer<A>();
+    b.append(tail);
+    b.snoc(as.head);
+    b.append(as.tail);
+    final List<A> bb = b.toList();
+    return nel(head, bb);
+  }
+
+  /**
+   * Maps the given function across this list.
+   *
+   * @param f The function to map across this list.
+   * @return A new list after the given function has been applied to each element.
+   */
+  public <B> NonEmptyList<B> map(final F<A, B> f) {
+    return nel(f.f(head), tail.map(f));
+  }
+
+  /**
+   * Binds the given function across each element of this list with a final join.
+   *
+   * @param f The function to apply to each element of this list.
+   * @return A new list after performing the map, then final join.
+   */
+  public <B> NonEmptyList<B> bind(final F<A, NonEmptyList<B>> f) {
+    final List.Buffer<B> b = new List.Buffer<B>();
+    final NonEmptyList<B> p = f.f(head);
+    b.snoc(p.head);
+    b.append(p.tail);
+    tail.foreachDoEffect(new Effect1<A>() {
+        public void f(final A a) {
+            final NonEmptyList<B> p = f.f(a);
+            b.snoc(p.head);
+            b.append(p.tail);
+        }
+    });
+    final List<B> bb = b.toList();
+    return nel(bb.head(), bb.tail());
+  }
+
+  /**
+   * Returns a NonEmptyList of the sublists of this list.
+   *
+   * @return a NonEmptyList of the sublists of this list.
+   */
+  public NonEmptyList<NonEmptyList<A>> sublists() {
+    return fromList(
+        somes(toList().toStream().substreams()
+            .map(F1Functions.o(new F<List<A>, Option<NonEmptyList<A>>>() {
+              public Option<NonEmptyList<A>> f(final List<A> list) {
+                return fromList(list);
+              }
+            }, Conversions.<A>Stream_List())).toList())).some();
+  }
+
+  /**
+   * Returns a NonEmptyList of the tails of this list. A list is considered a tail of itself for the purpose of this
+   * function (Comonad pattern).
+   *
+   * @return A NonEmptyList of the tails of this list.
+   */
+  public NonEmptyList<NonEmptyList<A>> tails() {
+    return fromList(somes(toList().tails().map(new F<List<A>, Option<NonEmptyList<A>>>() {
+      public Option<NonEmptyList<A>> f(final List<A> list) {
+        return fromList(list);
+      }
+    }))).some();
+  }
+
+  /**
+   * Maps the given function across the tails of this list (comonad pattern).
+   *
+   * @param f The function to map across the tails of this list.
+   * @return The results of applying the given function to the tails of this list, as a NonEmptyList.
+   */
+  public <B> NonEmptyList<B> mapTails(final F<NonEmptyList<A>, B> f) {
+    return tails().map(f);
+  }
+
+  /**
+   * Returns a <code>List</code> projection of this list.
+   *
+   * @return A <code>List</code> projection of this list.
+   */
+  public List<A> toList() {
+    return tail.cons(head);
+  }
+
+  /**
+   * Projects an immutable collection of this non-empty list.
+   *
+   * @return An immutable collection of this non-empty list.
+   */
+  public Collection<A> toCollection() {
+    return toList().toCollection();
+  }
+
+  /**
+   * Returns a function that takes a non-empty list to a list.
+   *
+   * @return A function that takes a non-empty list to a list.
+   */
+  public static <A> F<NonEmptyList<A>, List<A>> toList_() {
+    return new F<NonEmptyList<A>, List<A>>() {
+      public List<A> f(final NonEmptyList<A> as) {
+        return as.toList();
+      }
+    };
+  }
+
+  /**
+   * Return a non-empty list with the given head and tail.
+   *
+   * @param head The first element of the new list.
+   * @param tail The remaining elements of the new list.
+   * @return A non-empty list with the given head and tail.
+   */
+  public static <A> NonEmptyList<A> nel(final A head, final List<A> tail) {
+    return new NonEmptyList<A>(head, tail);
+  }
+
+  /**
+   * Return a non-empty list with the given value.
+   *
+   * @param head The value in the non-empty list.
+   * @return A non-empty list with the given value.
+   */
+  public static <A> NonEmptyList<A> nel(final A head) {
+    return nel(head, List.<A>nil());
+  }
+
+  /**
+   * Returns a function that puts an element into a non-empty list.
+   *
+   * @return A function that puts an element into a non-empty list.
+   */
+  public static <A> F<A, NonEmptyList<A>> nel() {
+    return new F<A, NonEmptyList<A>>() {
+      public NonEmptyList<A> f(final A a) {
+        return nel(a);
+      }
+    };
+  }
+
+  /**
+   * Returns a potential non-empty list from the given list. A non-value is returned if the given list is empty.
+   *
+   * @param as The list to construct a potential non-empty list with.
+   * @return A potential non-empty list from the given list.
+   */
+  public static <A> Option<NonEmptyList<A>> fromList(final List<A> as) {
+    return as.isEmpty() ?
+           Option.<NonEmptyList<A>>none() :
+           some(nel(as.head(), as.tail()));
+  }
+}