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

net.sf.staccatocommons.control.monad.Monads Maven / Gradle / Ivy

The newest version!
/*
 Copyright (c) 2011, The Staccato-Commons Team

 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU Lesser General Public License as published by
 the Free Software Foundation; version 3 of the License.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU Lesser General Public License for more details.
 */
package net.sf.staccatocommons.control.monad;

import java.util.Arrays;
import java.util.Iterator;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;

import net.sf.staccatocommons.control.monad.internal.BlockingMonadValue;
import net.sf.staccatocommons.control.monad.internal.IteratorMonadValue;
import net.sf.staccatocommons.control.monad.internal.NilMonad;
import net.sf.staccatocommons.control.monad.internal.SingleMonadValue;
import net.sf.staccatocommons.control.monad.internal.SubmitMonadValue;
import net.sf.staccatocommons.defs.Applicable;
import net.sf.staccatocommons.defs.Evaluable;
import net.sf.staccatocommons.defs.Executable;
import net.sf.staccatocommons.defs.ProtoMonad;
import net.sf.staccatocommons.defs.tuple.Tuple2;
import net.sf.staccatocommons.lang.Option;
import net.sf.staccatocommons.lang.function.Functions;
import net.sf.staccatocommons.lang.tuple.Tuples;
import net.sf.staccatocommons.restrictions.Constant;
import net.sf.staccatocommons.restrictions.check.NonNull;
import net.sf.staccatocommons.restrictions.processing.IgnoreRestrictions;

/**
 * Simple {@link Monad}s and {@link MonadicFunction}s
 * 
 * @author flbulgarelli
 * @since 1.2
 */
public class Monads {

  /**
   * Answers a {@link Monad} that wraps a single element. Evaluating this monad
   * has no effect
   * 
   * @param element
   *          the element to wrap
   * @return a monad that wraps the given element
   */
  public static  Monad cons(A element) {
    return from(new SingleMonadValue(element));
  }

  /**
   * Answers a {@link Monad} that wraps an array of elements. Evaluating this
   * monad has no effect
   * 
   * @param elements
   *          the elements to wrap
   * @return a monad that wraps the given array of elements
   */
  public static  Monad from(A... elements) {
    return from(Arrays.asList(elements));
  }

  /**
   * Answers a {@link Monad} that wraps an {@link Iterable} of elements.
   * Evaluating this monad has no effect
   * 
   * @param elements
   *          the elements to wrap
   * @return a monad that wraps the given {@link Iterable} of elements
   */
  public static  Monad from(Iterable elements) {
    Iterator iterator = elements.iterator();
    if (iterator.hasNext())
      return from(new IteratorMonadValue(iterator));
    return nil();
  }

  public static  Monad from(Option element) {
    if (element.isDefined())
      return cons((A) element.value());
    return nil();
  }

  public static  Monad from(BlockingQueue queue) {
    return from(new BlockingMonadValue(queue));
  }

  public static  Monad from(MonadicValue monadValue) {
    return new UnboundMonad(monadValue);
  }

  /**
   * The async {@link Monad}
   * 
   * @param 
   * @param executor
   * @param callable
   * @return
   */
  public static  Monad async(final ExecutorService executor, Callable callable) {
    return from(new SubmitMonadValue(executor, callable));
  }

  /**
   * The Empty Monad, that is, the monad that has no elements to visit and has
   * no side effect. Binding the nil monad always results in the nil monad
   * 
   * @param 
   * @return the constant empty {@link Monad}
   */
  @Constant
  public static  Monad nil() {
    return new NilMonad();
  }

  /**
   * Answers a {@link MonadicFunction} that performs mapping using the given
   * mapping function
   * 
   * @param function
   * @return a new {@link MonadicFunction} that performs mapping, as defined in
   *         {@link ProtoMonad#map(Applicable)}
   */
  public static  MonadicFunction map(
    @NonNull final Applicable function) {
    return new AbstractMonadicFunction() {
      public Monad apply(A arg) {
        return Monads.cons((B) function.apply(arg));
      }
    };
  }

  /**
   * Answers a {@link MonadicFunction} that performs filtering using the given
   * filtering function
   * 
   * @param function
   * @return a new {@link MonadicFunction} that performs filtering, as defined
   *         in {@link ProtoMonad#filter(Applicable)}
   */
  public static  MonadicFunction filter(@NonNull final Evaluable predicate) {
    return new AbstractMonadicFunction() {
      public Monad apply(A arg) {
        if (predicate.eval(arg))
          return Monads.cons(arg);
        return Monads.nil();
      }
    };
  }

  /**
   * Answers a {@link MonadicFunction} that executes an actions with effect
   * using the given {@code block}
   * 
   * @param block
   * @return a new {@link MonadicFunction}
   */
  @IgnoreRestrictions
  public static  MonadicFunction each(@NonNull final Executable block) {
    return map(Functions.impure(block));
  }

  /**
   * Answers a {@link MonadicFunction} that performs
   * {@link Tuples#clone(Applicable)} using the given {@code function}
   * 
   * @param function
   * @return a new {@link MonadicFunction} that performs cloning
   */
  @IgnoreRestrictions
  public static  MonadicFunction> clone(
    final Applicable function) {
    return map(Tuples.clone(function));
  }

  /**
   * Answers a {@link MonadicFunction} that performs
   * {@link Tuples#branch(Applicable)} using the given {@code function}
   * 
   * @param function
   * @return a new {@link MonadicFunction} that performs branching
   */
  @IgnoreRestrictions
  public static  MonadicFunction> branch(
    final Applicable function0,
    final Applicable function1) {
    return map(Tuples.branch(function0, function1));
  }

  /**
   * The async Monad function
   * 
   * @param 
   * @param executor
   * @return
   */
  public static  MonadicFunction async(final ExecutorService executor) {
    return new AbstractMonadicFunction() {
      public Monad apply(final A arg) {
        return Monads.async(executor, new Callable() {
          public A call() throws Exception {
            return arg;
          }
        });
      }
    };
  }

  public static  MonadicFunction cons() {
    return new AbstractMonadicFunction() {
      public Monad apply(A arg) {
        return Monads.cons(arg);
      }
    };
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy