package haskell.prelude;

import haskell.prelude.text.Show;

/**
 * data Either a b = Left a | Right b
 *     deriving (Eq, Ord, Read, Show)
 */
public class Either<A, B>
        extends AbstractOrd<Either<A, B>>
        implements Eq<Either<A, B>>,
                Ord<Either<A, B>>,
                //Read<Either<A, B>>,
                Show<Either<A, B>> {

    final A x;
    final B y;

    Either(final java.lang.String name, final A x, final B y) {
        super(name);
        this.x = x;
        this.y = y;
    }

    /**
     * Left a
     */
    public static <A, B> Function<A, Either<A, B>> Left() {
        return new Function<A, Either<A, B>>("Left") {
            @Override
            public Either<A, B> apply(final A x) {
                return Left(x);
            }
        };
    }

    public static <A, B> Either<A, B> Left(final A x) {
        return new Either<A, B>("Left", x, null);
    }

    public boolean isLeft() {
        return (_left_() != null);
    }

    public A _left_() {
        return eval().x;
    }

    /**
     * Right b
     */
    public static <A, B> Function<B, Either<A, B>> Right() {
        return new Function<B, Either<A, B>>("Right") {
            @Override
            public Either<A, B> apply(final B y) {
                return Right(y);
            }
        };
    }

    public static <A, B> Either<A, B> Right(final B y) {
        return new Either<A, B>("Right", null, y);
    }

    public boolean isRight() {
        return (_right_() != null);
    }

    public B _right_() {
        return eval().y;
    }

    /**
     * either :: (a -> c) -> (b -> c) -> Either a b -> c
     */

    /**
     * either f g (Left  x) = f x
     * either f g (Right y) = g y
     */

    @Override
    protected Eq.Support<Either<A, B>> _Eq_() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    protected Ord.Support<Either<A, B>> _Ord_() {
        // TODO Auto-generated method stub
        return null;
    }

    public int compareTo(Either<A, B> o) {
        // TODO Auto-generated method stub
        return 0;
    }

}
