package fj.demo.test;
import fj.Function;
import static fj.Function.compose;
import fj.P2;
import fj.data.List;
import static fj.Equal.listEqual;
import static fj.Equal.stringEqual;
import static fj.test.Arbitrary.arbF;
import static fj.test.Arbitrary.arbInteger;
import static fj.test.Arbitrary.arbList;
import static fj.test.Arbitrary.arbLong;
import static fj.test.Arbitrary.arbString;
import fj.function.Effect1;
import fj.test.CheckResult;
import static fj.test.CheckResult.summary;
import static fj.test.Cogen.cogenInteger;
import static fj.test.Cogen.cogenLong;
import fj.test.Property;
import static fj.test.Property.prop;
import static fj.test.Property.property;
import static fj.test.reflect.Check.check;
import fj.test.reflect.CheckParams;
/*
Checks the two functor laws on List.map. These laws are:
1) The Law of Identity
forall x. map identity x == x
For any list, mapping the identity function (\x -> x) produces the same list.
2) The Law of Composition
forall f. forall g. forall x. map (f . g) x == map f (map g x)
...where (f . g) denotes composition of f with g. That is, \c -> f(g(c)).
Note that to test this second law requires the generation of arbitrary functions.
*/
@SuppressWarnings("PackageVisibleField")
@CheckParams(minSuccessful = 1000)
public final class ListFunctorLaws {
final Property identity = property(arbList(arbString), x -> prop(listEqual(stringEqual).eq(x, x.map(Function.identity()))));
final Property composition = property(arbF(cogenInteger, arbString), arbF(cogenLong, arbInteger), arbList(arbLong), (f, g, x) -> {
final List<String> s1 = x.map(compose(f, g));
final List<String> s2 = x.map(g).map(f);
return prop(listEqual(stringEqual).eq(s1, s2));
});
// identity: OK, passed 1000 tests.
// composition: OK, passed 1000 tests.
@SuppressWarnings("unchecked")
public static void main(final String[] args) {
check(ListFunctorLaws.class).foreachDoEffect(r -> {
System.out.print(r._1() + ": ");
summary.println(r._2());
});
}
}