package fj.test;
import fj.*;
import static fj.P.p;
import static fj.P.p2;
import static fj.P.p3;
import static fj.P.p4;
import static fj.P.p5;
import static fj.P.p6;
import static fj.P.p7;
import static fj.P.p8;
import static fj.Primitive.Byte_Long;
import static fj.Primitive.Character_Long;
import static fj.Primitive.Double_Long;
import static fj.Primitive.Float_Long;
import static fj.Primitive.Integer_Long;
import static fj.Primitive.Long_Byte;
import static fj.Primitive.Long_Character;
import static fj.Primitive.Long_Double;
import static fj.Primitive.Long_Float;
import static fj.Primitive.Long_Integer;
import static fj.Primitive.Long_Short;
import static fj.Primitive.Short_Long;
import static fj.data.Array.array;
import fj.data.Conversions;
import static fj.data.List.isNotEmpty_;
import fj.data.Array;
import fj.data.Either;
import fj.data.Java;
import fj.data.List;
import fj.data.Natural;
import fj.data.Option;
import fj.data.Stream;
import static fj.data.Stream.cons;
import static fj.data.Stream.iterate;
import static fj.data.Stream.nil;
import static java.lang.System.arraycopy;
import static java.math.BigInteger.ZERO;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Calendar;
import java.util.Date;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.IdentityHashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Properties;
import java.util.Stack;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.Vector;
import java.util.WeakHashMap;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.SynchronousQueue;
/**
* Represents a shrinking strategy over the given type parameter if that type can be represented as
* a tree structure. This is used in falsification to produce the smallest counter-example, rather
* than the first counter-example.
*
* @version %build.number%
*/
public final class Shrink<A> {
private final F<A, Stream<A>> f;
private Shrink(final F<A, Stream<A>> f) {
this.f = f;
}
/**
* Returns a shrink of the given argument.
*
* @param a The argument to shrink.
* @return A shrink of the given argument.
*/
public Stream<A> shrink(final A a) {
return f.f(a);
}
/**
* Creates a shrink from this shrink and the given symmetric transformations.
*
* @param f A transformation from this shrink type to the new shrink type.
* @param g A transformation from the new shrink type to this shrink type.
* @return A shrink from this shrink and the given symmetric transformations.
*/
public <B> Shrink<B> map(final F<A, B> f, final F<B, A> g) {
return shrink(b -> Shrink.this.f.f(g.f(b)).map(f));
}
/**
* Constructs a shrink strategy from the given function that produces a tree of values given a
* value.
*
* @param f A function that produces a tree of values given a value.
* @return A shrink strategy from the given function that produces a tree of values given a
* value.
*/
public static <A> Shrink<A> shrink(final F<A, Stream<A>> f) {
return new Shrink<>(f);
}
/**
* Returns a shrink strategy that cannot be reduced further.
*
* @return A shrink strategy that cannot be reduced further.
*/
public static <A> Shrink<A> empty() {
return shrink(a -> nil());
}
/**
* A shrink strategy for longs using 0 as the bottom of the shrink.
*/
public static final Shrink<Long> shrinkLong = shrink(i -> {
if (i == 0L)
return nil();
else {
final Stream<Long> is = cons(0L, () -> iterate(x -> x / 2L, i).takeWhile(x2 -> x2 != 0L).map(x1 -> i - x1));
return i < 0L ? cons(-i, () -> is) : is;
}
});
/**
* A shrink strategy for booleans using false as the bottom of the shrink.
*/
public static final Shrink<Boolean> shrinkBoolean =
shrink(Function.constant(Stream.single(false)));
/**
* A shrink strategy for integers using 0 as the bottom of the shrink.
*/
public static final Shrink<Integer> shrinkInteger = shrinkLong.map(Long_Integer, Integer_Long);
/**
* A shrink strategy for bytes using 0 as the bottom of the shrink.
*/
public static final Shrink<Byte> shrinkByte = shrinkLong.map(Long_Byte, Byte_Long);
/**
* A shrink strategy for characters using 0 as the bottom of the shrink.
*/
public static final Shrink<Character> shrinkCharacter = shrinkLong.map(Long_Character, Character_Long);
/**
* A shrink strategy for shorts using 0 as the bottom of the shrink.
*/
public static final Shrink<Short> shrinkShort = shrinkLong.map(Long_Short, Short_Long);
/**
* A shrink strategy for floats using 0 as the bottom of the shrink.
*/
public static final Shrink<Float> shrinkFloat = shrinkLong.map(Long_Float, Float_Long);
/**
* A shrink strategy for doubles using 0 as the bottom of the shrink.
*/
public static final Shrink<Double> shrinkDouble = shrinkLong.map(Long_Double, Double_Long);
/**
* Returns a shrink strategy for optional values. A 'no value' is already fully
* shrunk, otherwise, the shrinking occurs on the value with the given shrink strategy.
*
* @param sa The shrink strategy for the potential value.
* @return A shrink strategy for optional values.
*/
public static <A> Shrink<Option<A>> shrinkOption(final Shrink<A> sa) {
return shrink(o -> o.isNone() ?
Stream.nil() :
cons(Option.none(), () -> sa.shrink(o.some()).map(Option.some_())));
}
/**
* Returns a shrink strategy for either values.
*
* @param sa The shrinking strategy for left values.
* @param sb The shrinking strategy for right values.
* @return A shrink strategy for either values.
*/
public static <A, B> Shrink<Either<A, B>> shrinkEither(final Shrink<A> sa, final Shrink<B> sb) {
return shrink(e -> e.isLeft() ?
sa.shrink(e.left().value()).map(Either.left_()) :
sb.shrink(e.right().value()).map(Either.right_()));
}
/**
* Returns a shrink strategy for lists. An empty list is fully shrunk.
*
* @param sa The shrink strategy for the elements of the list.
* @return A shrink strategy for lists.
*/
public static <A> Shrink<List<A>> shrinkList(final Shrink<A> sa) {
final class Util {
Stream<List<A>> removeChunks(final int n, final List<A> as) {
if (as.isEmpty())
return nil();
else if (as.tail().isEmpty())
return cons(List.nil(), Stream.nil_());
else {
final int n1 = n / 2;
final int n2 = n - n1;
final List<A> as1 = as.take(n1);
final F<List<A>, Boolean> isNotEmpty = isNotEmpty_();
return cons(
as1,
P.lazy(() ->
{
final List<A> as2 = as.drop(n1);
return cons(as2, P.lazy(() -> removeChunks(n1, as1)
.filter(isNotEmpty)
.map(aas1 -> aas1.append(as2))
.interleave(removeChunks(n2, as2)
.filter(isNotEmpty)
.map(as1::append))));
})
);
}
}
@SuppressWarnings("IfMayBeConditional")
Stream<List<A>> shrinkOne(final List<A> as) {
if (as.isEmpty())
return nil();
else
return sa.shrink(as.head()).map(a -> as.tail().cons(a)).append(shrinkOne(as.tail()).map(aas -> aas.cons(as.head())));
}
}
return shrink(as -> {
final Util u = new Util();
return u.removeChunks(as.length(), as).append(u.shrinkOne(as));
});
}
/**
* Returns a shrink strategy for arrays. An empty array is fully shrunk.
*
* @param sa The shrink strategy for the elements of the array.
* @return A shrink strategy for arrays.
*/
public static <A> Shrink<Array<A>> shrinkArray(final Shrink<A> sa) {
return shrinkList(sa).map(Conversions.List_Array(), Conversions.Array_List());
}
/**
* Returns a shrink strategy for streams. An empty stream is fully shrunk.
*
* @param sa The shrink strategy for the elements of the stream.
* @return A shrink strategy for streams.
*/
public static <A> Shrink<Stream<A>> shrinkStream(final Shrink<A> sa) {
return shrinkList(sa).map(Conversions.List_Stream(), Conversions.Stream_List());
}
/**
* A shrink strategy for strings using the empty string as the bottom of the shrink.
*/
public static final Shrink<String> shrinkString =
shrinkList(shrinkCharacter).map(Conversions.List_String, Conversions.String_List);
/**
* A shrink strategy for string buffers using the empty string as the bottom of the shrink.
*/
public static final Shrink<StringBuffer> shrinkStringBuffer =
shrinkList(shrinkCharacter).map(Conversions.List_StringBuffer, Conversions.StringBuffer_List);
/**
* A shrink strategy for string builders using the empty string as the bottom of the shrink.
*/
public static final Shrink<StringBuilder> shrinkStringBuilder =
shrinkList(shrinkCharacter).map(Conversions.List_StringBuilder, Conversions.StringBuilder_List);
/**
* A shrink strategy for throwables.
*
* @param ss A shrink strategy for throwable messages.
* @return A shrink strategy for throwables.
*/
public static Shrink<Throwable> shrinkThrowable(final Shrink<String> ss) {
return ss.map(Throwable::new, Throwable::getMessage);
}
/**
* A shrink strategy for throwables.
*/
public static final Shrink<Throwable> shrinkThrowable = shrinkThrowable(shrinkString);
// BEGIN java.util
/**
* Returns a shrink strategy for array lists. An empty array list is fully shrunk.
*
* @param sa The shrink strategy for the elements of the array list.
* @return A shrink strategy for array lists.
*/
public static <A> Shrink<ArrayList<A>> shrinkArrayList(final Shrink<A> sa) {
return shrinkList(sa).map(Java.List_ArrayList(), Java.ArrayList_List());
}
/**
* A shrink strategy for bit sets.
*/
public static final Shrink<BitSet> shrinkBitSet =
shrinkList(shrinkBoolean).map(Java.List_BitSet, Java.BitSet_List);
/**
* A shrink strategy for calendars.
*/
public static final Shrink<Calendar> shrinkCalendar =
shrinkLong.map(i -> {
final Calendar c = Calendar.getInstance();
c.setTimeInMillis(i);
return c;
}, c -> c.getTime().getTime());
/**
* A shrink strategy for dates.
*/
public static final Shrink<Date> shrinkDate =
shrinkLong.map(Date::new, Date::getTime);
/**
* A shrink strategy for enum maps.
*
* @param sk The shrink strategy for keys.
* @param sv The shrink strategy for values.
* @return A shrink strategy for enum maps.
*/
public static <K extends Enum<K>, V> Shrink<EnumMap<K, V>> shrinkEnumMap(final Shrink<K> sk, final Shrink<V> sv) {
return shrinkHashtable(sk, sv).map(EnumMap::new, Hashtable::new);
}
/**
* A shrink strategy for enum sets.
*
* @param sa The shrink strategy for the elements.
* @return A shrink strategy for enum sets.
*/
public static <A extends Enum<A>> Shrink<EnumSet<A>> shrinkEnumSet(final Shrink<A> sa) {
return shrinkList(sa).map(Java.List_EnumSet(), Java.EnumSet_List());
}
/**
* A shrink strategy for gregorian calendars.
*/
public static final Shrink<GregorianCalendar> shrinkGregorianCalendar =
shrinkLong.map(i -> {
final GregorianCalendar c = new GregorianCalendar();
c.setTimeInMillis(i);
return c;
}, c -> c.getTime().getTime());
/**
* A shrink strategy for hash maps.
*
* @param sk The shrink strategy for keys.
* @param sv The shrink strategy for values.
* @return A shrink strategy for hash maps.
*/
public static <K, V> Shrink<HashMap<K, V>> shrinkHashMap(final Shrink<K> sk, final Shrink<V> sv) {
return shrinkHashtable(sk, sv).map(HashMap::new, Hashtable::new);
}
/**
* A shrink strategy for hash sets.
*
* @param sa The shrink strategy for the elements.
* @return A shrink strategy for hash sets.
*/
public static <A> Shrink<HashSet<A>> shrinkHashSet(final Shrink<A> sa) {
return shrinkList(sa).map(Java.List_HashSet(), Java.HashSet_List());
}
/**
* A shrink strategy for hash tables.
*
* @param sk The shrink strategy for keys.
* @param sv The shrink strategy for values.
* @return A shrink strategy for hash tables.
*/
@SuppressWarnings("UseOfObsoleteCollectionType")
public static <K, V> Shrink<Hashtable<K, V>> shrinkHashtable(final Shrink<K> sk, final Shrink<V> sv) {
return shrinkList(shrinkP2(sk, sv)).map(kvs -> {
final Hashtable<K, V> h = new Hashtable<>();
kvs.foreachDoEffect(kv -> h.put(kv._1(), kv._2()));
return h;
}, h -> {
List<P2<K, V>> x = List.nil();
for (final Map.Entry<K, V> entry : h.entrySet()) {
x = x.snoc(p(entry.getKey(), entry.getValue()));
}
return x;
});
}
/**
* A shrink strategy for identity hash maps.
*
* @param sk The shrink strategy for keys.
* @param sv The shrink strategy for values.
* @return A shrink strategy for identity hash maps.
*/
public static <K, V> Shrink<IdentityHashMap<K, V>> shrinkIdentityHashMap(final Shrink<K> sk, final Shrink<V> sv) {
return shrinkHashtable(sk, sv).map(IdentityHashMap::new, Hashtable::new);
}
/**
* A shrink strategy for linked hash maps.
*
* @param sk The shrink strategy for keys.
* @param sv The shrink strategy for values.
* @return A shrink strategy for linked hash maps.
*/
public static <K, V> Shrink<LinkedHashMap<K, V>> shrinkLinkedHashMap(final Shrink<K> sk, final Shrink<V> sv) {
return shrinkHashtable(sk, sv).map(LinkedHashMap::new, Hashtable::new);
}
/**
* A shrink strategy for linked hash sets.
*
* @param sa The shrink strategy for the elements.
* @return A shrink strategy for linked hash sets.
*/
public static <A> Shrink<LinkedHashSet<A>> shrinkLinkedHashSet(final Shrink<A> sa) {
return shrinkList(sa).map(Java.List_LinkedHashSet(), Java.LinkedHashSet_List());
}
/**
* A shrink strategy for linked lists.
*
* @param sa The shrink strategy for the elements.
* @return A shrink strategy for linked lists.
*/
public static <A> Shrink<LinkedList<A>> shrinkLinkedList(final Shrink<A> sa) {
return shrinkList(sa).map(Java.List_LinkedList(), Java.LinkedList_List());
}
/**
* A shrink strategy for priority queues.
*
* @param sa The shrink strategy for the elements.
* @return A shrink strategy for priority queues.
*/
public static <A> Shrink<PriorityQueue<A>> shrinkPriorityQueue(final Shrink<A> sa) {
return shrinkList(sa).map(Java.List_PriorityQueue(), Java.PriorityQueue_List());
}
/**
* A shrink strategy for properties.
*/
public static final Shrink<Properties> shrinkProperties = shrinkHashtable(shrinkString, shrinkString)
.map(h -> {
final Properties p = new Properties();
for (final Map.Entry<String, String> entry : h.entrySet()) {
p.setProperty(entry.getKey(), entry.getValue());
}
return p;
}, p -> {
final Hashtable<String, String> t = new Hashtable<>();
for (final Object s : p.keySet()) {
t.put((String) s, p.getProperty((String) s));
}
return t;
});
/**
* A shrink strategy for stacks.
*
* @param sa The shrink strategy for the elements.
* @return A shrink strategy for stacks.
*/
public static <A> Shrink<Stack<A>> shrinkStack(final Shrink<A> sa) {
return shrinkList(sa).map(Java.List_Stack(), Java.Stack_List());
}
/**
* A shrink strategy for tree maps.
*
* @param sk The shrink strategy for keys.
* @param sv The shrink strategy for values.
* @return A shrink strategy for tree maps.
*/
public static <K, V> Shrink<TreeMap<K, V>> shrinkTreeMap(final Shrink<K> sk, final Shrink<V> sv) {
return shrinkHashtable(sk, sv).map(TreeMap::new, Hashtable::new);
}
/**
* A shrink strategy for tree sets.
*
* @param sa The shrink strategy for the elements.
* @return A shrink strategy for tree sets.
*/
public static <A> Shrink<TreeSet<A>> shrinkTreeSet(final Shrink<A> sa) {
return shrinkList(sa).map(Java.List_TreeSet(), Java.TreeSet_List());
}
/**
* A shrink strategy for vectors.
*
* @param sa The shrink strategy for the elements.
* @return A shrink strategy for vectors.
*/
public static <A> Shrink<Vector<A>> shrinkVector(final Shrink<A> sa) {
return shrinkList(sa).map(Java.List_Vector(), Java.Vector_List());
}
/**
* A shrink strategy for weak hash maps.
*
* @param sk The shrink strategy for keys.
* @param sv The shrink strategy for values.
* @return A shrink strategy for weak hash maps.
*/
public static <K, V> Shrink<WeakHashMap<K, V>> shrinkWeakHashMap(final Shrink<K> sk, final Shrink<V> sv) {
return shrinkHashtable(sk, sv).map(WeakHashMap::new, Hashtable::new);
}
// END java.util
// BEGIN java.util.concurrent
/**
* A shrink strategy for array blocking queues.
*
* @param sa The shrink strategy for the elements.
* @return A shrink strategy for array blocking queues.
*/
public static <A> Shrink<ArrayBlockingQueue<A>> shrinkArrayBlockingQueue(final Shrink<A> sa) {
return shrinkList(sa).map(Java.List_ArrayBlockingQueue(false), Java.ArrayBlockingQueue_List());
}
/**
* A shrink strategy for concurrent hash maps.
*
* @param sk The shrink strategy for keys.
* @param sv The shrink strategy for values.
* @return A shrink strategy for concurrent hash maps.
*/
public static <K, V> Shrink<ConcurrentHashMap<K, V>> shrinkConcurrentHashMap(final Shrink<K> sk, final Shrink<V> sv) {
return shrinkHashtable(sk, sv).map(ConcurrentHashMap::new, Hashtable::new);
}
/**
* A shrink strategy for concurrent linked queues.
*
* @param sa The shrink strategy for the elements.
* @return A shrink strategy for concurrent linked queues.
*/
public static <A> Shrink<ConcurrentLinkedQueue<A>> shrinkConcurrentLinkedQueue(final Shrink<A> sa) {
return shrinkList(sa).map(Java.List_ConcurrentLinkedQueue(), Java.ConcurrentLinkedQueue_List());
}
/**
* A shrink strategy for copy on write array lists.
*
* @param sa The shrink strategy for the elements.
* @return A shrink strategy for copy on write array lists.
*/
public static <A> Shrink<CopyOnWriteArrayList<A>> shrinkCopyOnWriteArrayList(final Shrink<A> sa) {
return shrinkList(sa).map(Java.List_CopyOnWriteArrayList(), Java.CopyOnWriteArrayList_List());
}
/**
* A shrink strategy for copy on write array sets.
*
* @param sa The shrink strategy for the elements.
* @return A shrink strategy for copy on write array sets.
*/
public static <A> Shrink<CopyOnWriteArraySet<A>> shrinkCopyOnWriteArraySet(final Shrink<A> sa) {
return shrinkList(sa).map(Java.List_CopyOnWriteArraySet(), Java.CopyOnWriteArraySet_List());
}
/**
* A shrink strategy for delay queues.
*
* @param sa The shrink strategy for the elements.
* @return A shrink strategy for delay queues.
*/
public static <A extends Delayed> Shrink<DelayQueue<A>> shrinkDelayQueue(final Shrink<A> sa) {
return shrinkList(sa).map(Java.List_DelayQueue(), Java.DelayQueue_List());
}
/**
* A shrink strategy for linked blocking queues.
*
* @param sa The shrink strategy for the elements.
* @return A shrink strategy for linked blocking queues.
*/
public static <A> Shrink<LinkedBlockingQueue<A>> shrinkLinkedBlockingQueue(final Shrink<A> sa) {
return shrinkList(sa).map(Java.List_LinkedBlockingQueue(), Java.LinkedBlockingQueue_List());
}
/**
* A shrink strategy for priority blocking queues.
*
* @param sa The shrink strategy for the elements.
* @return A shrink strategy for priority blocking queues.
*/
public static <A> Shrink<PriorityBlockingQueue<A>> shrinkPriorityBlockingQueue(final Shrink<A> sa) {
return shrinkList(sa).map(Java.List_PriorityBlockingQueue(), Java.PriorityBlockingQueue_List());
}
/**
* A shrink strategy for synchronous queues.
*
* @param sa The shrink strategy for the elements.
* @return A shrink strategy for synchronous queues.
*/
public static <A> Shrink<SynchronousQueue<A>> shrinkSynchronousQueue(final Shrink<A> sa) {
return shrinkList(sa).map(Java.List_SynchronousQueue(false), Java.SynchronousQueue_List());
}
// END java.util.concurrent
// BEGIN java.sql
/**
* A shrink strategy for SQL dates.
*/
public static final Shrink<java.sql.Date> shrinkSQLDate =
shrinkLong.map(java.sql.Date::new, Date::getTime);
/**
* A shrink strategy for SQL times.
*/
public static final Shrink<Time> shrinkTime =
shrinkLong.map(Time::new, Date::getTime);
/**
* A shrink strategy for SQL timestamps.
*/
public static final Shrink<Timestamp> shrinkTimestamp =
shrinkLong.map(Timestamp::new, Timestamp::getTime);
// END java.sql
// BEGIN java.math
/**
* A shrink strategy for big integers.
*/
public static final Shrink<BigInteger> shrinkBigInteger = shrink(i -> {
final Equal<BigInteger> eq = Equal.bigintEqual;
final BigInteger two = BigInteger.valueOf(2L);
if (eq.eq(i, ZERO)) {
return nil();
} else {
final Stream<BigInteger> is = cons(ZERO,
() -> iterate(x -> x.divide(two), i)
.takeWhile(x2 -> eq.notEq(x2, ZERO))
.map(i::subtract));
return Ord.bigintOrd.isLessThan(i, ZERO) ? cons(i.negate(), () -> is) : is;
}
});
/**
* A shrink strategy for big decimals.
*/
public static final Shrink<BigDecimal> shrinkBigDecimal =
shrinkBigInteger.map(BigDecimal::new, BigDecimal::toBigInteger);
// END java.math
/**
* A shrink strategy for naturals.
*/
public static final Shrink<Natural> shrinkNatural = shrinkBigInteger.map(l -> Natural.natural(l).orSome(Natural.ZERO), Natural::bigIntegerValue);
/**
* Returns a shrinking strategy for product-1 values.
*
* @param sa The shrinking strategy for the values.
* @return a shrinking strategy for product-1 values.
*/
public static <A> Shrink<P1<A>> shrinkP1(final Shrink<A> sa) {
return shrink(p -> sa.shrink(p._1()).map(P::p));
}
/**
* Returns a shrinking strategy for product-2 values.
*
* @param sa The shrinking strategy for the values.
* @param sb The shrinking strategy for the values.
* @return a shrinking strategy for product-2 values.
*/
public static <A, B> Shrink<P2<A, B>> shrinkP2(final Shrink<A> sa, final Shrink<B> sb) {
return shrink(p -> {
final F<A, F<B, P2<A, B>>> p2 = p2();
return sa.shrink(p._1()).bind(sb.shrink(p._2()), p2);
});
}
/**
* Returns a shrinking strategy for product-3 values.
*
* @param sa The shrinking strategy for the values.
* @param sb The shrinking strategy for the values.
* @param sc The shrinking strategy for the values.
* @return a shrinking strategy for product-3 values.
*/
public static <A, B, C> Shrink<P3<A, B, C>> shrinkP3(final Shrink<A> sa, final Shrink<B> sb, final Shrink<C> sc) {
return shrink(p -> {
final F<A, F<B, F<C, P3<A, B, C>>>> p3 = p3();
return sa.shrink(p._1()).bind(sb.shrink(p._2()), sc.shrink(p._3()), p3);
});
}
/**
* Returns a shrinking strategy for product-4 values.
*
* @param sa The shrinking strategy for the values.
* @param sb The shrinking strategy for the values.
* @param sc The shrinking strategy for the values.
* @param sd The shrinking strategy for the values.
* @return a shrinking strategy for product-4 values.
*/
public static <A, B, C, D> Shrink<P4<A, B, C, D>> shrinkP4(final Shrink<A> sa, final Shrink<B> sb, final Shrink<C> sc,
final Shrink<D> sd) {
return shrink(p -> {
final F<A, F<B, F<C, F<D, P4<A, B, C, D>>>>> p4 = p4();
return sa.shrink(p._1()).bind(sb.shrink(p._2()), sc.shrink(p._3()), sd.shrink(p._4()), p4);
});
}
/**
* Returns a shrinking strategy for product-5 values.
*
* @param sa The shrinking strategy for the values.
* @param sb The shrinking strategy for the values.
* @param sc The shrinking strategy for the values.
* @param sd The shrinking strategy for the values.
* @param se The shrinking strategy for the values.
* @return a shrinking strategy for product-5 values.
*/
public static <A, B, C, D, E> Shrink<P5<A, B, C, D, E>> shrinkP5(final Shrink<A> sa, final Shrink<B> sb,
final Shrink<C> sc, final Shrink<D> sd,
final Shrink<E> se) {
return shrink(p -> {
final F<A, F<B, F<C, F<D, F<E, P5<A, B, C, D, E>>>>>> p5 = p5();
return sa.shrink(p._1()).bind(sb.shrink(p._2()), sc.shrink(p._3()), sd.shrink(p._4()), se.shrink(p._5()), p5);
});
}
/**
* Returns a shrinking strategy for product-6 values.
*
* @param sa The shrinking strategy for the values.
* @param sb The shrinking strategy for the values.
* @param sc The shrinking strategy for the values.
* @param sd The shrinking strategy for the values.
* @param se The shrinking strategy for the values.
* @param sf The shrinking strategy for the values.
* @return a shrinking strategy for product-6 values.
*/
public static <A, B, C, D, E, F$> Shrink<P6<A, B, C, D, E, F$>> shrinkP6(final Shrink<A> sa, final Shrink<B> sb,
final Shrink<C> sc, final Shrink<D> sd,
final Shrink<E> se, final Shrink<F$> sf) {
return shrink(p -> {
final F<A, F<B, F<C, F<D, F<E, F<F$, P6<A, B, C, D, E, F$>>>>>>> p6 = p6();
return sa.shrink(p._1())
.bind(sb.shrink(p._2()), sc.shrink(p._3()), sd.shrink(p._4()), se.shrink(p._5()), sf.shrink(p._6()), p6);
});
}
/**
* Returns a shrinking strategy for product-7 values.
*
* @param sa The shrinking strategy for the values.
* @param sb The shrinking strategy for the values.
* @param sc The shrinking strategy for the values.
* @param sd The shrinking strategy for the values.
* @param se The shrinking strategy for the values.
* @param sf The shrinking strategy for the values.
* @param sg The shrinking strategy for the values.
* @return a shrinking strategy for product-7 values.
*/
public static <A, B, C, D, E, F$, G> Shrink<P7<A, B, C, D, E, F$, G>> shrinkP7(final Shrink<A> sa, final Shrink<B> sb,
final Shrink<C> sc, final Shrink<D> sd,
final Shrink<E> se,
final Shrink<F$> sf,
final Shrink<G> sg) {
return shrink(p -> {
final F<A, F<B, F<C, F<D, F<E, F<F$, F<G, P7<A, B, C, D, E, F$, G>>>>>>>> p7 = p7();
return sa.shrink(p._1())
.bind(sb.shrink(p._2()), sc.shrink(p._3()), sd.shrink(p._4()), se.shrink(p._5()), sf.shrink(p._6()),
sg.shrink(p._7()), p7);
});
}
/**
* Returns a shrinking strategy for product-8 values.
*
* @param sa The shrinking strategy for the values.
* @param sb The shrinking strategy for the values.
* @param sc The shrinking strategy for the values.
* @param sd The shrinking strategy for the values.
* @param se The shrinking strategy for the values.
* @param sf The shrinking strategy for the values.
* @param sg The shrinking strategy for the values.
* @param sh The shrinking strategy for the values.
* @return a shrinking strategy for product-8 values.
*/
public static <A, B, C, D, E, F$, G, H> Shrink<P8<A, B, C, D, E, F$, G, H>> shrinkP8(final Shrink<A> sa,
final Shrink<B> sb,
final Shrink<C> sc,
final Shrink<D> sd,
final Shrink<E> se,
final Shrink<F$> sf,
final Shrink<G> sg,
final Shrink<H> sh) {
return shrink(
p -> {
final F<A, F<B, F<C, F<D, F<E, F<F$, F<G, F<H, P8<A, B, C, D, E, F$, G, H>>>>>>>>> p8 = p8();
return sa.shrink(p._1())
.bind(sb.shrink(p._2()), sc.shrink(p._3()), sd.shrink(p._4()), se.shrink(p._5()), sf.shrink(p._6()),
sg.shrink(p._7()), sh.shrink(p._8()), p8);
});
}
}