>>7basically, Java 8 introduced several FP concepts like lambdas and higher-order functions (through
@FunctionalInterface
. in addition to that, some of the more popular monads were ported in an unfortunately inconsisten way: a
Collection<>
can be converted to
Stream<>
which is more or less a
Free
monad, allowing you to write pipelines which look like this reinterpretation of the classic HMA program:
private void hma(List<String> benis){
benis.stream() //turn into monad
.map ((s)->"HAX MY ANUS!") //map each s to output of lambda which turns them to "HAX MY ANUS!"
.filter((s)->s.startsWith("HAX")) //those filters, applied to results of map, are obvious now that you know lambda syntax
.filter((s)->s.contains("ANUS"))
.filter((s)->s.equals("HAX MY ANUS!"))
.forEach(System.out::println); //forEach is used to terminate a stream by evaluating a certain function for side-effects over the whole sequence
}
they also added
Optional<>
which is a lot like
Maybe
and
Future<>
which I don't think has a direct equivalent in Haskal due to its laziness.
now, the problem is that it's not consistent: e.g. while both
Optional<>
and
Stream<>
have
map() and flatMap()
, there's no way to write a function that would take any monad (e.g. through some kind of
Monad<>
interface). you must make sure it takes one of them. it's also inconvenient when you have a sequence of
Optional<>s
and want to use stream API on it as you must manually
map()
/
filter()
them twice (I think Java 9 will make it more consistent by allowing you to turn a
Optional<>
into a
Stream<>
, which would turn
Stream<>
into a general-purpose monadic type).
despite the inconsistencies, Stream API is kind of fun to use - especially when compared to standard ultra-verbose Java. I was pleasantly surprised when I had to work with a Java codebase at work because my previous experiences with the language were similar to yours.