// Path: a-foundation/src/main/java/com/ajjpj/afoundation/function/AFunction1.java
// public interface AFunction1<P, R, E extends Throwable> extends Serializable {
//     R apply(P param) throws E;
// }
// 
// Path: a-foundation/src/main/java/com/ajjpj/afoundation/function/APartialFunction.java
// public interface APartialFunction<P, R, E extends Throwable> extends AFunction1<P, R, E> {
//     boolean isDefinedAt (P param);
// }
// 
// Path: a-foundation/src/main/java/com/ajjpj/afoundation/function/APredicate.java
// public interface APredicate<T,E extends Throwable> extends Serializable {
//     boolean apply(T o) throws E;
// }


import com.ajjpj.afoundation.collection.AEquality;
import com.ajjpj.afoundation.function.AFunction1;
import com.ajjpj.afoundation.function.APartialFunction;
import com.ajjpj.afoundation.function.APredicate;
import java.util.Collection;
package com.ajjpj.afoundation.collection.immutable;




/**
 * This interface contains methods provided by all a-base collections. Implementing <code>Iterable</code> allows
 *  collections to be used with Java's <code>for(....: collection)</code> syntax introduced with version 1.5.<p>
 *
 * The first generic parameter T represents the collection's element type, while the second parameter represents
 *  the concrete collection class.
 *
 * @author arno
 */
public interface ACollection<T> extends ATraversable<T>, Iterable<T> {
    /**
     * @return an empty {@link ACollection} of the same size as this one.
     */
    ACollection<T> clear();

    /**
     * @return the number of elements in this {@link ACollection}.
     */
    int size();

    /**
     * @return true if and only if this collection's size is 0
     */
    boolean isEmpty();

    /**
     * @return true if and only if this collection's size is greater than 0
     */
    boolean nonEmpty();

    /**
     * This method checks if the collection has an element that is 'equal' to the parameter {@code el}. For collections
     *  that have a configurable {@link com.ajjpj.afoundation.collection.AEquality}, that equality is used to check
     *  containment. This applies to {@link ASet} instances in particular.
     */
    boolean contains (T el);

    /**
     * Filters this collection's elements, this method returns a new collection comprised of only those elements that match
     *  a given predicate.
     */
    @Override <E extends Throwable> ACollection<T> filter(APredicate<? super T, E> pred) throws E;

    /**
     * Filters this collection's elements, this method returns a new collection comprised of only those elements that do not match
     *  a given predicate.
     */
    @Override <E extends Throwable> AMonadicOps<T> filterNot (APredicate<? super T, E> pred) throws E;

    @Override <X, E extends Throwable> ACollection<X> map(AFunction1<? super T, ? extends X, E> f) throws E;
    @Override <X, E extends Throwable> ACollection<X> flatMap(AFunction1<? super T, ? extends Iterable<X>, E> f) throws E;

    /**
     * Turns a collection of collections into a 'flat' collection, removing one layer of collections.
     */
    <X> ACollection<X> flatten();

// Path: a-foundation/src/main/java/com/ajjpj/afoundation/function/AFunction1.java
// public interface AFunction1<P, R, E extends Throwable> extends Serializable {
//     R apply(P param) throws E;
// }
// 
// Path: a-foundation/src/main/java/com/ajjpj/afoundation/function/APartialFunction.java
// public interface APartialFunction<P, R, E extends Throwable> extends AFunction1<P, R, E> {
//     boolean isDefinedAt (P param);
// }
// 
// Path: a-foundation/src/main/java/com/ajjpj/afoundation/function/APredicate.java
// public interface APredicate<T,E extends Throwable> extends Serializable {
//     boolean apply(T o) throws E;
// }


// Path: a-foundation/src/main/java/com/ajjpj/afoundation/collection/immutable/ACollection.java
import com.ajjpj.afoundation.collection.AEquality;
import com.ajjpj.afoundation.function.AFunction1;
import com.ajjpj.afoundation.function.APartialFunction;
import com.ajjpj.afoundation.function.APredicate;
import java.util.Collection;

package com.ajjpj.afoundation.collection.immutable;




/**
 * This interface contains methods provided by all a-base collections. Implementing <code>Iterable</code> allows
 *  collections to be used with Java's <code>for(....: collection)</code> syntax introduced with version 1.5.<p>
 *
 * The first generic parameter T represents the collection's element type, while the second parameter represents
 *  the concrete collection class.
 *
 * @author arno
 */
public interface ACollection<T> extends ATraversable<T>, Iterable<T> {
    /**
     * @return an empty {@link ACollection} of the same size as this one.
     */
    ACollection<T> clear();

    /**
     * @return the number of elements in this {@link ACollection}.
     */
    int size();

    /**
     * @return true if and only if this collection's size is 0
     */
    boolean isEmpty();

    /**
     * @return true if and only if this collection's size is greater than 0
     */
    boolean nonEmpty();

    /**
     * This method checks if the collection has an element that is 'equal' to the parameter {@code el}. For collections
     *  that have a configurable {@link com.ajjpj.afoundation.collection.AEquality}, that equality is used to check
     *  containment. This applies to {@link ASet} instances in particular.
     */
    boolean contains (T el);

    /**
     * Filters this collection's elements, this method returns a new collection comprised of only those elements that match
     *  a given predicate.
     */
    @Override <E extends Throwable> ACollection<T> filter(APredicate<? super T, E> pred) throws E;

    /**
     * Filters this collection's elements, this method returns a new collection comprised of only those elements that do not match
     *  a given predicate.
     */
    @Override <E extends Throwable> AMonadicOps<T> filterNot (APredicate<? super T, E> pred) throws E;

    @Override <X, E extends Throwable> ACollection<X> map(AFunction1<? super T, ? extends X, E> f) throws E;
    @Override <X, E extends Throwable> ACollection<X> flatMap(AFunction1<? super T, ? extends Iterable<X>, E> f) throws E;

    /**
     * Turns a collection of collections into a 'flat' collection, removing one layer of collections.
     */
    <X> ACollection<X> flatten();

    @Override <X, E extends Throwable> ACollection<X> collect (APartialFunction<? super T, ? extends X, E> pf) throws E;