If actions is a suitably large array, this creates a stack overflow:
modifyPerIndex :: forall a. Array (Tuple Int (a -> a)) -> Array a -> Array a
modifyPerIndex actions array = run do
mutableArray <- thaw array
for_ actions \(Tuple index action) -> modify index action mutableArray
pure mutableArray
This does not:
modifyPerIndex :: forall a. Array (Tuple Int (a -> a)) -> Array a -> Array a
modifyPerIndex actions array = run do
mutableArray <- thaw array
foreach actions \(Tuple index action) -> void $ modify index action mutableArray
pure mutableArray
I'm assuming that's why Control.Monad.ST has its own version of foreach. for_'s Applicative & Foldable is a much looser constraint than foreach's Array. That being said, I'm not sure what Applicative & Foldable is missing such that for_ can't be stack safe (or can't be without some other drawback)
I've dug into the source a bit and have noted that for_ is implemented via foldr. I'm not sure where to find Array's foldr instance.
I'm pretty new to a lot of this, just trying to broaden my general understanding. :)