11package fj .data ;
22
3- import fj .F ;
4- import fj .F1Functions ;
3+ import fj .*;
54import fj .function .Effect1 ;
65
7- import static fj .data .Option .some ;
8- import static fj .data .Option .somes ;
9-
106import java .util .Collection ;
117import java .util .Iterator ;
128
9+ import static fj .Function .identity ;
10+ import static fj .data .Option .some ;
11+ import static fj .data .Option .somes ;
12+
1313/**
1414 * Provides an in-memory, immutable, singly linked list with total <code>head</code> and <code>tail</code>.
1515 *
@@ -26,17 +26,19 @@ public Iterator<A> iterator() {
2626 return toCollection ().iterator ();
2727 }
2828
29+ private final A head ;
30+
31+ private final List <A > tail ;
32+
2933 /**
3034 * The first element of this linked list.
3135 */
32- @ SuppressWarnings ({"PublicField" , "ClassEscapesDefinedScope" })
33- public final A head ;
36+ public A head () { return head ; }
3437
3538 /**
3639 * This list without the first element.
3740 */
38- @ SuppressWarnings ({"PublicField" })
39- public final List <A > tail ;
41+ public List <A > tail () { return tail ; }
4042
4143 private NonEmptyList (final A head , final List <A > tail ) {
4244 this .head = head ;
@@ -53,6 +55,23 @@ public NonEmptyList<A> cons(final A a) {
5355 return nel (a , tail .cons (head ));
5456 }
5557
58+ /**
59+ * Appends (snoc) the given element to this non empty list to produce a new non empty list. O(n).
60+ *
61+ * @param a The element to append to this non empty list.
62+ * @return A new non empty list with the given element appended.
63+ */
64+ public NonEmptyList <A > snoc (final A a ) {
65+ return nel (head , tail .snoc (a ));
66+ }
67+
68+ /**
69+ * The length of this list.
70+ *
71+ * @return The length of this list.
72+ */
73+ public int length () { return 1 + tail .length (); }
74+
5675 /**
5776 * Appends the given list to this list.
5877 *
@@ -135,6 +154,100 @@ public <B> NonEmptyList<B> mapTails(final F<NonEmptyList<A>, B> f) {
135154 return tails ().map (f );
136155 }
137156
157+ /**
158+ * Intersperses the given argument between each element of this non empty list.
159+ *
160+ * @param a The separator to intersperse in this non empty list.
161+ * @return A non empty list with the given separator interspersed.
162+ */
163+ public NonEmptyList <A > intersperse (final A a ) {
164+ final List <A > list = toList ().intersperse (a );
165+ return nel (list .head (), list .tail ());
166+ }
167+
168+ /**
169+ * Reverse this non empty list in constant stack space.
170+ *
171+ * @return A new non empty list with the elements in reverse order.
172+ */
173+ public NonEmptyList <A > reverse () {
174+ final List <A > list = toList ().reverse ();
175+ return nel (list .head (), list .tail ());
176+ }
177+
178+ /**
179+ * Sorts this non empty list using the given order over elements using a <em>merge sort</em> algorithm.
180+ *
181+ * @param o The order over the elements of this non empty list.
182+ * @return A sorted non empty list according to the given order.
183+ */
184+ public NonEmptyList <A > sort (final Ord <A > o ) {
185+ final List <A > list = toList ().sort (o );
186+ return nel (list .head (), list .tail ());
187+ }
188+
189+ /**
190+ * Zips this non empty list with the given non empty list to produce a list of pairs. If this list and the given list
191+ * have different lengths, then the longer list is normalised so this function never fails.
192+ *
193+ * @param bs The non empty list to zip this non empty list with.
194+ * @return A new non empty list with a length the same as the shortest of this list and the given list.
195+ */
196+ public <B > NonEmptyList <P2 <A , B >> zip (final NonEmptyList <B > bs ) {
197+ final List <P2 <A , B >> list = toList ().zip (bs .toList ());
198+ return nel (list .head (), list .tail ());
199+ }
200+
201+ /**
202+ * Zips this non empty list with the index of its element as a pair.
203+ *
204+ * @return A new non empty list with the same length as this list.
205+ */
206+ public NonEmptyList <P2 <A , Integer >> zipIndex () {
207+ final List <P2 <A , Integer >> list = toList ().zipIndex ();
208+ return nel (list .head (), list .tail ());
209+ }
210+
211+ /**
212+ * Zips this non empty list with the given non empty list using the given function to produce a new list. If this list
213+ * and the given list have different lengths, then the longer list is normalised so this function
214+ * never fails.
215+ *
216+ * @param bs The non empty list to zip this non empty list with.
217+ * @param f The function to zip this non empty list and the given non empty list with.
218+ * @return A new non empty list with a length the same as the shortest of this list and the given list.
219+ */
220+ public <B , C > NonEmptyList <C > zipWith (final List <B > bs , final F <A , F <B , C >> f ) {
221+ final List <C > list = toList ().zipWith (bs , f );
222+ return nel (list .head (), list .tail ());
223+ }
224+
225+ /**
226+ * Zips this non empty list with the given non empty list using the given function to produce a new list. If this list
227+ * and the given list have different lengths, then the longer list is normalised so this function
228+ * never fails.
229+ *
230+ * @param bs The non empty list to zip this non empty list with.
231+ * @param f The function to zip this non empty list and the given non empty list with.
232+ * @return A new non empty list with a length the same as the shortest of this list and the given list.
233+ */
234+ public <B , C > NonEmptyList <C > zipWith (final List <B > bs , final F2 <A , B , C > f ) {
235+ final List <C > list = toList ().zipWith (bs , f );
236+ return nel (list .head (), list .tail ());
237+ }
238+
239+ /**
240+ * Transforms a non empty list of pairs into a non empty list of first components and
241+ * a non empty list of second components.
242+ *
243+ * @param xs The non empty list of pairs to transform.
244+ * @return A non empty list of first components and a non empty list of second components.
245+ */
246+ public static <A , B > P2 <NonEmptyList <A >, NonEmptyList <B >> unzip (final NonEmptyList <P2 <A , B >> xs ) {
247+ final P2 <List <A >, List <B >> p = List .unzip (xs .toList ());
248+ return P .p (nel (p ._1 ().head (), p ._1 ().tail ()), nel (p ._2 ().head (), p ._2 ().tail ()));
249+ }
250+
138251 /**
139252 * Returns a <code>List</code> projection of this list.
140253 *
@@ -174,13 +287,14 @@ public static <A> NonEmptyList<A> nel(final A head, final List<A> tail) {
174287 }
175288
176289 /**
177- * Return a non- empty list with the given value .
290+ * Constructs a non empty list from the given elements .
178291 *
179- * @param head The value in the non-empty list.
180- * @return A non-empty list with the given value.
292+ * @param head The first in the non-empty list.
293+ * @param tail The elements to construct a list's tail with.
294+ * @return A non-empty list with the given elements.
181295 */
182- public static <A > NonEmptyList <A > nel (final A head ) {
183- return nel (head , List .< A > nil ( ));
296+ public static <A > NonEmptyList <A > nel (final A head , final A ... tail ) {
297+ return nel (head , List .list ( tail ));
184298 }
185299
186300 /**
@@ -203,4 +317,29 @@ public static <A> Option<NonEmptyList<A>> fromList(final List<A> as) {
203317 Option .<NonEmptyList <A >>none () :
204318 some (nel (as .head (), as .tail ()));
205319 }
320+
321+ /**
322+ * Concatenate (join) a non empty list of non empty lists.
323+ *
324+ * @param o The non empty list of non empty lists to join.
325+ * @return A new non empty list that is the concatenation of the given lists.
326+ */
327+ public static <A > NonEmptyList <A > join (final NonEmptyList <NonEmptyList <A >> o ) { return o .bind (identity ()); }
328+
329+ /**
330+ * Perform an equality test on this list which delegates to the .equals() method of the member instances.
331+ * This is implemented with Equal.nonEmptyListEqual using the anyEqual rule.
332+ *
333+ * @param obj the other object to check for equality against.
334+ * @return true if this list is equal to the provided argument
335+ */
336+ @ Override public boolean equals ( final Object obj ) {
337+ return Equal .equals0 (NonEmptyList .class , this , obj , () -> Equal .nonEmptyListEqual (Equal .<A >anyEqual ()));
338+ }
339+
340+ @ Override public int hashCode () {
341+ return Hash .nonEmptyListHash (Hash .<A >anyHash ()).hash (this );
342+ }
343+
344+ @ Override public String toString () { return Show .nonEmptyListShow (Show .<A >anyShow ()).showS (this ); }
206345}
0 commit comments