001    package fj;
002    
003    import static fj.Unit.unit;
004    
005    /**
006     * Represents a side-effect.
007     *
008     * @version %build.number%<br>
009     *          <ul>
010     *          <li>$LastChangedRevision: 122 $</li>
011     *          <li>$LastChangedDate: 2009-04-25 08:24:38 +1000 (Sat, 25 Apr 2009) $</li>
012     *          </ul>
013     */
014    public interface Effect<A> {
015      void e(A a);
016    
017      /**
018       * A projection of an effect. The methods defined on a projection may belong on an effect,
019       * however, this would disallow the use of {@link Effect} to be used with Java 7 closure syntax.
020       */
021      @SuppressWarnings({"InnerClassOfInterface"})
022      final class Projection {
023        private Projection() {
024          throw new UnsupportedOperationException();
025        }
026    
027        /**
028         * Returns an effect for the given function.
029         *
030         * @param f The function to produce the effort with.
031         * @return The effect using the given function.
032         */
033        public static <A> Effect<A> f(final F<A, Unit> f) {
034          return new Effect<A>() {
035            public void e(final A a) {
036              f.f(a);
037            }
038          };
039        }
040    
041        /**
042         * Returns a function for the given effect.
043         *
044         * @param e The effect to produce the function with.
045         * @return The function using the given effect.
046         */
047        public static <A> F<A, Unit> e(final Effect<A> e) {
048          return new F<A, Unit>() {
049            public Unit f(final A a) {
050              e.e(a);
051              return unit();
052            }
053          };
054        }
055    
056        /**
057         * A contra-variant functor on effect.
058         *
059         * @param e The effect to map over.
060         * @param f The function to map over the effect.
061         * @return An effect after a contra-variant map.
062         */
063        public static <A, B> Effect<B> comap(final Effect<A> e, final F<B, A> f) {
064          return new Effect<B>() {
065            public void e(final B b) {
066              e.e(f.f(b));
067            }
068          };
069        }
070      }
071    }