package haskell.prelude;

import haskell.lang.Class;

/**
 * class Functor f
 */
public interface Functor<A, F extends Functor<A, F>>
        extends Class<F> {

    abstract class Support
            <A, B, FA extends Functor<A, FA>, FB extends Functor<B, FB>> {

        /**
         * fmap :: (a -> b) -> f a -> f b
         */
        public final Function2<Function<A, B>, FA, FB> fmap() {
            return new Function2<Function<A, B>, FA, FB>("fmap") {
                @Override
                public FB apply(final Function<A, B> f, final FA x) {
                    return fmap(f, x);
                }
            };
        }

        public abstract FB fmap(Function<A, B> f, FA x);

    }

}
