{@link Maybe}<{@link These}<A,B>>
+ */
+ public static Maybe{@link SingletonHList}<_1> of the first element.
+ *
+ * @return The {@link SingletonHList}<_1>
+ */
+ public SingletonHList<_1> init() {
+ return invert().tail();
+ }
+
/**
* Static factory method for creating Tuple2s from {@link java.util.Map.Entry}s.
*
diff --git a/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple3.java b/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple3.java
index e32eac589..b392ffe38 100644
--- a/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple3.java
+++ b/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple3.java
@@ -44,8 +44,8 @@ public class Tuple3<_1, _2, _3> extends HCons<_1, Tuple2<_2, _3>> implements
Tuple3(_1 _1, Tuple2<_2, _3> tail) {
super(_1, tail);
this._1 = _1;
- _2 = tail._1();
- _3 = tail._2();
+ _2 = tail._1();
+ _3 = tail._2();
}
/**
@@ -56,6 +56,17 @@ public <_0> Tuple4<_0, _1, _2, _3> cons(_0 _0) {
return new Tuple4<>(_0, this);
}
+ /**
+ * Snoc an element onto the back of this {@link Tuple3}.
+ *
+ * @param _4 the new last element
+ * @param <_4> the new last element type
+ * @return the new {@link Tuple4}
+ */
+ public <_4> Tuple4<_1, _2, _3, _4> snoc(_4 _4) {
+ return tuple(_1, _2, _3, _4);
+ }
+
/**
* {@inheritDoc}
*/
@@ -208,6 +219,16 @@ AppTrav extends Applicative{@link Tuple2}<_1, _2> of all the elements of this
+ * {@link Tuple3}<_1, _2, _3> except the last.
+ *
+ * @return The {@link Tuple2}<_1, _2> representing all but the last element
+ */
+ public Tuple2<_1, _2> init() {
+ return rotateR3().tail();
+ }
+
/**
* Given a value of type A, produced an instance of this tuple with each slot set to that value.
*
diff --git a/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple4.java b/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple4.java
index 3e74da859..d8dc42868 100644
--- a/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple4.java
+++ b/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple4.java
@@ -46,9 +46,9 @@ public class Tuple4<_1, _2, _3, _4> extends HCons<_1, Tuple3<_2, _3, _4>> implem
Tuple4(_1 _1, Tuple3<_2, _3, _4> tail) {
super(_1, tail);
this._1 = _1;
- _2 = tail._1();
- _3 = tail._2();
- _4 = tail._3();
+ _2 = tail._1();
+ _3 = tail._2();
+ _4 = tail._3();
}
/**
@@ -59,6 +59,17 @@ public <_0> Tuple5<_0, _1, _2, _3, _4> cons(_0 _0) {
return new Tuple5<>(_0, this);
}
+ /**
+ * Snoc an element onto the back of this {@link Tuple4}.
+ *
+ * @param _5 the new last element
+ * @param <_5> the new last element type
+ * @return the new {@link Tuple5}
+ */
+ public <_5> Tuple5<_1, _2, _3, _4, _5> snoc(_5 _5) {
+ return tuple(_1, _2, _3, _4, _5);
+ }
+
/**
* {@inheritDoc}
*/
@@ -235,6 +246,16 @@ AppTrav extends Applicative{@link Tuple3}<_1, _2, _3> of all the elements of this
+ * {@link Tuple4}<_1, _2, _3, _4> except the last.
+ *
+ * @return The {@link Tuple3}<_1, _2, _3> representing all but the last element
+ */
+ public Tuple3<_1, _2, _3> init() {
+ return rotateR4().tail();
+ }
+
/**
* Given a value of type A, produced an instance of this tuple with each slot set to that value.
*
diff --git a/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple5.java b/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple5.java
index c87ee564b..5a6f20cbb 100644
--- a/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple5.java
+++ b/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple5.java
@@ -48,10 +48,10 @@ public class Tuple5<_1, _2, _3, _4, _5> extends HCons<_1, Tuple4<_2, _3, _4, _5>
Tuple5(_1 _1, Tuple4<_2, _3, _4, _5> tail) {
super(_1, tail);
this._1 = _1;
- _2 = tail._1();
- _3 = tail._2();
- _4 = tail._3();
- _5 = tail._4();
+ _2 = tail._1();
+ _3 = tail._2();
+ _4 = tail._3();
+ _5 = tail._4();
}
/**
@@ -62,6 +62,17 @@ public <_0> Tuple6<_0, _1, _2, _3, _4, _5> cons(_0 _0) {
return new Tuple6<>(_0, this);
}
+ /**
+ * Snoc an element onto the back of this {@link Tuple5}.
+ *
+ * @param _6 the new last element
+ * @param <_6> the new last element type
+ * @return the new {@link Tuple6}
+ */
+ public <_6> Tuple6<_1, _2, _3, _4, _5, _6> snoc(_6 _6) {
+ return tuple(_1, _2, _3, _4, _5, _6);
+ }
+
/**
* {@inheritDoc}
*/
@@ -262,6 +273,16 @@ AppTrav extends Applicative{@link Tuple4}<_1, _2, _3, _4> of all the elements of this
+ * {@link Tuple5}<_1, _2, _3, _4, _5> except the last.
+ *
+ * @return The {@link Tuple4}<_1, _2, _3, _4> representing all but the last element
+ */
+ public Tuple4<_1, _2, _3, _4> init() {
+ return rotateR5().tail();
+ }
+
/**
* Given a value of type A, produced an instance of this tuple with each slot set to that value.
*
diff --git a/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple6.java b/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple6.java
index 6d07b503b..1034e3b6b 100644
--- a/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple6.java
+++ b/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple6.java
@@ -51,11 +51,11 @@ public class Tuple6<_1, _2, _3, _4, _5, _6> extends HCons<_1, Tuple5<_2, _3, _4,
Tuple6(_1 _1, Tuple5<_2, _3, _4, _5, _6> tail) {
super(_1, tail);
this._1 = _1;
- _2 = tail._1();
- _3 = tail._2();
- _4 = tail._3();
- _5 = tail._4();
- _6 = tail._5();
+ _2 = tail._1();
+ _3 = tail._2();
+ _4 = tail._3();
+ _5 = tail._4();
+ _6 = tail._5();
}
/**
@@ -66,6 +66,17 @@ public <_0> Tuple7<_0, _1, _2, _3, _4, _5, _6> cons(_0 _0) {
return new Tuple7<>(_0, this);
}
+ /**
+ * Snoc an element onto the back of this {@link Tuple6}.
+ *
+ * @param _7 the new last element
+ * @param <_7> the new last element type
+ * @return the new {@link Tuple7}
+ */
+ public <_7> Tuple7<_1, _2, _3, _4, _5, _6, _7> snoc(_7 _7) {
+ return tuple(_1, _2, _3, _4, _5, _6, _7);
+ }
+
/**
* {@inheritDoc}
*/
@@ -293,6 +304,16 @@ AppTrav extends Applicative{@link Tuple5}<_1, _2, _3, _4, _5> of all the elements of this
+ * {@link Tuple6}<_1, _2, _3, _4, _5, _6> except the last.
+ *
+ * @return The {@link Tuple5}<_1, _2, _3, _4, _5> representing all but the last element
+ */
+ public Tuple5<_1, _2, _3, _4, _5> init() {
+ return rotateR6().tail();
+ }
+
/**
* Given a value of type A, produced an instance of this tuple with each slot set to that value.
*
diff --git a/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple7.java b/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple7.java
index a3e162f73..cdfe552d6 100644
--- a/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple7.java
+++ b/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple7.java
@@ -54,12 +54,12 @@ public class Tuple7<_1, _2, _3, _4, _5, _6, _7> extends HCons<_1, Tuple6<_2, _3,
Tuple7(_1 _1, Tuple6<_2, _3, _4, _5, _6, _7> tail) {
super(_1, tail);
this._1 = _1;
- _2 = tail._1();
- _3 = tail._2();
- _4 = tail._3();
- _5 = tail._4();
- _6 = tail._5();
- _7 = tail._6();
+ _2 = tail._1();
+ _3 = tail._2();
+ _4 = tail._3();
+ _5 = tail._4();
+ _6 = tail._5();
+ _7 = tail._6();
}
/**
@@ -70,6 +70,17 @@ public <_0> Tuple8<_0, _1, _2, _3, _4, _5, _6, _7> cons(_0 _0) {
return new Tuple8<>(_0, this);
}
+ /**
+ * Snoc an element onto the back of this {@link Tuple7}.
+ *
+ * @param _8 the new last element
+ * @param <_8> the new last element type
+ * @return the new {@link Tuple8}
+ */
+ public <_8> Tuple8<_1, _2, _3, _4, _5, _6, _7, _8> snoc(_8 _8) {
+ return tuple(_1, _2, _3, _4, _5, _6, _7, _8);
+ }
+
/**
* {@inheritDoc}
*/
@@ -323,6 +334,16 @@ AppTrav extends Applicative{@link Tuple6}<_1, _2, _3, _4, _5, _6> of all the elements of this
+ * {@link Tuple7}<_1, _2, _3, _4, _5, _6, _7> except the last.
+ *
+ * @return The {@link Tuple6}<_1, _2, _3, _4, _5, _6> representing all but the last element
+ */
+ public Tuple6<_1, _2, _3, _4, _5, _6> init() {
+ return rotateR7().tail();
+ }
+
/**
* Given a value of type A, produced an instance of this tuple with each slot set to that value.
*
diff --git a/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple8.java b/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple8.java
index 8a8001e24..079a30611 100644
--- a/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple8.java
+++ b/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple8.java
@@ -57,13 +57,13 @@ public class Tuple8<_1, _2, _3, _4, _5, _6, _7, _8> extends HCons<_1, Tuple7<_2,
Tuple8(_1 _1, Tuple7<_2, _3, _4, _5, _6, _7, _8> tail) {
super(_1, tail);
this._1 = _1;
- _2 = tail._1();
- _3 = tail._2();
- _4 = tail._3();
- _5 = tail._4();
- _6 = tail._5();
- _7 = tail._6();
- _8 = tail._7();
+ _2 = tail._1();
+ _3 = tail._2();
+ _4 = tail._3();
+ _5 = tail._4();
+ _6 = tail._5();
+ _7 = tail._6();
+ _8 = tail._7();
}
/**
@@ -74,6 +74,17 @@ public <_0> HCons<_0, Tuple8<_1, _2, _3, _4, _5, _6, _7, _8>> cons(_0 _0) {
return new HCons<>(_0, this);
}
+ /**
+ * Snoc an element onto the back of this {@link Tuple8}.
+ *
+ * @param _9 the new last element
+ * @param <_9> the new last element type
+ * @return the new {@link HCons consed} {@link Tuple8}
+ */
+ public <_9> HCons<_1, Tuple8<_2, _3, _4, _5, _6, _7, _8, _9>> snoc(_9 _9) {
+ return singletonHList(_9).cons(_8).cons(_7).cons(_6).cons(_5).cons(_4).cons(_3).cons(_2).cons(_1);
+ }
+
/**
* {@inheritDoc}
*/
@@ -353,6 +364,16 @@ AppTrav extends Applicative{@link Tuple7}<_1, _2, _3, _4, _5, _6, _7> of all the elements of this
+ * {@link Tuple8}<_1, _2, _3, _4, _5, _6, _7, _8> except the last.
+ *
+ * @return The {@link Tuple7}<_1, _2, _3, _4, _5, _6, _7> representing all but the last element
+ */
+ public Tuple7<_1, _2, _3, _4, _5, _6, _7> init() {
+ return rotateR8().tail();
+ }
+
/**
* Given a value of type A, produced an instance of this tuple with each slot set to that value.
*
diff --git a/src/main/java/com/jnape/palatable/lambda/functions/Fn1.java b/src/main/java/com/jnape/palatable/lambda/functions/Fn1.java
index 3f2be1e92..cb4904d35 100644
--- a/src/main/java/com/jnape/palatable/lambda/functions/Fn1.java
+++ b/src/main/java/com/jnape/palatable/lambda/functions/Fn1.java
@@ -123,7 +123,7 @@ default
+ * {@code
+ * List> fns = asList(x -> x + 1, x -> x, x -> x - 1);
+ * List args = asList(0, 1, 2);
+ * Iterable results = zipWith($(), fns, args); // [1, 1, 1]
+ * }
+ *
+ *
+ * @param the applied {@link Fn1 Fn1's} input type
+ * @param the applied {@link Fn1 Fn1's} output type
+ */
+public final class $ implements Fn2A to some {@link Comparable} type B and two values
@@ -16,6 +18,7 @@
* @param the value type
* @param the mapped comparison type
* @see CmpEq
+ * @see CmpEqWith
* @see LTBy
* @see GTBy
*/
@@ -28,7 +31,7 @@ private CmpEqBy() {
@Override
public Boolean checkedApply(Fn1 super A, ? extends B> compareFn, A x, A y) {
- return compareFn.apply(x).compareTo(compareFn.apply(y)) == 0;
+ return cmpEqWith(comparing(compareFn.toFunction()), x, y);
}
@Override
diff --git a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn3/CmpEqWith.java b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn3/CmpEqWith.java
new file mode 100644
index 000000000..ff95cd2fc
--- /dev/null
+++ b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn3/CmpEqWith.java
@@ -0,0 +1,62 @@
+package com.jnape.palatable.lambda.functions.builtin.fn3;
+
+import com.jnape.palatable.lambda.functions.Fn3;
+import com.jnape.palatable.lambda.functions.specialized.BiPredicate;
+import com.jnape.palatable.lambda.functions.specialized.Predicate;
+
+import java.util.Comparator;
+
+import static com.jnape.palatable.lambda.functions.builtin.fn3.Compare.compare;
+import static com.jnape.palatable.lambda.functions.ordering.ComparisonRelation.equal;
+import static com.jnape.palatable.lambda.functions.specialized.Predicate.predicate;
+
+/**
+ * Given a {@link Comparator} from some type A and two values of type A, return
+ * true if the first value is strictly equal to the second value (according to
+ * {@link Comparator#compare(Object, Object)} otherwise, return false.
+ *
+ * @param the value type
+ * @see CmpEqBy
+ * @see LTBy
+ * @see GTBy
+ * @see Compare
+ */
+public final class CmpEqWith implements Fn3A and two values of type A, return a
+ * {@link ComparisonRelation} of the first value with reference to the second value (according to
+ * {@link Comparator#compare(Object, Object)}. The order of parameters is flipped with respect to
+ * {@link Comparator#compare(Object, Object)} for more idiomatic partial application.
+ * + * Example: + *
+ * {@code
+ * Compare.compare(naturalOrder(), 1, 2); // ComparisonRelation.GreaterThan
+ * Compare.compare(naturalOrder(), 2, 1); // ComparisonRelation.LessThan
+ * Compare.compare(naturalOrder(), 1, 1); // ComparisonRelation.Equal
+ * }
+ *
+ *
+ * @param the value type
+ * @see Comparator
+ * @see Compare
+ */
+public final class Compare implements Fn3A to some {@link Comparable} type B and two values
@@ -16,6 +18,7 @@
* @param the value type
* @param the mapped comparison type
* @see GT
+ * @see GTWith
* @see LTBy
*/
public final class GTBy> implements Fn3A to some {@link Comparable} type B and two values
@@ -18,6 +19,7 @@
* @param the value type
* @param the mapped comparison type
* @see GTE
+ * @see GTEWith
* @see LTEBy
*/
public final class GTEBy> implements Fn3A and two values of type A,
+ * return true if the second value is greater than or equal to the first value in
+ * terms of their mapped B results according to {@link Comparator#compare(Object, Object)};
+ * otherwise, return false.
+ *
+ * @param the value type
+ * @see GTE
+ * @see GTEBy
+ * @see LTEWith
+ */
+public final class GTEWith implements Fn3A and two values of type A,
+ * return true if the second value is strictly greater than the first value in
+ * terms of their mapped B results; otherwise, return false.
+ *
+ * @param the value type
+ * @see GT
+ * @see GTBy
+ * @see LTWith
+ */
+public final class GTWith implements Fn3A to some {@link Comparable} type B and two values
@@ -27,7 +29,7 @@ private LTBy() {
@Override
public Boolean checkedApply(Fn1 super A, ? extends B> compareFn, A y, A x) {
- return compareFn.apply(x).compareTo(compareFn.apply(y)) < 0;
+ return ltWith(comparing(compareFn.toFunction()), y, x);
}
@Override
diff --git a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn3/LTEBy.java b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn3/LTEBy.java
index bc755470d..4c377d583 100644
--- a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn3/LTEBy.java
+++ b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn3/LTEBy.java
@@ -6,7 +6,8 @@
import com.jnape.palatable.lambda.functions.specialized.BiPredicate;
import com.jnape.palatable.lambda.functions.specialized.Predicate;
-import static com.jnape.palatable.lambda.functions.builtin.fn3.CmpEqBy.cmpEqBy;
+import static com.jnape.palatable.lambda.functions.builtin.fn3.LTEWith.lteWith;
+import static java.util.Comparator.comparing;
/**
* Given a mapping function from some type A to some {@link Comparable} type B and two values
@@ -28,7 +29,7 @@ private LTEBy() {
@Override
public Boolean checkedApply(Fn1 super A, ? extends B> compareFn, A y, A x) {
- return LTBy.ltBy(compareFn).or(cmpEqBy(compareFn)).apply(y, x);
+ return lteWith(comparing(compareFn.toFunction()), y, x);
}
@Override
diff --git a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn3/LTEWith.java b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn3/LTEWith.java
new file mode 100644
index 000000000..403f5c15f
--- /dev/null
+++ b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn3/LTEWith.java
@@ -0,0 +1,62 @@
+package com.jnape.palatable.lambda.functions.builtin.fn3;
+
+import com.jnape.palatable.lambda.functions.Fn3;
+import com.jnape.palatable.lambda.functions.builtin.fn2.LTE;
+import com.jnape.palatable.lambda.functions.specialized.BiPredicate;
+import com.jnape.palatable.lambda.functions.specialized.Predicate;
+
+import java.util.Comparator;
+
+import static com.jnape.palatable.lambda.functions.builtin.fn3.GTWith.gtWith;
+import static com.jnape.palatable.lambda.functions.specialized.Predicate.predicate;
+
+/**
+ * Given a {@link Comparator} from some type A and two values of type A,
+ * return true if the second value is less than or equal to the first value in
+ * terms of their mapped B results according to {@link Comparator#compare(Object, Object)};
+ * otherwise, return false.
+ *
+ * @param the value type
+ * @see LTE
+ * @see LTEBy
+ * @see GTEWith
+ */
+public final class LTEWith implements Fn3A and two values of type A,
+ * return true if the second value is strictly less than than the first value in
+ * terms of their mapped B results; otherwise, return false.
+ *
+ * @param the value type
+ * @see LT
+ * @see LTBy
+ * @see GTWith
+ */
+public final class LTWith implements Fn3+ * Due to its singly-linked embedded design, {@link IterateT} is a canonical example of purely-functional streaming + * computation. For example, to lazily print all lines from a file descriptor, an initial implementation using + * {@link IterateT} might take the following form: + *
+ * String filePath = "/tmp/a_tale_of_two_cities.txt";
+ * IterateT<IO<?>, String> streamLines = IterateT.unfold(
+ * reader -> io(() -> maybe(reader.readLine()).fmap(line -> tuple(line, reader))),
+ * io(() -> Files.newBufferedReader(Paths.get(filePath))));
+ *
+ * // iterative read and print lines without retaining references
+ * IO<Unit> printLines = streamLines.forEach(line -> io(() -> System.out.println(line)));
+ * printLines.unsafePerformIO(); // prints "It was the best of times, it was the worst of times, [...]"
+ *
+ *
+ * @param other {@link IterateT}.
+ *
+ * @param other the other {@link IterateT}
+ * @return the concatenated {@link IterateT}
+ */
+ public IterateTC inside the
+ * context of the monadic effect, using the provided cFn0 to construct the initial instance.
+ *
+ * Note that this is a fundamentally monolithic operation - meaning that incremental progress is not possible - and
+ * as such, calling this on an infinite {@link IterateT} will result in either heap exhaustion (e.g. in the case of
+ * {@link List lists}) or non-termination (e.g. in the case of {@link Set sets}).
+ *
+ * @param cFn0 the {@link Collection} construction function
+ * @param fn and a starting seed value
+ * mb by successively applying fn to the latest seed value, producing {@link Maybe maybe}
+ * a value to yield out and the next seed value for the subsequent computation.
+ *
+ * @param fn the unfolding function
+ * @param mb the starting seed value
+ * @param