Skip to content

Commit 2354044

Browse files
committed
IterateT gains equals/hashCode/toString
1 parent 23bf1e9 commit 2354044

File tree

2 files changed

+91
-26
lines changed
  • src
    • main/java/com/jnape/palatable/lambda/monad/transformer/builtin
    • test/java/com/jnape/palatable/lambda/monad/transformer/builtin

2 files changed

+91
-26
lines changed

src/main/java/com/jnape/palatable/lambda/monad/transformer/builtin/IterateT.java

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,13 @@
1717
import com.jnape.palatable.lambda.monad.Monad;
1818
import com.jnape.palatable.lambda.monad.MonadRec;
1919
import com.jnape.palatable.lambda.monad.transformer.MonadT;
20+
import com.jnape.palatable.lambda.monoid.builtin.Concat;
2021

22+
import java.util.ArrayList;
2123
import java.util.Collection;
2224
import java.util.Iterator;
2325
import java.util.List;
26+
import java.util.Objects;
2427
import java.util.Set;
2528

2629
import static com.jnape.palatable.lambda.adt.Maybe.just;
@@ -30,8 +33,10 @@
3033
import static com.jnape.palatable.lambda.adt.choice.Choice2.b;
3134
import static com.jnape.palatable.lambda.adt.hlist.HList.tuple;
3235
import static com.jnape.palatable.lambda.functions.Fn1.withSelf;
36+
import static com.jnape.palatable.lambda.functions.builtin.fn1.Constantly.constantly;
3337
import static com.jnape.palatable.lambda.functions.builtin.fn2.$.$;
3438
import static com.jnape.palatable.lambda.functions.builtin.fn2.Into.into;
39+
import static com.jnape.palatable.lambda.functions.builtin.fn2.Map.map;
3540
import static com.jnape.palatable.lambda.functions.builtin.fn2.Tupler2.tupler;
3641
import static com.jnape.palatable.lambda.functions.builtin.fn3.FoldLeft.foldLeft;
3742
import static com.jnape.palatable.lambda.functions.recursion.RecursiveResult.recurse;
@@ -176,7 +181,7 @@ public <B, MB extends MonadRec<B, M>> MB foldCut(
176181
* @return the folded effect result
177182
*/
178183
public <MU extends MonadRec<Unit, M>> MU forEach(Fn1<? super A, ? extends MonadRec<Unit, M>> fn) {
179-
return fold((__, a) -> fn.apply(a), runIterateT().pure(UNIT));
184+
return fold((__, a) -> fn.apply(a), pureM.apply(UNIT));
180185
}
181186

182187
/**
@@ -239,29 +244,25 @@ public <B> IterateT<M, B> pure(B b) {
239244
* @return the {@link List} inside of the effect
240245
*/
241246
public <C extends Collection<A>, MAS extends MonadRec<C, M>> MAS toCollection(Fn0<C> cFn0) {
242-
MonadRec<Maybe<Tuple2<A, IterateT<M, A>>>, M> mmta = runIterateT();
243247
return fold((c, a) -> {
244248
c.add(a);
245-
return mmta.pure(c);
246-
}, mmta.pure(cFn0.apply()));
249+
return pureM.apply(c);
250+
}, pureM.apply(cFn0.apply()));
247251
}
248252

249253
/**
250254
* {@inheritDoc}
251255
*/
252256
@Override
253257
public <B> IterateT<M, B> zip(Applicative<Fn1<? super A, ? extends B>, IterateT<M, ?>> appFn) {
254-
return suspended(() -> {
255-
MonadRec<Maybe<Tuple2<A, IterateT<M, A>>>, M> mmta = runIterateT();
256-
return join(maybeT(mmta).zip(
257-
maybeT(appFn.<IterateT<M, Fn1<? super A, ? extends B>>>coerce().runIterateT())
258-
.fmap(into((f, fs) -> into((a, as) -> maybeT(
259-
as.<B>fmap(f)
260-
.cons(mmta.pure(f.apply(a)))
261-
.concat(as.cons(mmta.pure(a)).zip(fs))
262-
.runIterateT()))))))
263-
.runMaybeT();
264-
}, pureM);
258+
return suspended(() -> join(maybeT(runIterateT()).zip(
259+
maybeT(appFn.<IterateT<M, Fn1<? super A, ? extends B>>>coerce().runIterateT())
260+
.fmap(into((f, fs) -> into((a, as) -> maybeT(
261+
as.<B>fmap(f)
262+
.cons(pureM.apply(f.apply(a)))
263+
.concat(as.cons(pureM.apply(a)).zip(fs))
264+
.runIterateT()))))))
265+
.runMaybeT(), pureM);
265266
}
266267

267268
/**
@@ -289,6 +290,30 @@ public <B> IterateT<M, A> discardR(Applicative<B, IterateT<M, ?>> appB) {
289290
return MonadT.super.discardR(appB).coerce();
290291
}
291292

293+
@Override
294+
public boolean equals(Object other) {
295+
if (other instanceof IterateT<?, ?>) {
296+
return Objects.equals(toCollection(ArrayList::new),
297+
((IterateT<?, ?>) other).toCollection(ArrayList::new));
298+
}
299+
return false;
300+
}
301+
302+
@Override
303+
public int hashCode() {
304+
return toCollection(ArrayList::new).hashCode();
305+
}
306+
307+
@Override
308+
public String toString() {
309+
Iterable<String> nodes = Concat.concat(map(Object::toString, conses),
310+
Concat.concat(map(constantly("..."), middles),
311+
map(Object::toString, snocs)));
312+
return "IterateT{ "
313+
+ String.join(" :# ", nodes)
314+
+ " }";
315+
}
316+
292317
private MonadRec<RecursiveResult<IterateT<M, A>, Maybe<Tuple2<A, IterateT<M, A>>>>, M> resume() {
293318
return conses.head().match(
294319
__ -> middles.head().match(

src/test/java/com/jnape/palatable/lambda/monad/transformer/builtin/IterateTTest.java

Lines changed: 51 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@
1313
import com.jnape.palatable.traitor.runners.Traits;
1414
import org.junit.Test;
1515
import org.junit.runner.RunWith;
16-
import testsupport.traits.*;
16+
import testsupport.traits.ApplicativeLaws;
17+
import testsupport.traits.Equivalence;
18+
import testsupport.traits.FunctorLaws;
19+
import testsupport.traits.MonadLaws;
20+
import testsupport.traits.MonadRecLaws;
1721

1822
import java.util.ArrayList;
1923
import java.util.Collection;
@@ -30,9 +34,16 @@
3034
import static com.jnape.palatable.lambda.functions.recursion.RecursiveResult.terminate;
3135
import static com.jnape.palatable.lambda.functor.builtin.Identity.pureIdentity;
3236
import static com.jnape.palatable.lambda.functor.builtin.Lazy.lazy;
33-
import static com.jnape.palatable.lambda.functor.builtin.Writer.*;
37+
import static com.jnape.palatable.lambda.functor.builtin.Writer.listen;
38+
import static com.jnape.palatable.lambda.functor.builtin.Writer.pureWriter;
39+
import static com.jnape.palatable.lambda.functor.builtin.Writer.tell;
40+
import static com.jnape.palatable.lambda.functor.builtin.Writer.writer;
3441
import static com.jnape.palatable.lambda.io.IO.io;
35-
import static com.jnape.palatable.lambda.monad.transformer.builtin.IterateT.*;
42+
import static com.jnape.palatable.lambda.monad.transformer.builtin.IterateT.empty;
43+
import static com.jnape.palatable.lambda.monad.transformer.builtin.IterateT.liftIterateT;
44+
import static com.jnape.palatable.lambda.monad.transformer.builtin.IterateT.pureIterateT;
45+
import static com.jnape.palatable.lambda.monad.transformer.builtin.IterateT.singleton;
46+
import static com.jnape.palatable.lambda.monad.transformer.builtin.IterateT.unfold;
3647
import static com.jnape.palatable.lambda.monoid.builtin.AddAll.addAll;
3748
import static com.jnape.palatable.lambda.monoid.builtin.Join.join;
3849
import static com.jnape.palatable.traitor.framework.Subjects.subjects;
@@ -44,7 +55,9 @@
4455
import static org.junit.Assert.assertThat;
4556
import static testsupport.Constants.STACK_EXPLODING_NUMBER;
4657
import static testsupport.matchers.IOMatcher.yieldsValue;
47-
import static testsupport.matchers.IterateTMatcher.*;
58+
import static testsupport.matchers.IterateTMatcher.isEmpty;
59+
import static testsupport.matchers.IterateTMatcher.iterates;
60+
import static testsupport.matchers.IterateTMatcher.iteratesAll;
4861
import static testsupport.traits.Equivalence.equivalence;
4962

5063
@RunWith(Traits.class)
@@ -219,32 +232,59 @@ public void stackSafetyForStrictMonads() {
219232
@Test
220233
public void stackSafetyForNonStrictMonads() {
221234
IterateT<Lazy<?>, Integer> hugeNonStrictIterateT =
222-
unfold(x -> lazy(() -> x <= 50_000 ? just(tuple(x, x + 1)) : nothing()), lazy(0));
235+
unfold(x -> lazy(() -> x <= STACK_EXPLODING_NUMBER ? just(tuple(x, x + 1)) : nothing()), lazy(0));
223236
Lazy<Integer> fold = hugeNonStrictIterateT.fold((x, y) -> lazy(() -> x + y), lazy(0));
224237
assertEquals((Integer) 1250025000, fold.value());
225238
}
226239

227240
@Test
228241
public void concatIsStackSafe() {
229-
IterateT<Identity<?>, Integer> bigIterateT = times(10_000, xs -> xs.concat(singleton(new Identity<>(1))),
242+
IterateT<Identity<?>, Integer> bigIterateT = times(STACK_EXPLODING_NUMBER,
243+
xs -> xs.concat(singleton(new Identity<>(1))),
230244
singleton(new Identity<>(0)));
231-
assertEquals(new Identity<>(10_000),
245+
assertEquals(new Identity<>(STACK_EXPLODING_NUMBER),
232246
bigIterateT.fold((x, y) -> new Identity<>(x + y), new Identity<>(0)));
233247
}
234248

249+
@Test
250+
public void iterateT() {
251+
assertEquals(IterateT.<Identity<?>, Integer>empty(pureIdentity()).cons(new Identity<>(1)),
252+
IterateT.iterateT(new Identity<>(just(tuple(1, empty(pureIdentity()))))));
253+
}
254+
255+
@Test
256+
public void testToString() {
257+
assertEquals("IterateT{ Identity{a=1} :# Identity{a=2} :# Identity{a=3} }",
258+
IterateT.of(new Identity<>(1), new Identity<>(2), new Identity<>(3)).toString());
259+
260+
assertEquals("IterateT{ ... }",
261+
IterateT.iterateT(new Identity<>(just(tuple(1, empty(pureIdentity()))))).toString());
262+
263+
assertEquals("IterateT{ Identity{a=1} :# ... :# Identity{a=3} }",
264+
IterateT.iterateT(new Identity<>(just(tuple(2, empty(pureIdentity())))))
265+
.cons(new Identity<>(1))
266+
.snoc(new Identity<>(3))
267+
.toString());
268+
269+
assertEquals("IterateT{ ... }",
270+
IterateT.of(new Identity<>(1))
271+
.concat(IterateT.of(new Identity<>(2)))
272+
.toString());
273+
}
274+
235275
@Test
236276
public void staticPure() {
237277
assertEquals(new Identity<>(singletonList(1)),
238278
pureIterateT(pureIdentity())
239-
.<Integer, IterateT<Identity<?>, Integer>>apply(1)
240-
.<List<Integer>, Identity<List<Integer>>>toCollection(ArrayList::new));
279+
.<Integer, IterateT<Identity<?>, Integer>>apply(1)
280+
.<List<Integer>, Identity<List<Integer>>>toCollection(ArrayList::new));
241281
}
242282

243283
@Test
244284
public void staticLift() {
245285
assertEquals(new Identity<>(singletonList(1)),
246286
liftIterateT()
247-
.<Integer, Identity<?>, IterateT<Identity<?>, Integer>>apply(new Identity<>(1))
248-
.<List<Integer>, Identity<List<Integer>>>toCollection(ArrayList::new));
287+
.<Integer, Identity<?>, IterateT<Identity<?>, Integer>>apply(new Identity<>(1))
288+
.<List<Integer>, Identity<List<Integer>>>toCollection(ArrayList::new));
249289
}
250290
}

0 commit comments

Comments
 (0)