I’m creating yet another functional java library, called jFunc. Why would I do such a thing, we already have cycylops-react and highj why would i waste my time creating another one. A better question is why not, and maybe an even better question would be why don’t we just all program in haskell. But it began by me just trying to grasp concepts in haskell and the funcitonal paradiams presented there in. This is my attempt at making useful documentation for jFunc.

Star

Fork

jFunc is a functional java library by functional I mean the libray containes data types that are immutable and lazy. Along with lots of tools to create composble operations and functions.

Persistent Data Structures

FList

FList is immutable and Lazy, FList is analogous to a stream of values.

Becuase FList is lazy we can create infinite list of elements. The below example is an infinite lists of even numbers.

  FList<Integer> evenNumber = start(2).filter(i -> i % 2 == 0);

Below is an example of creating an infite list of prime numbers.

  public static boolean isPrime(Integer i) {
   final int sqrtOfi = (int)Math.sqrt(i);
   return allTrueWhile(primes, p -> p <= sqrtOfi
       , p -> i % p != 0);
  }

  public static FList<Integer> primes = flist(2, 3, () -> start(4).filter(Numbers::isPrime));

  print(primes.take(12)); //[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37]

DList

DList also known as a difference list support constant time append, unlike FList where append is O(n) where n is the numbr of elements in the FList.

If an algorithm builds a list by appending smaller lists repeatdly then DList can greatly improve performnace.

Either

Either is paramatized by two types. Each parameter represents a possible value that the Either can hold, so a Either<L,R> can contain a value of type L (the left value) or a value of type R (the right value).

The Either type is vary useful for describing computation that can return one of two possible values, makeing it very useful for error handling.

In the below code userRead checks a if a username exists, returning a type of Either<Exception,User>. If the the user name ecautally exist then the either contains a User otherwise it contains an Exception.

  @POST
  @Path("/login")
  @Produces(MediaType.APPLICATION_JSON)
  public Response getToken(Login login) {

    EntityManger em = getEntityManager();

    Either<Exception, User> userRead =
      read(User.class, login.username)
        .runAndClose(em);

    Either<Response, Response> response =
      userRead.bimap(forbidden,validate.call(login))

    return either(response);
  }

bimap(F1<L,A> left, F1<R,B> right) maps the two given functions to the contains of the either the function the is mapped over the contnents of the eiterh depened on if the either has a left value or a right value.

forbidden and validate both return a type of Response because of this we can use either(Either<R,R> either) either return the left or right value within an either, we can use either when the left and right value are the same type. Theres no need to inspect the content of the either since we transform the left and right sie of the either into the approritea reposone.

  public static F1<Excpetion,Response> forbidden = 
    e -> Response.status(Response.Status.FORBIDDEN).entity(new ErrorResponse(e.getMessage())).build();
  public static F2<Login,User,Response> validate =
    (l,u) -> {
      String ps = u.getPassword();
      if (ps.equals(l.password)) {
        return Response.ok().entity(tokenGen(u)).build();
      } else {
        return Response.status(Response.Status.UNAUTHORIZED).build();
      }
    };

Maybe

Maybe is a control structure that repesent a value that is something or nothing. We can refactor functions that may return null with Maybe.

  public static F2<Integer, Integer, Maybe<Integer>> div = (num, den) ->  {
    if(den == 0)
      return Maybe.noting();
    else
      return Maybe.maybe(num / den);
  }

Because dividing by zero would result in an error we may return a Maybe containing nothing. We can bind and map over the returned Maybe to manipulate the possible value within the value.

  publilc static F2<Integer, Integer> double = i -> 2 * i;

  Maybe<Integer> num = div.call(4, 2);
  num.map(double); // Maybe 4

  num = div.call(4, 0);
  num.map(double); // Nothing

Tuples

Similar to FList Tuples are a sequence of values unlike FList a tuple is heterogenous and has a fixed length. jFunc’s Tuples may have a size of 2 to 8(T2, T3, T4, T5, T6, T7, T8)

Map TODO


Functions

F0-F8

jFunc has functional interfaces for functions from arity 0 to 8(F0, F1,F2, F3, F4, F5, F6, F7, F8). all functions can be paritablly applied.


F2<Integer, Integer, Integer> add = (i, i1) -> i + i1;

F1<Integer,Integer> add3 = add.call(3);

F1<Integer,Integer> add4 = add.call(4);

Integer seven = add3.call(0) + add4.call(0);

Integer seven$ = add.call(3,4);

//seven == seven$


P1-P8

jFunc contains functional interface for functins that speciifcally return boolean values. These interfaces are called predicates(P1, P2, P3, P4, P5, P6, P7, P8). P1 is a predicate of arity one, P2 is a pridctaice of arity two and so on.

Trampoline

  public static Trampoline<BigInteger> fib(Integer i) {
    return fib_prime(BigInteger.ZERO, BigInteger.ONE, i);
  }

  public static Trampoline<BigInteger> fib_prime(BigInteger a, BigInteger b, Integer i) {
    if(i == 0) return done(a);
    if(i == 1) return done(b);
    return fib_prime(b, a.add(b), i - 1);
  }
  public static Trampoline<BigInteger> fact(BigInteger n) {
    if(n.equals(BigInteger.ZERO))
      return done(BigInteger.ONE);
    else if(n.equals(BigInteger.ONE))
      return done(BigInteger.ONE);
    else{
      return more(() -> {
        return fact(n.add(BigInteger.ONE.negate())).map(i -> n.multiply(i));
      });
    }
  }

Eval

Eval allows the evaluation of expressions to be derfered, additionall the computed value is cached for later use.

Example To Come


Exception Handling

Try

Try0-Try8

Monads

MaybeT

Example To Come

ReaderT

Example To Come

WriterT

Example To Come

StateT

The StateT monad allows for the threading of some state through a series of functions.

/*
 * Example use of State monad
 * Passes a string of dictionary {a,b,c}
 * Game is to produce a number from the string.
 * By default the game is off, a C toggles the
 * game on and off. A 'a' gives +1 and a b gives -1.
 * E.g 
 * 'ab'    = 0
 * 'ca'    = 1
 * 'cabca' = 0
 * State = game is on or off & current score
 *       = (Boolean, Int)
 */
public static State<T2<Boolean,Integer>, Integer> playGame(FList<Character> s) {
  return CaseOf.caseOf(s)
    .of( FList::isEmpty, () -> State.<T2<Boolean,Integer>>get().bind(t -> ret(t._2())) )
    .otherwise( list -> {
      return State.<T2<Boolean,Integer>>get()
        .bind(t -> {
          boolean on = t._1();
          int score  = t._2();
          return CaseOf.caseOf(list.head())
             .of(eq('a').AND(on), () -> put( T2.t2( on, score + 1) ) )
             .of(eq('b').AND(on), () -> put( T2.t2( on, score - 1) ) )
             .of(eq('c')        , () -> put( T2.t2(!on, score    ) ) )
             .otherwise(          () -> put( T2.t2( on, score    ) ) )
             .semi(playGame(list.tail()));
        });
    });
}
public static void main(String[] args) {
  T2<Boolean,Integer> initState = T2.t2(false,0);
  Integer i = playGame(flist('c', 'a', 'b', 'c', 'a'))
              .evalState(initState);
  System.out.println(i); // 0
}

The above code snippets are translation of Haskell code found here.

ParserT TODO