import static java.util.Arrays.asList;import static java.util.Collections.emptyList; import static java.util.Optional.of; import static java.util.stream.Collectors.toList; import java.util.List; public class CartesianProduct { public List<?> product(List<?>... a) { if (a.length >= 2) { List<?> product = a[0]; for (int i = 1; i < a.length; i++) { product = product(product, a[i]); } return product; } return emptyList(); } private <A, B> List<?> product(List<A> a, List<B> b) { return of(a.stream() .map(e1 -> of(b.stream().map(e2 -> asList(e1, e2)).collect(toList())).orElse(emptyList())) .flatMap(List::stream) .collect(toList())).orElse(emptyList()); } }
A programmer that spent a lot of time studying Monads and playing around with them, and that understands the Monad instances for lists, might come up with the following solution in Haskell:
cartProdN :: [[a]] -> [[a]] cartProdN = sequence
This also made me realize of two things:0. Haskell will never be mainstream, because there are not a lot of programmers out there who are willing to do the investment required for learning the necessary concepts to understand and write code like the one shown above.