I’m looking at this definition of traverse
for arrays:
return function (f) {
return function (array) {
function go(bot, top) {
switch (top - bot) {
case 0: return pure([]);
case 1: return map(array1)(f(array[bot]));
case 2: return apply(map(array2)(f(array[bot])))(f(array[bot + 1]));
case 3: return apply(apply(map(array3)(f(array[bot])))(f(array[bot + 1])))(f(array[bot + 2]));
default:
// This slightly tricky pivot selection aims to produce two
// even-length partitions where possible.
var pivot = bot + Math.floor((top - bot) / 4) * 2;
return apply(map(concat2)(go(bot, pivot)))(go(pivot, top));
}
}
return go(0, array.length);
};
};
and this definition of apply
for Effect
ap f a = do
f' <- f
a' <- a
pure (f' a')
and I would have expected this to blow the stack
traverse (pure :: _ -> Effect _) (1 .. 1000000)
But it doesn’t. Can somebody help me understand how this is okay? I don’t suppose I can universally extrapolate that using traverse
and sequence
are stack-safe for any monad, and that I only need to worry about stack safety when manually recursing?