Skip to content

Commit 8bfe8aa

Browse files
committed
feat(core): Add SolveHandler flatmap
1 parent c01e34d commit 8bfe8aa

File tree

2 files changed

+53
-7
lines changed

2 files changed

+53
-7
lines changed

Diff for: src/main/java/io/github/joselion/maybe/SolveHandler.java

+31-7
Original file line numberDiff line numberDiff line change
@@ -341,13 +341,14 @@ public <X extends Throwable> EffectHandler<X> runEffect(// NOSONAR
341341
}
342342

343343
/**
344-
* If the value is present, map it to another value through the {@code mapper}
345-
* function. If the error is present, the {@code mapper} is never applied and
346-
* the next handler will still contain the error.
347-
*
348-
* @param <U> the type the value will be mapped to
349-
* @param mapper a function that receives the solved value and produces another
350-
* @return a new handler with either the mapped value, or the previous error
344+
* If the value is present, map it to another value using the {@code mapper}
345+
* function. If an error is present, the {@code mapper} function is never
346+
* applied and the next handler will still contain the error.
347+
*
348+
* @param <U> the type the value is mapped to
349+
* @param mapper a function which takes the value as argument and returns
350+
* another value
351+
* @return a new handler with either the mapped value or an error
351352
*/
352353
public <U> SolveHandler<U, E> map(final Function<? super T, ? extends U> mapper) {
353354
return this.value
@@ -358,6 +359,29 @@ public <U> SolveHandler<U, E> map(final Function<? super T, ? extends U> mapper)
358359
);
359360
}
360361

362+
/**
363+
* If the value is present, map it to another value using the {@code mapper}
364+
* function. If an error is present, the {@code mapper} function is never
365+
* applied and the next handler will still contain the error.
366+
*
367+
* This method is similar to {@link #map(Function)}, but the mapping function is
368+
* one whose result is a {@code Maybe}, and if invoked, flatMap does not wrap
369+
* it within an additional {@code Maybe}.
370+
*
371+
* @param <U> the type the value is mapped to
372+
* @param mapper a function which takes the value as argument and returns a
373+
* {@code Maybe<U>} with another value
374+
* @return a new handler with either the mapped value or an error
375+
*/
376+
public <U> SolveHandler<U, E> flatMap(final Function<? super T, Maybe<? extends U>> mapper) {
377+
return this.value
378+
.mapRight(mapper)
379+
.unwrap(
380+
SolveHandler::failure,
381+
maybe -> maybe.solve(ThrowingFunction.identity())
382+
);
383+
}
384+
361385
/**
362386
* If the value is present, cast the value to anoter type. If the cast fails
363387
* or if the error is present, it returns a new handler which contains a

Diff for: src/test/java/io/github/joselion/maybe/SolveHandlerTests.java

+22
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,28 @@
383383
}
384384
}
385385

386+
@Nested class flatMap {
387+
@Nested class when_the_value_is_present {
388+
@Test void returns_a_handler_applying_the_mapper_function() {
389+
final var handler = SolveHandler.from("Hello world!")
390+
.flatMap(x -> Maybe.of(x.length()));
391+
392+
assertThat(handler.success()).contains(12);
393+
assertThat(handler.error()).isEmpty();
394+
}
395+
}
396+
397+
@Nested class when_the_error_is_present {
398+
@Test void returns_a_handler_with_the_previous_error() {
399+
final var handler = SolveHandler.failure(FAIL_EXCEPTION)
400+
.flatMap(x -> Maybe.of(x.toString()));
401+
402+
assertThat(handler.success()).isEmpty();
403+
assertThat(handler.error()).contains(FAIL_EXCEPTION);
404+
}
405+
}
406+
}
407+
386408
@Nested class cast {
387409
@Nested class when_the_value_is_present {
388410
@Nested class and_the_object_can_be_cast {

0 commit comments

Comments
 (0)