sort and sortBy are not stack safe
milesfrain opened this issue · 4 comments
sort $ range 1 1000000/home/miles/projects/purescript/lists/output/Data.List/index.js:287
return as(new Data_List_Types.Cons(a, ys));
^
RangeError: Maximum call stack size exceeded
at $tco_var_as (/home/miles/projects/purescript/lists/output/Data.List/index.js:287:39)
Should we swap out this current version (which I assume depends on Haskell's laziness) for something that just reuses Array's sortBy? I think that might end up being faster even in situations where we're not having stack issues.
purescript-lists/src/Data/List.purs
Lines 447 to 482 in 6d8e30e
I'm thinking something like this would work:
sortBy :: forall a. (a -> a -> Ordering) -> List a -> List a
sortBy cmp = fromFoldable <<< Array.sortBy cmp <<< Array.fromFoldableBut it's very slow. It should be much faster if we change Array.fromFoldable to use foldl instead. Here's the existing version:
fromFoldable :: forall f. Foldable f => f ~> Array
fromFoldable = fromFoldableImpl foldrEdit: Another option, but still slower than the original list version (up to 10k elements, then list version overflows).
sortBy :: forall a. (a -> a -> Ordering) -> List a -> List a
sortBy cmp = fromFoldable <<< Array.sortBy cmp <<< toUnfoldableHave you benchmarked what effect it would have by swapping fromFoldable to use foldl rather than foldr?
FYI the Haskell version depends more on the GHC runtime being smarter about stack usage, which is separate from laziness. In Haskell it’s very rare that you have to worry about stack overflows, because of how the GHC runtime works.
I just ran into this while solving Advent of Code. Any recommended workarounds in the meantime?