Java 8 Examples

These examples use the Java 8 syntax. Corresponding examples are also available in Java 7 and the original proposed BGGA syntax.

The example list is:

Array Exists

Checks for the existence of a String that has all lower case characters. In this case it is true (since, the case of "what"), but without this specific case, it is false. This example uses List.forall to test the characters of the String.

import fj.data.Array;
import static fj.data.Array.array;
import static fj.data.List.fromString;
import static fj.function.Characters.isLowerCase;

public final class Array_exists {
    public static void main(final String[] args) {
        final Array<String> a = array("Hello", "There", "what", "DAY", "iS", "iT");
        final boolean b = a.exists(s -> fromString(s).forall(isLowerCase));
        System.out.println(b); // true ("what" is the only value that qualifies; try removing it)
    }
}

Array Filter

Removes elements from an array that do not meet a certain criteria. In this case, we are using an array of integers and the filter removes any odd numbers.

import fj.data.Array;
import static fj.data.Array.array;
import static fj.Show.arrayShow;
import static fj.Show.intShow;
import static fj.function.Integers.even;

public final class Array_filter {
    public static void main(final String[] args) {
        final Array<Integer> a = array(97, 44, 67, 3, 22, 90, 1, 77, 98, 1078, 6, 64, 6, 79, 42);
        final Array<Integer> b = a.filter(even);
        final Array<Integer> c = a.filter(i -> i % 2 == 0);
        arrayShow(intShow).println(b); // {44,22,90,98,1078,6,64,6,42}
    }
}

Array Fold Left

Reduces the list applying a function per element. In this case, the fold sums the elements with a starting value of 0. Since 0 + 97 + 44 + 67 + 3 + 22 + 90 + 1 + 77 + 98 + 1078 + 6 + 64 + 6 + 79 + 42 == 1774 the result of the fold is 1774.

import fj.F;
import fj.data.Array;
import static fj.data.Array.array;
import static fj.function.Integers.add;

public final class Array_foldLeft {
    public static void main(final String[] args) {
        final Array<Integer> a = array(97, 44, 67, 3, 22, 90, 1, 77, 98, 1078, 6, 64, 6, 79, 42);
        final int b = a.foldLeft(add, 0);

        F<Integer, F<Integer, Integer>> add2 = i -> (j -> i + j);
        final int c = a.foldLeft(add2, 0);
        System.out.println(b); // 1774
    }
}

Array For All

Checks that all Strings in the array have lower case characters. In this case, the check fails because of the case of "There", however, the removal of this case produces a result of true.

import fj.data.Array;
import static fj.data.Array.array;
import static fj.data.List.fromString;
import static fj.function.Characters.isLowerCase;

public final class Array_forall {
    public static void main(final String[] args) {
        final Array<String> a = array("hello", "There", "what", "day", "is", "it");
        final boolean b = a.forall(s -> fromString(s).forall(isLowerCase));
        System.out.println(b); // false ("There" is a counter-example; try removing it)
    }
}

Array Map

Maps a function across the array of integers. In this case, the function adds 42 to each element of the array to produce a new array.

import fj.data.Array;
import static fj.data.Array.array;
import static fj.function.Integers.add;
import static fj.Show.arrayShow;
import static fj.Show.intShow;

public final class Array_map {
    public static void main(final String[] args) {
        final Array<Integer> a = array(1, 2, 3);
        final Array<Integer> b = a.map(add.f(42));
        final Array<Integer> c = a.map(i -> i + 42);
        arrayShow(intShow).println(b); // {43,44,45}
        arrayShow(intShow).println(c); // {43,44,45}
    }
}

List Map

Maps a function across a list of integers. This is similar to the Array map. This example adds 42 to each element of the list to produce a new list.

import fj.data.List;
import static fj.data.List.list;
import static fj.function.Integers.add;
import static fj.Show.intShow;
import static fj.Show.listShow;

public final class List_map {
    public static void main(final String[] args) {
        final List<Integer> a = list(1, 2, 3);
        final List<Integer> b = a.map(add.f(42));
        final List<Integer> c = a.map(i -> i = 42);
        listShow(intShow).println(b); // [43,44,45]
    }
}

Option Bind

Binds a function across the optional value type. The function checks if the contained value is even and if it is multiples that value by 3 and returns that new value. If the contained value is odd (or if there is no value), then no value is returned (none).

import fj.F;
import fj.data.Option;
import static fj.Show.intShow;
import static fj.Show.optionShow;
import static fj.data.Option.none;
import static fj.data.Option.some;

public final class Option_bind {
    public static void main(final String[] args) {
        final Option<Integer> o1 = some(7);
        final Option<Integer> o2 = some(8);
        final Option<Integer> o3 = none();

        F<Integer, Option<Integer>> f = i -> i % 2 == 0 ? some(i * 3) : none();
        final Option<Integer> o4 = o1.bind(f);
        final Option<Integer> o5 = o2.bind(f);
        final Option<Integer> o6 = o3.bind(f);

        optionShow(intShow).println(o4); // None
        optionShow(intShow).println(o5); // Some(24)
        optionShow(intShow).println(o6); // None
    }
}

Option filter

Removes the value from the optional value if it does not match a given predicate. In this case the condition for preservation is that the contained value is an even number

import fj.F;
import fj.data.Option;
import static fj.Show.intShow;
import static fj.Show.optionShow;
import static fj.data.Option.none;
import static fj.data.Option.some;
import static fj.function.Integers.even;

public final class Option_filter {
    public static void main(final String[] args) {
        final Option<Integer> o1 = some(7);
        final Option<Integer> o2 = none();
        final Option<Integer> o3 = some(8);

        final Option<Integer> o4 = o1.filter(even);
        final Option<Integer> o5 = o2.filter(even);
        final Option<Integer> o6 = o3.filter(even);

        F<Integer, Boolean> f = i -> i % 2 == 0;
        final Option<Integer> o7 = o1.filter(f);
        final Option<Integer> o8 = o1.filter(f);
        final Option<Integer> o9 = o1.filter(i -> i % 2 == 0);

        optionShow(intShow).println(o4); // None
        optionShow(intShow).println(o5); // None
        optionShow(intShow).println(o6); // Some(8)
    }
}

Option Map

Maps a function across the optional value type. The function adds 42 to any contained value.

import fj.data.Option;
import static fj.Show.intShow;
import static fj.Show.optionShow;
import static fj.data.Option.none;
import static fj.data.Option.some;
import static fj.function.Integers.add;

public final class Option_map {
    public static void main(final String[] args) {
        final Option<Integer> o1 = some(7);
        final Option<Integer> o2 = none();
        final Option<Integer> p1 = o1.map(add.f(42));
        final Option<Integer> p2 = o2.map(add.f(42));

        final Option<Integer> p3 = o1.map(i -> i + 42);
        final Option<Integer> p4 = o2.map(i -> i + 42);

        optionShow(intShow).println(p1); // Some(49)
        optionShow(intShow).println(p2); // None
    }
}

IO Walkthrough

Demonstrates how to work with the IO type.

// IO is just a container to defer a computation (lazy), with the intention
// to encapsulate computations that either consume and/or produce side-effects
// the computation is not (yet) executed on creation hence it can be treated
// like a value

final IO<Unit> askName = () -> {
    System.out.println("Hi, what's your name?");
    return Unit.unit();
};

// fj.data.IOFunctions contains a lot of convenience functions regarding IO, the
// above example could be rewritten with IOFunctions.stdoutPrintln
// we now create an IO value to prompt for the name if executed

IO<Unit> promptName = IOFunctions.stdoutPrint("Name: ");

// we can compose these two values with fj.data.IOFunctions.append, since they
// both are not interested in any runtime value

IO<Unit> askAndPromptName = IOFunctions.append(askName, promptName);

// now we create an IO value to read a line from stdin

final IO<String> readName = () -> new BufferedReader(new InputStreamReader(System.in)).readLine();

// this is the same as IOFunctions.stdinReadLine()

// now we create a function which takes a string, upper cases it and creates
// an IO value that would print the upper cased string if executed

final F<String, IO<Unit>> upperCaseAndPrint = F1Functions.<String, IO<Unit>, String>o(IOFunctions::stdoutPrintln).f(String::toUpperCase);

// we now want to compose reading the name with printing it, for that we need to
// have access to the runtime value that is returned when the
// IO value for read is executed, hence we use fj.data.IOFunctions.bind instead
// of fj.data.IOFunctions.append

final IO<Unit> readAndPrintUpperCasedName = IOFunctions.bind(readName, upperCaseAndPrint);

// so append is really just a specialised form of bind, ignoring the runtime
// value of the IO execution that was composed before us

final IO<Unit> program = IOFunctions.bind(askAndPromptName, ignored -> readAndPrintUpperCasedName);

// this is the same as writing IOFunctions.append(askAndPromptName, readAndPrintUpperCasedName)

// we have recorded the entire program, but have not run anything yet
// now we get to the small dirty part at the end of our program where we actually
// execute it

// we can either choose to just call program.run(), which allows the execution to escape
// or we use safe to receive an fj.data.Either with the potential exception on the
// left side

toSafeValidation(program).run().on((IOException e) -> { e.printStackTrace(); return Unit.unit(); });

// doing function composition like this can be quite cumbersome, since you will end
// up nesting parenthesis unless you flatten it out by
// assigning the functions to variables like above, but you can use the fj.F1W
// syntax wrapper for composing single-argument functions and fj.data.IOW
// for composing IO values instead, the entire program can be written like so:

IOW.lift(stdoutPrintln("What's your name again?"))
        .append(stdoutPrint("Name: "))
        .append(stdinReadLine())
        .bind(F1W.lift((String s) -> s.toUpperCase())
        .andThen(IOFunctions::stdoutPrintln))
        .safe().run().on((IOException e) -> { e.printStackTrace(); return Unit.unit(); });