All Downloads are FREE. Search and download functionalities are using the official Maven repository.

fj.data.Enumerator Maven / Gradle / Ivy

Go to download

Functional Java is an open source library that supports closures for the Java programming language

There is a newer version: 5.0
Show newest version
package fj.data;

import fj.F;

import static fj.Function.*;
import static fj.data.Option.none;
import static fj.data.Option.some;

import fj.Function;
import fj.Ord;

import static fj.Ord.*;
import fj.Ordering;
import static fj.Ordering.*;

import java.math.BigDecimal;
import java.math.BigInteger;

/**
 * Abstracts over a type that may have a successor and/or predecessor value. This implies ordering for that type. A user
 * may construct an enumerator with an optimised version for plus, otherwise a default is implemented using
 * the given successor/predecessor implementations.
 * 

* For any enumerator e, the following laws must satisfy: *

    *
  • forall a. e.successor(a).forall(\t -> e.predecessor(t).forall(\z -> z == a))
  • *
  • forall a. e.predecessor(a).forall(\t -> e.successor(t).forall(\z -> z == a))
  • *
  • e.max().forall(\t -> e.successor(t).isNone)
  • *
  • e.min().forall(\t -> e.predecessor(t).isNone)
  • *
  • forall a n. e.plus(a, 0) == Some(a)
  • *
  • forall a n | n > 0. e.plus(a, n) == e.plus(a, n - 1)
  • *
  • forall a n | n < 0. e.plus(a, n) == e.plus(a, n + 1)
  • *
* * @version %build.number% */ public final class Enumerator { private final F> successor; private final F> predecessor; private final Option max; private final Option min; private final Ord order; private final F>> plus; private Enumerator(final F> successor, final F> predecessor, final Option max, final Option min, final Ord order, final F>> plus) { this.successor = successor; this.predecessor = predecessor; this.max = max; this.min = min; this.order = order; this.plus = plus; } /** * Returns the potential successor of a value for this enumerator in curried form. * * @return The potential successor of a value for this enumerator in curried form. */ public F> successor() { return successor; } /** * Returns the potential successor of a value for this enumerator. * * @param a The value to return the successor of. * @return The potential successor of a value for this enumerator. */ public Option successor(final A a) { return successor.f(a); } /** * Returns the potential predecessor of a value for this enumerator in curried form. * * @return The potential predecessor of a value for this enumerator in curried form. */ public F> predecessor() { return predecessor; } /** * Returns the potential predecessor of a value for this enumerator. * * @param a The value to return the predecessor of. * @return The potential predecessor of a value for this enumerator. */ public Option predecessor(final A a) { return predecessor.f(a); } /** * Returns the maximum value for this enumerator if there is one. * * @return The maximum value for this enumerator if there is one. */ public Option max() { return max; } /** * Returns the minimum value for this enumerator if there is one. * * @return The minimum value for this enumerator if there is one. */ public Option min() { return min; } /** * Returns a function that moves a value along the enumerator a given number of times. * * @return A function that moves a value along the enumerator a given number of times. */ public F>> plus() { return plus; } /** * Returns a function that moves a value along the enumerator a given number of times. * * @param a The value to begin moving along from. * @return A function that moves a value along the enumerator a given number of times. */ public F> plus(final A a) { return plus.f(a); } /** * Returns a function that moves a value along the enumerator a given number of times. * * @param l The number of times to move along the enumerator. * @return A function that moves a value along the enumerator a given number of times. */ public F> plus(final long l) { return flip(plus).f(l); } /** * Moves a value along the enumerator a given number of times. * * @param a The value to begin moving along from. * @param l The number of times to move along the enumerator. * @return A potential value after having moved the given number of times. */ public Option plus(final A a, final long l) { return plus.f(a).f(l); } /** * Returns the ordering for the enumerator. * * @return The ordering for the enumerator. */ public Ord order() { return order; } /** * Invariant functor map over this enumerator. * * @param f The covariant map. * @param g The contra-variant map. * @return An enumerator after the given functions are applied. */ public Enumerator xmap(final F f, final F g) { final F, Option> of = o -> o.map(f); return enumerator(compose(compose(of, successor), g), compose(compose(of, predecessor), g), max.map(f), min.map(f), order.contramap(g), compose(compose(Function., Option>compose().f(of), plus), g)); } /** * Returns a stream of the values from this enumerator, starting at the given value, counting up. * * @param a A value at which to begin the stream. * @return a stream of the values from this enumerator, starting at the given value, counting up. */ public Stream toStream(final A a) { final F id = identity(); return Stream.fromFunction(this, id, a); } /** * Create a new enumerator with the given minimum value. * * @param min A minimum value. * @return A new enumerator identical to this one, but with the given minimum value. */ public Enumerator setMin(final Option min) { return enumerator(successor, predecessor, max, min, order, plus); } /** * Create a new enumerator with the given maximum value. * * @param max A maximum value. * @return A new enumerator identical to this one, but with the given maximum value. */ public Enumerator setMax(final Option max) { return enumerator(successor, predecessor, max, min, order, plus); } /** * Construct an enumerator. ` * * @param successor The successor function. * @param predecessor The predecessor function. * @param max The potential maximum value. * @param min The potential minimum value. * @param order The ordering for the type. * @param plus The function to move the enumeration a given number of times. This may be supplied for a performance * enhancement for certain types. * @return An enumerator with the given values. */ public static Enumerator enumerator(final F> successor, final F> predecessor, final Option max, final Option min, final Ord order, final F>> plus) { return new Enumerator<>(successor, predecessor, max, min, order, plus); } /** * Construct an enumerator. The plus function is derived from the successor and * predecessor. * * @param successor The successor function. * @param predecessor The predecessor function. * @param max The potential maximum value. * @param min The potential minimum value. * @param order The ordering for the type. * @return An enumerator with the given values. */ public static Enumerator enumerator(final F> successor, final F> predecessor, final Option max, final Option min, final Ord order) { return new Enumerator<>(successor, predecessor, max, min, order, curry((a, l) -> { if (l == 0L) return some(a); else if (l < 0L) { A aa = a; for (long x = l; x < 0; x++) { final Option s = predecessor.f(aa); if (s.isNone()) return none(); else aa = s.some(); } return some(aa); } else { A aa = a; for (long x = l; x > 0; x--) { final Option s = successor.f(aa); if (s.isNone()) return none(); else aa = s.some(); } return some(aa); } })); } /** * An enumerator for boolean. */ public static final Enumerator booleanEnumerator = enumerator( b -> b ? Option.none() : some(true), b -> b ? some(false) : Option.none(), some(true), some(false), booleanOrd ); /** * An enumerator for byte. */ public static final Enumerator byteEnumerator = enumerator( b -> b == Byte.MAX_VALUE ? Option.none() : some((byte) (b + 1)), b -> b == Byte.MIN_VALUE ? Option.none() : some((byte) (b - 1)), some(Byte.MAX_VALUE), some(Byte.MIN_VALUE), byteOrd ); /** * An enumerator for char. */ public static final Enumerator charEnumerator = enumerator( c -> c == Character.MAX_VALUE ? Option.none() : some((char) (c + 1)), c -> c == Character.MIN_VALUE ? Option.none() : some((char) (c - 1)), some(Character.MAX_VALUE), some(Character.MIN_VALUE), charOrd ); /** * An enumerator for double. */ public static final Enumerator doubleEnumerator = enumerator( d -> d == Double.MAX_VALUE ? Option.none() : some(d + 1D), d -> d == Double.MIN_VALUE ? Option.none() : some(d - 1D), some(Double.MAX_VALUE), some(Double.MIN_VALUE), doubleOrd ); /** * An enumerator for float. */ public static final Enumerator floatEnumerator = enumerator( f -> f == Float.MAX_VALUE ? Option.none() : some(f + 1F), f -> f == Float.MIN_VALUE ? Option.none() : some(f - 1F), some(Float.MAX_VALUE), some(Float.MIN_VALUE), floatOrd ); /** * An enumerator for int. */ public static final Enumerator intEnumerator = enumerator( i -> i == Integer.MAX_VALUE ? Option.none() : some(i + 1), i -> i == Integer.MIN_VALUE ? Option.none() : some(i - 1), some(Integer.MAX_VALUE), some(Integer.MIN_VALUE), intOrd ); /** * An enumerator for BigInteger. */ public static final Enumerator bigintEnumerator = enumerator( i -> some(i.add(BigInteger.ONE)), i -> some(i.subtract(BigInteger.ONE)), Option.none(), Option.none(), bigintOrd, curry((i, l) -> some(i.add(BigInteger.valueOf(l)))) ); /** * An enumerator for BigDecimal. */ public static final Enumerator bigdecimalEnumerator = enumerator( i -> some(i.add(BigDecimal.ONE)), i -> some(i.subtract(BigDecimal.ONE)), Option.none(), Option.none(), bigdecimalOrd, curry((d, l) -> some(d.add(BigDecimal.valueOf(l)))) ); /** * An enumerator for long. */ public static final Enumerator longEnumerator = enumerator( i -> i == Long.MAX_VALUE ? Option.none() : some(i + 1L), i -> i == Long.MIN_VALUE ? Option.none() : some(i - 1L), some(Long.MAX_VALUE), some(Long.MIN_VALUE), longOrd ); /** * An enumerator for short. */ public static final Enumerator shortEnumerator = enumerator( i -> i == Short.MAX_VALUE ? Option.none() : some((short) (i + 1)), i -> i == Short.MIN_VALUE ? Option.none() : some((short) (i - 1)), some(Short.MAX_VALUE), some(Short.MIN_VALUE), shortOrd ); /** * An enumerator for Ordering. */ public static final Enumerator orderingEnumerator = enumerator( o -> o == LT ? some(EQ) : o == EQ ? some(GT) : Option.none(), o -> o == GT ? some(EQ) : o == EQ ? some(LT) : Option.none(), some(GT), some(LT), orderingOrd ); /** * An enumerator for Natural */ public static final Enumerator naturalEnumerator = enumerator( n -> some(n.succ()), Natural::pred, Option.none(), some(Natural.ZERO), naturalOrd, curry((n, l) -> some(n).apply( Natural.natural(l).map(curry((n1, n2) -> n1.add(n2))) ) ) ); }