Commit 792b6d40 authored by pysaumont's avatar pysaumont
Browse files

Replaces subclass methods with abastract parent class ones

parent 05d0ec1f
......@@ -22,6 +22,7 @@ subprojects {
project(':fpinjava-common') {
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.+'
}
}
......
......@@ -5,9 +5,9 @@ public interface Function<T, U> {
U apply(T arg);
default <V> Function<V, U> compose(Function<V, T> f) {
return x -> apply(f.apply(x));
}
default <V> Function<V, U> compose(Function<V, T> f) {
return x -> apply(f.apply(x));
}
default <V> Function<T, V> andThen(Function<U, V> f) {
return x -> f.apply(apply(x));
......
......@@ -26,9 +26,6 @@ public abstract class List<A> {
public abstract <B> B foldLeft(B identity, Function<B, Function<A, B>> f);
public abstract <B> Tuple<B, List<A>> foldLeft(B identity, B zero, Function<B, Function<A, B>> f);
public abstract <B> B foldRight(B identity, Function<A, Function<B, B>> f);
public abstract <B> List<B> map(Function<A, B> f);
public abstract List<A> filter(Function<A, Boolean> f);
public abstract <B> List<B> flatMap(Function<A, List<B>> f);
public abstract A reduce(Function<A, Function<A, A>> f);
public abstract Result<A> headOption();
public abstract Result<List<A>> tailOption();
......@@ -43,6 +40,18 @@ public abstract class List<A> {
public abstract Result<Tuple<A, List<A>>> headAndTail();
public abstract Stream<A> toStream();
public <B> List<B> map(Function<A, B> f) {
return foldRight(list(), h -> t -> new Cons<>(f.apply(h),t));
}
public List<A> filter(Function<A, Boolean> f) {
return foldRight(list(), h -> t -> f.apply(h) ? new Cons<>(h,t) : t);
}
public <B> List<B> flatMap(Function<A, List<B>> f) {
return foldRight(list(), h -> t -> concat(f.apply(h), t));
}
public List<List<A>> choices() {
return subLists().flatMap(List::perms);
}
......@@ -433,21 +442,6 @@ public abstract class List<A> {
return identity;
}
@Override
public <B> List<B> map(Function<A, B> f) {
return list();
}
@Override
public List<A> filter(Function<A, Boolean> f) {
return this;
}
@Override
public <B> List<B> flatMap(Function<A, List<B>> f) {
return list();
}
@Override
public A reduce(Function<A, Function<A, A>> f) {
throw new IllegalStateException(
......@@ -636,23 +630,6 @@ public abstract class List<A> {
return reverse().foldLeft(identity, x -> y -> f.apply(y).apply(x));
}
@Override
public <B> List<B> map(Function<A, B> f) {
return foldRight(list(), h -> t -> new Cons<>(f.apply(h),t));
}
@Override
public List<A> filter(Function<A, Boolean> f) {
return foldRight(list(), h -> t -> f.apply(h) ? new Cons<>(h,t) : t);
}
@Override
public <B> List<B> flatMap(Function<A, List<B>> f) {
/* Java is unable to infer type of the second parameter for the second function */
/* return foldRight(list(), h -> t -> f.apply(h).foldRight(t, x -> (List<B> y) -> new Cons<>(x, y))); */
return foldRight(list(), h -> t -> concat(f.apply(h), t));
}
@Override
public A reduce(Function<A, Function<A, A>> f) {
return this.tail().foldLeft(this.head(), f);
......
......@@ -5,12 +5,17 @@ import com.fpinjava.io.IO;
import java.io.Serializable;
import java.util.concurrent.Callable;
import static com.fpinjava.io.IO.unit;
public abstract class Result<T> implements Serializable {
private Result() {
}
public abstract <U> IO<Result<U>> mapIO(Function<T, IO<U>> f);
public abstract <V> IO<Result<V>> flatMapIO(Function<T, IO<Result<V>>> f);
public abstract Boolean isSuccess();
public abstract Boolean isFailure();
public abstract Boolean isEmpty();
......@@ -40,6 +45,11 @@ public abstract class Result<T> implements Serializable {
return map(x -> this).getOrElse(defaultValue);
}
public static <A> IO<Result<A>> foldLIO(Result<IO<A>> r) {
IO<Result<A>> z = () -> Result.empty();
Function<IO<Result<A>>, Function<IO<A>, IO<Result<A>>>> f = iors -> ios -> iors.flatMap(rs -> ios.flatMap(s -> unit(Result.of(s))));
return r.foldLeft(z,f);
}
public static <T, U> Result<T> failure(Failure<U> failure) {
return new Failure<>(failure.exception);
}
......@@ -191,6 +201,11 @@ public abstract class Result<T> implements Serializable {
public IO<Nothing> tryIO(Function<T, IO<Nothing>> success, Function<String, IO<Nothing>> failure) {
return failure.apply(exception.getMessage());
}
public <U> IO<Result<U>> mapIO(Function<T, IO<U>> f) {
return unit(failure(this));
}
}
private static class Empty<T> extends Result<T> {
......@@ -199,6 +214,11 @@ public abstract class Result<T> implements Serializable {
super();
}
@Override
public <V> IO<Result<V>> flatMapIO(Function<T, IO<Result<V>>> f) {
return null;
}
@Override
public Boolean isSuccess() {
return false;
......@@ -323,6 +343,10 @@ public abstract class Result<T> implements Serializable {
public IO<Nothing> tryIO(Function<T, IO<Nothing>> success, Function<String, IO<Nothing>> failure) {
return failure.apply("Empty Result");
}
public <U> IO<Result<U>> mapIO(Function<T, IO<U>> f) {
return IO.unit(Result.empty());
}
}
private static class Success<T> extends Result<T> {
......@@ -334,6 +358,11 @@ public abstract class Result<T> implements Serializable {
this.value = value;
}
@Override
public <V> IO<Result<V>> flatMapIO(Function<T, IO<Result<V>>> f) {
return null;
}
@Override
public Boolean isSuccess() {
return true;
......@@ -474,6 +503,10 @@ public abstract class Result<T> implements Serializable {
public IO<Nothing> tryIO(Function<T, IO<Nothing>> success, Function<String, IO<Nothing>> failure) {
return success.apply(this.value);
}
public <U> IO<Result<U>> mapIO(Function<T, IO<U>> f) {
return foldLIO( map(f));
}
}
public static <T> Result<T> of(final Callable<T> callable) {
......
......@@ -18,7 +18,10 @@ public abstract class List<A> {
public abstract List<A> init();
public abstract int length();
public abstract <B> B foldLeft(B identity, Function<B, Function<A, B>> f);
public abstract <B> List<B> map(Function<A, B> f);
public <B> List<B> map(Function<A, B> f) {
throw new IllegalStateException("To be implemented");
}
public <B> B foldRight(B identity, Function<A, Function<B, B>> f) {
return reverse().foldLeft(identity, x -> y -> f.apply(y).apply(x));
......@@ -87,11 +90,6 @@ public abstract class List<A> {
public <B> B foldLeft(B identity, Function<B, Function<A, B>> f) {
return identity;
}
@Override
public <B> List<B> map(Function<A, B> f) {
throw new IllegalStateException("To be implemented");
}
}
private static class Cons<A> extends List<A> {
......@@ -186,11 +184,6 @@ public abstract class List<A> {
? ret(acc)
: sus(() -> foldLeft_(f.apply(acc).apply(list.head()), list.tail(), f));
}
@Override
public <B> List<B> map(Function<A, B> f) {
throw new IllegalStateException("To be implemented");
}
}
@SuppressWarnings("unchecked")
......
......@@ -18,8 +18,14 @@ public abstract class List<A> {
public abstract List<A> init();
public abstract int length();
public abstract <B> B foldLeft(B identity, Function<B, Function<A, B>> f);
public abstract <B> List<B> map(Function<A, B> f);
public abstract List<A> filter(Function<A, Boolean> f);
public List<A> filter(Function<A, Boolean> f) {
throw new IllegalStateException("To be implemented");
}
public <B> List<B> map(Function<A, B> f) {
return foldRight(list(), h -> t -> new Cons<>(f.apply(h),t));
}
public <B> B foldRight(B identity, Function<A, Function<B, B>> f) {
return reverse().foldLeft(identity, x -> y -> f.apply(y).apply(x));
......@@ -88,16 +94,6 @@ public abstract class List<A> {
public <B> B foldLeft(B identity, Function<B, Function<A, B>> f) {
return identity;
}
@Override
public <B> List<B> map(Function<A, B> f) {
return list();
}
@Override
public List<A> filter(Function<A, Boolean> f) {
throw new IllegalStateException("To be implemented");
}
}
private static class Cons<A> extends List<A> {
......@@ -192,16 +188,6 @@ public abstract class List<A> {
? ret(acc)
: sus(() -> foldLeft_(f.apply(acc).apply(list.head()), list.tail(), f));
}
@Override
public <B> List<B> map(Function<A, B> f) {
return foldRight(list(), h -> t -> new Cons<>(f.apply(h),t));
}
@Override
public List<A> filter(Function<A, Boolean> f) {
throw new IllegalStateException("To be implemented");
}
}
@SuppressWarnings("unchecked")
......
......@@ -18,9 +18,18 @@ public abstract class List<A> {
public abstract List<A> init();
public abstract int length();
public abstract <B> B foldLeft(B identity, Function<B, Function<A, B>> f);
public abstract <B> List<B> map(Function<A, B> f);
public abstract List<A> filter(Function<A, Boolean> f);
public abstract <B> List<B> flatMap(Function<A, List<B>> f);
public <B> List<B> flatMap(Function<A, List<B>> f) {
throw new IllegalStateException("To be implemented");
}
public List<A> filter(Function<A, Boolean> f) {
return foldRight(list(), h -> t -> f.apply(h) ? new Cons<>(h,t) : t);
}
public <B> List<B> map(Function<A, B> f) {
return foldRight(list(), h -> t -> new Cons<>(f.apply(h),t));
}
public <B> B foldRight(B identity, Function<A, Function<B, B>> f) {
return reverse().foldLeft(identity, x -> y -> f.apply(y).apply(x));
......@@ -89,21 +98,6 @@ public abstract class List<A> {
public <B> B foldLeft(B identity, Function<B, Function<A, B>> f) {
return identity;
}
@Override
public <B> List<B> map(Function<A, B> f) {
return list();
}
@Override
public List<A> filter(Function<A, Boolean> f) {
return this;
}
@Override
public <B> List<B> flatMap(Function<A, List<B>> f) {
throw new IllegalStateException("To be implemented");
}
}
private static class Cons<A> extends List<A> {
......@@ -198,21 +192,6 @@ public abstract class List<A> {
? ret(acc)
: sus(() -> foldLeft_(f.apply(acc).apply(list.head()), list.tail(), f));
}
@Override
public <B> List<B> map(Function<A, B> f) {
return foldRight(list(), h -> t -> new Cons<>(f.apply(h),t));
}
@Override
public List<A> filter(Function<A, Boolean> f) {
return foldRight(list(), h -> t -> f.apply(h) ? new Cons<>(h,t) : t);
}
@Override
public <B> List<B> flatMap(Function<A, List<B>> f) {
throw new IllegalStateException("To be implemented");
}
}
@SuppressWarnings("unchecked")
......
......@@ -6,6 +6,11 @@ import org.junit.Test;
public class ListTest {
@Test
public void testMap0() {
assertEquals("[NIL]", List.<Integer>list().map(x -> x + 1).toString());
}
@Test
public void testMap() {
assertEquals("[2, 3, 4, 5, NIL]", List.list(1, 2, 3, 4).map(x -> x + 1).toString());
......
......@@ -203,4 +203,9 @@ public abstract class List<A> {
public static <A> List<A> concat(List<A> list1, List<A> list2) {
return foldRight(list1, list2, x -> y -> new Cons<>(x, y));
}
public static <A> List<A> concat_(List<A> list1, List<A> list2) {
return list1.reverse().foldLeft(list2, x -> x::cons);
}
}
......@@ -5,6 +5,9 @@ import com.fpinjava.lists.exercise05_16.List;
public class DoubleToString {
public static List<String> doubleToString(List<Double> list) {
return List.foldRight(list, List.<String>list(), h -> t -> t.cons(Double.toString(h)));
return List.foldRight(list,
// Starting with an empty list
List.<String>list(),
h -> t -> t.cons(Double.toString(h)));
}
}
......@@ -18,7 +18,11 @@ public abstract class List<A> {
public abstract List<A> init();
public abstract int length();
public abstract <B> B foldLeft(B identity, Function<B, Function<A, B>> f);
public abstract <B> List<B> map(Function<A, B> f);
public <B> List<B> map(Function<A, B> f) {
return foldRight(list(), h -> t -> new Cons<>(f.apply(h),t));
}
public <B> B foldRight(B identity, Function<A, Function<B, B>> f) {
return reverse().foldLeft(identity, x -> y -> f.apply(y).apply(x));
......@@ -87,11 +91,6 @@ public abstract class List<A> {
public <B> B foldLeft(B identity, Function<B, Function<A, B>> f) {
return identity;
}
@Override
public <B> List<B> map(Function<A, B> f) {
return list();
}
}
private static class Cons<A> extends List<A> {
......@@ -186,11 +185,6 @@ public abstract class List<A> {
? ret(acc)
: sus(() -> foldLeft_(f.apply(acc).apply(list.head()), list.tail(), f));
}
@Override
public <B> List<B> map(Function<A, B> f) {
return foldRight(list(), h -> t -> new Cons<>(f.apply(h),t));
}
}
@SuppressWarnings("unchecked")
......
......@@ -18,8 +18,14 @@ public abstract class List<A> {
public abstract List<A> init();
public abstract int length();
public abstract <B> B foldLeft(B identity, Function<B, Function<A, B>> f);
public abstract <B> List<B> map(Function<A, B> f);
public abstract List<A> filter(Function<A, Boolean> f);
public List<A> filter(Function<A, Boolean> f) {
return foldRight(list(), h -> t -> f.apply(h) ? new Cons<>(h,t) : t);
}
public <B> List<B> map(Function<A, B> f) {
return foldRight(list(), h -> t -> new Cons<>(f.apply(h),t));
}
public <B> B foldRight(B identity, Function<A, Function<B, B>> f) {
return reverse().foldLeft(identity, x -> y -> f.apply(y).apply(x));
......@@ -88,16 +94,6 @@ public abstract class List<A> {
public <B> B foldLeft(B identity, Function<B, Function<A, B>> f) {
return identity;
}
@Override
public <B> List<B> map(Function<A, B> f) {
return list();
}
@Override
public List<A> filter(Function<A, Boolean> f) {
return this;
}
}
private static class Cons<A> extends List<A> {
......@@ -192,16 +188,6 @@ public abstract class List<A> {
? ret(acc)
: sus(() -> foldLeft_(f.apply(acc).apply(list.head()), list.tail(), f));
}
@Override
public <B> List<B> map(Function<A, B> f) {
return foldRight(list(), h -> t -> new Cons<>(f.apply(h),t));
}
@Override
public List<A> filter(Function<A, Boolean> f) {
return foldRight(list(), h -> t -> f.apply(h) ? new Cons<>(h,t) : t);
}
}
@SuppressWarnings("unchecked")
......
......@@ -20,11 +20,21 @@ public abstract class List<A> {
public abstract List<A> init();
public abstract int length();
public abstract <B> B foldLeft(B identity, Function<B, Function<A, B>> f);
public abstract <B> List<B> map(Function<A, B> f);
public abstract List<A> filter(Function<A, Boolean> f);
public abstract <B> List<B> flatMap(Function<A, List<B>> f);
public abstract List<A> concat(List<A> list2);
public <B> List<B> flatMap(Function<A, List<B>> f) {
/* Java is unable to infer type of the second parameter for the second function */
return foldRight(list(), h -> t -> f.apply(h).foldRight(t, x -> (List<B> y) -> new Cons<>(x, y)));
}
public List<A> filter(Function<A, Boolean> f) {
return foldRight(list(), h -> t -> f.apply(h) ? new Cons<>(h,t) : t);
}
public <B> List<B> map(Function<A, B> f) {
return foldRight(list(), h -> t -> new Cons<>(f.apply(h),t));
}
public <B> B foldRight(B identity, Function<A, Function<B, B>> f) {
return reverse().foldLeft(identity, x -> y -> f.apply(y).apply(x));
}
......@@ -93,21 +103,6 @@ public abstract class List<A> {
return identity;
}
@Override
public <B> List<B> map(Function<A, B> f) {
return list();
}
@Override
public List<A> filter(Function<A, Boolean> f) {
return this;
}
@Override
public <B> List<B> flatMap(Function<A, List<B>> f) {
return list();
}
@Override
public List<A> concat(List<A> list2) {
return list2;
......@@ -207,16 +202,6 @@ public abstract class List<A> {
: sus(() -> foldLeft_(f.apply(acc).apply(list.head()), list.tail(), f));
}
@Override
public <B> List<B> map(Function<A, B> f) {
return foldRight(list(), h -> t -> new Cons<>(f.apply(h),t));
}
@Override
public List<A> filter(Function<A, Boolean> f) {
return foldRight(list(), h -> t -> f.apply(h) ? new Cons<>(h,t) : t);
}
public <B> List<B> flatMap_(Function<A, List<B>> f) {
return foldRight(list(), h -> t -> concat(f.apply(h), t));
}
......@@ -224,12 +209,6 @@ public abstract class List<A> {
public List<A> concat(List<A> list2) {
return foldRight(list2, x -> y -> new Cons<>(x, y));
}
@Override
public <B> List<B> flatMap(Function<A, List<B>> f) {
/* Java is unable to infer type of the second parameter for the second function */
return foldRight(list(), h -> t -> f.apply(h).foldRight(t, x -> (List<B> y) -> new Cons<>(x, y)));
}
}
@SuppressWarnings("unchecked")
......
......@@ -14,4 +14,11 @@ public class ListTest {
assertEquals("[1, 2, 3, 4, 5, 6, NIL]", List.concat(list(1, 2, 3), list(4, 5, 6)).toString());
}
@Test
public void testConcat_() {
assertEquals("[4, 5, 6, NIL]", List.concat_(list(), list(4, 5, 6)).toString());
assertEquals("[1, 2, 3, NIL]", List.concat_(list(1, 2, 3), list()).toString());