package fj.data;
import fj.F;
import fj.data.test.PropertyAssert;
import fj.test.*;
import org.junit.Test;
import static fj.F1Functions.bind;
import static fj.F1Functions.map;
import static fj.test.Arbitrary.*;
import static fj.test.Cogen.cogenInteger;
import static fj.test.Property.prop;
import static fj.test.Property.property;
import static org.junit.Assert.assertTrue;
/**
* Created by MarkPerry on 4/12/2014.
*/
public class ReaderTest {
@Test
public void testMap() {
// (3 + 8) * 11
// example taken from http://learnyouahaskell.com/for-a-few-monads-more
int x = Reader.unit((Integer i) -> i + 3).map(i -> i * 5).f(8);
assertTrue(x == 55);
// System.out.println(x); // 55
}
@Test
public void testFlatMap() {
// (3 * 2) + (3 + 10)
// example taken from http://learnyouahaskell.com/for-a-few-monads-more
int y = Reader.unit((Integer i) -> i * 2).flatMap(a -> Reader.unit((Integer i) -> i + 10).map(b -> a + b)).f(3);
// System.out.println(y); // 19
assertTrue(y == 19);
}
@Test
public void testMapProp() {
Property p = property(
arbF(cogenInteger, arbInteger),
arbF(cogenInteger, arbInteger),
arbInteger,
(f, g, i) -> {
int expected = map(f, g).f(i);
// System.out.println(String.format("input: %d, result: %d", i, expected));
return prop(expected == Reader.unit(f).map(g).f(i));
});
PropertyAssert.assertResult(p);
}
@Test
public void testFlatMapProp() {
Gen<F<Integer, Reader<Integer, Integer>>> a = arbF(cogenInteger, arbReader());
Property p = property(
arbF(cogenInteger, arbInteger),
a,
arbInteger,
(f, g, i) -> {
int expected = bind(f, j -> g.f(j).getFunction()).f(i);
// System.out.println(String.format("input: %d, result: %d", i, expected));
return prop(expected == Reader.unit(f).flatMap(g).f(i));
}
);
PropertyAssert.assertResult(p);
}
// Left identity: return a >>= f == f a
@Test
public void testLeftIdentity() {
Property p = Property.property(
arbInteger,
arbInteger,
arbF(cogenInteger, arbReader()),
(i, j, f) -> {
int a = Reader.<Integer, Integer>constant(i).flatMap(f).f(j);
int b = f.f(i).f(j);
return prop(a == b);
});
PropertyAssert.assertResult(p);
}
// Right identity: m >>= return == m
@Test
public void testRightIdentity() {
Property p = Property.property(
arbInteger,
arbReader(),
(i, r2) -> {
return prop(r2.flatMap(a -> Reader.constant(a)).f(i) == r2.f(i));
});
PropertyAssert.assertResult(p);
}
// Associativity: (m >>= f) >>= g == m >>= (\x -> f x >>= g)
@Test
public void testAssociativity() {
Property p = Property.property(
arbInteger,
arbReader(),
arbF(cogenInteger, arbReader()),
arbF(cogenInteger, arbReader()),
(i, r, f, g) -> {
boolean b2 = r.flatMap(f).flatMap(g).f(i) == r.flatMap(x -> f.f(x).flatMap(g)).f(i);
return prop(b2);
});
PropertyAssert.assertResult(p);
}
public Gen<Reader<Integer, Integer>> arbReader() {
return Arbitrary.arbReader(cogenInteger, arbInteger);
}
}