lang: add some monads examples

This commit is contained in:
Thibaud Gasser 2020-01-27 21:51:35 +01:00
parent c5ea09d09d
commit 9f1881fb08
5 changed files with 175 additions and 0 deletions

View File

@ -0,0 +1,13 @@
package monads;
import java.util.function.Function;
public interface Monad<T> {
static <U> Monad<U> unit(U value) {
return null;
}
<U> Monad<U> flatMap(Function<T, Monad<U>> mapper);
default <U> Monad<U> map(Function<T, U> mapper) {
return flatMap(t -> unit(mapper.apply(t)));
}
}

View File

@ -0,0 +1,69 @@
package monads;
import java.util.Optional;
import static monads.util.OptionalUtils.optionalAdd;
public class OptionalExamples {
private final Soundcard soundcard;
private final Computer computer;
private final USB usb;
public OptionalExamples() {
usb = new USB("3.1");
soundcard = new Soundcard(usb);
computer = new Computer(soundcard);
}
private void nestedOptional() {
System.out.println("Nested optionals example");
var version = computer.getSoundcard()
.flatMap(Soundcard::getUSB)
.map(USB::getVersion)
.orElse("UNKNOWN");
System.out.printf("Version : %s%n", version);
}
private void addOptionals() {
System.out.println("Add optionals example");
assert optionalAdd(Optional.of(1), Optional.of(1)).equals(Optional.of(2));
assert optionalAdd(Optional.of(1), Optional.of(1)).equals(Optional.empty());
}
public static void main(String[] args) {
var examples = new OptionalExamples();
examples.nestedOptional();
examples.addOptionals();
}
private static class Computer {
private final Soundcard soundcard;
private Computer(Soundcard soundcard) {
this.soundcard = soundcard;
}
public Optional<Soundcard> getSoundcard() { return Optional.ofNullable(soundcard); }
}
private static class Soundcard {
private final USB usb;
private Soundcard(USB usb) {
this.usb = usb;
}
public Optional<USB> getUSB() { return Optional.ofNullable(usb); }
}
private static class USB {
private final String version;
private USB(String version) {
this.version = version;
}
public String getVersion(){ return version; }
}
}

View File

@ -0,0 +1,37 @@
package monads;
public class ResultExamples {
public static void main(String[] args) {
// var ok = Result.ok();
}
private static class Result<T> {
private final T value;
private final String error;
private Result(T value, String error) {
this.value = value;
this.error = error;
}
public static <U> Result<U> ok(U value) {
return new Result<>(value, null);
}
public static <U> Result<U> error(String error) {
return new Result<>(null, error);
}
public boolean isError() {
return error != null;
}
public String getError() {
return error;
}
public T getValue() {
return value;
}
}
}

View File

@ -0,0 +1,33 @@
package monads;
import java.util.stream.Stream;
public class StreamExamples {
/**
* Given n > 0 find all pairs (i; j) where
* 1 < j <= i <= n and i + j is prime
*/
private Stream<long[]> findPrimes(long n) {
return Stream.iterate(1, i -> i + 1)
.limit(n)
.flatMap(i -> Stream.iterate(1, j -> j + 1)
.limit(n)
.map(j -> new long[] {i, j})
).filter(pair -> isPrime(pair[0] + pair[1]));
}
private boolean isPrime(long n) {
return Stream.iterate(2, i -> i + 1)
.limit((long) Math.sqrt(n))
.noneMatch(i -> n % i == 0);
}
public static void main(String[] args) {
StreamExamples examples = new StreamExamples();
var start = System.nanoTime();
var primes = (Long) examples.findPrimes(10L).count();
var end = System.nanoTime();
System.out.printf("Elapsed : %fs", (end - start) / 1_000_000_000.0);
//primes.map(Arrays::toString).forEach(System.out::println);
}
}

View File

@ -0,0 +1,23 @@
package monads.util;
import java.util.Optional;
import java.util.function.BiFunction;
public final class OptionalUtils {
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
public static Optional<Integer> optionalAdd(Optional<Integer> val1, Optional<Integer> val2) {
return flatMap2(val1, val2, (first, second) -> Optional.of(first + second));
}
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
public static <T, U, R> Optional<R> flatMap2(
Optional<T> opt1,
Optional<U> opt2,
BiFunction<T, U, Optional<R>> mapper
) {
return opt1.flatMap(a ->
opt2.flatMap(b ->
mapper.apply(a, b)
));
}
}