I’m trying to write a cartesian product function in Purescript.
To my surprise, this doesn’t seem to be stack-safe, it blows up with relatively small inputs:
cartesianProduct :: Array (Array Int) -> Array (Array Int)
cartesianProduct =
Arr.foldl
( \b arr -> do
x <- arr
xs <- b
[ Arr.snoc xs x ]
)
[ [] ]
xs = Arr.range 0 5 <#> \i -> do
Arr.range 0 10 <#> \j -> j
result = cartesianProduct xs
-- RangeError: Maximum call stack size exceeded
However, this javascript implementation (which seems, in spirit, to be very similar) does not blow up. And it can in fact handle much larger inputs (though it’ll take a while to complete).
function cartesian(xs) {
return xs.reduce(
(a, b) => a.flatMap((x) => b.flatMap((y) => [[...x, y]])),
[[]]
);
}
let xs = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
cartesian([xs, xs, xs, xs, xs, xs]);
Why is the purescript version not stack safe and how can it be re-written to be stack safe?