Skip to content

Commit 6333855

Browse files
committed
make map stack safe(r) again
begin with reverse unrolled map
1 parent e510520 commit 6333855

File tree

1 file changed

+12
-26
lines changed

1 file changed

+12
-26
lines changed

src/Data/List/Types.purs

Lines changed: 12 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import Data.Traversable (class Traversable, traverse)
3232
import Data.TraversableWithIndex (class TraversableWithIndex)
3333
import Data.Tuple (Tuple(..), snd)
3434
import Data.Unfoldable (class Unfoldable)
35+
import Partial.Unsafe (unsafePartial)
3536

3637
data List a = Nil | Cons a (List a)
3738

@@ -79,33 +80,18 @@ instance functorList :: Functor List where
7980
-- https://discuss.ocaml.org/t/a-new-list-map-that-is-both-stack-safe-and-fast/865
8081
-- chunk sizes determined through experimentation
8182
listMap :: forall a b. (a -> b) -> List a -> List b
82-
listMap f = startUnrolledMap unrollLimit where
83-
-- iterate the unrolled map up to 200 times,
84-
-- which hits up to 1000 elements
85-
unrollLimit = 200
86-
87-
startUnrolledMap :: Int -> List a -> List b
88-
startUnrolledMap 0 (x : xs) = f x : chunkedRevMap xs
89-
startUnrolledMap n (x1 : x2 : x3 : x4 : x5 : xs) =
90-
f x1 : f x2 : f x3 : f x4 : f x5 : startUnrolledMap (n - 1) xs
91-
startUnrolledMap n (x1 : x2 : x3 : x4 : xs) =
92-
f x1 : f x2 : f x3 : f x4 : startUnrolledMap (n - 1) xs
93-
startUnrolledMap n (x1 : x2 : x3 : xs) =
94-
f x1 : f x2 : f x3 : startUnrolledMap (n - 1) xs
95-
startUnrolledMap n (x1 : x2 : xs) =
96-
f x1 : f x2 : startUnrolledMap (n - 1) xs
97-
startUnrolledMap n (x : xs) = f x : startUnrolledMap (n - 1) xs
98-
99-
startUnrolledMap _ Nil = Nil
100-
101-
chunkedRevMap :: List a -> List b
102-
chunkedRevMap = go Nil
83+
listMap f = chunkedRevMap Nil
84+
where
85+
chunkedRevMap :: List (List a) -> List a -> List b
86+
chunkedRevMap chunksAcc chunk@(x1 : x2 : x3 : xs) =
87+
chunkedRevMap (chunk : chunksAcc) xs
88+
chunkedRevMap chunksAcc finalChunk =
89+
reverseUnrolledMap chunksAcc $ unsafePartial unrolledMap finalChunk
10390
where
104-
go :: List (List a) -> List a -> List b
105-
go chunksAcc chunk@(x1 : x2 : x3 : xs) =
106-
go (chunk : chunksAcc) xs
107-
go chunksAcc finalChunk =
108-
reverseUnrolledMap chunksAcc $ startUnrolledMap 0 finalChunk
91+
unrolledMap :: Partial => List a -> List b
92+
unrolledMap (x1 : x2 : Nil) = f x1 : f x2 : Nil
93+
unrolledMap (x : Nil) = f x : Nil
94+
unrolledMap Nil = Nil
10995

11096
reverseUnrolledMap :: List (List a) -> List b -> List b
11197
reverseUnrolledMap ((x1 : x2 : x3 : _) : cs) acc =

0 commit comments

Comments
 (0)