public interface Mónada<T> {
// unit es un constructor o fábrica estática
public <U> Mónada<U> map(Function<T, U> f);
}
public class Identidad<T> implements Mónada<T> {
private T valor;
private Identidad(final T valor) {
this.valor = valor;
}
public static <T> Identidad<T> of(T valor) {
return new Identidad<>(valor);
}
public <U> Identidad<U> map(Function<T, U> f) {
U nuevo = f.apply(valor);
// No se puede escapar de la Mónada
return Identidad.of(nuevo);
}
public T get() {
return valor;
}
}
Identidad.of("Monads are fun")
.map(String::toUppercase)
.map(s -> s.replace(" ", "-"))
.get(); // MONADS-ARE-FUN
String s = "Monads are fun";
String s1 = s.toUppercase();
String s2 = s1.replace(" ", "-");
// MONADS-ARE-FUN
Idéntico a
Identidad.of("Monads are fun")
.map(s -> s.replace(" ", ""))
.map(String::length)
.get(); // 12
String s = "Monads are fun";
String s1 = s.replace(" ", "");
int length = s1.length();
// 12
Idéntico a
public class Identidad<T> implements Mónada<T> {
public <U> Identidad<U> map(Function<T, U> f) {
U nuevo = f.apply(valor);
// No se puede escapar la Mónada
return Identidad.of(nuevo);
}
public <U> Identidad<U> flatMap(Function<T, Identidad<U>> f) {
Identidad<U> nuevo = f.apply(valor);
return nuevo; // no hay necesidad de envolver en Mónada
}
}
// Identidad Izquierda
String s = "Monads are fun";
String s1 = s.toUppercase();
String s2 = Identidad.of(s)
.map(String::toUppercase)
.get();
assert s1.equals(s2);
// Identidad Derecha
String s = "Monads are fun";
String s1 = Identidad.of(s)
.flatMap(Identidad::of)
.get();
assert s.equals(s1);
// Transitividad
String s = "Monads are fun";
String s1 = Identidad.of(s)
.map(s -> s.toUppercase()
.replace(" ", "-"))
.get();
String s2 = Identidad.of(s)
.map(String::toUppercase)
.map(s -> s.replace(" ", "-")
.get();
assert s1.equals(s2);
public final class Optional<T> {
private static final Optional<?> EMPTY = new Optional<>();
private final T value;
private Optional(T value) {
this.value = Objects.requireNonNull(value);
}
private Optional() {
this.value = null;
}
public static<T> Optional<T> empty() {
return (Optional<T>) EMPTY;
}
public static <T> Optional<T> of(T value) {
return value == null ? empty() : new Optional(value);
}
// más código
}
public final class Optional<T> {
// más código
public boolean isPresent() {
return value != null;
}
public <U> Optional<U> map(Function<T, U> f) {
Objects.requireNonNull(f);
if (!isPresent()) {
return empty();
} else {
return Optional.of(f.apply(value));
}
}
public <U> Optional<U> flatMap(Function<T, Optional<U>> f) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Objects.requireNonNull(f.apply(value));
}
}
}
public final class Optional<T> {
// más código
public Optional<T> filter(Predicate<T> predicate) {
Objects.requireNonNull(predicate);
if (!isPresent()) {
return this;
} else {
return predicate.test(value) ? this : empty();
}
}
public T orElse(T other) {
return isPresent() ? value : other;
}
public T orElseGet(Supplier<T> other) {
return isPresent() ? value : other.get();
}
}