Skip to content

Commit 19ff68f

Browse files
committed
Add @jutaro's stack safe foldM variant
1 parent 0e3f07a commit 19ff68f

File tree

5 files changed

+32
-16
lines changed

5 files changed

+32
-16
lines changed

bower.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
"purescript-foldable-traversable": "^2.0.0",
2020
"purescript-partial": "^1.1.0",
2121
"purescript-st": "^2.0.0",
22+
"purescript-tailrec": "^2.0.0",
2223
"purescript-tuples": "^3.0.0",
2324
"purescript-unfoldable": "^2.0.0"
2425
},

src/Data/Array.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,3 +272,13 @@ exports.zipWith = function (f) {
272272
};
273273
};
274274
};
275+
276+
//------------------------------------------------------------------------------
277+
// Partial ---------------------------------------------------------------------
278+
//------------------------------------------------------------------------------
279+
280+
exports.unsafeIndexImpl = function (xs) {
281+
return function (n) {
282+
return xs[n];
283+
};
284+
};

src/Data/Array.purs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,9 @@ module Data.Array
101101
, unzip
102102

103103
, foldM
104+
, foldRecM
105+
106+
, unsafeIndex
104107

105108
, module Exports
106109
) where
@@ -110,6 +113,7 @@ import Prelude
110113
import Control.Alt ((<|>))
111114
import Control.Alternative (class Alternative)
112115
import Control.Lazy (class Lazy, defer)
116+
import Control.Monad.Rec.Class (class MonadRec, Step(..), tailRecM2)
113117

114118
import Data.Foldable (class Foldable, foldl, foldr)
115119
import Data.Foldable (foldl, foldr, foldMap, fold, intercalate, elem, notElem, find, findMap, any, all) as Exports
@@ -626,3 +630,18 @@ unzip = uncons' (\_ -> Tuple [] []) \(Tuple a b) ts -> case unzip ts of
626630
-- | Perform a fold using a monadic step function.
627631
foldM :: forall m a b. Monad m => (a -> b -> m a) -> a -> Array b -> m a
628632
foldM f a = uncons' (\_ -> pure a) (\b bs -> f a b >>= \a' -> foldM f a' bs)
633+
634+
foldRecM :: forall m a b. MonadRec m => (a -> b -> m a) -> a -> Array b -> m a
635+
foldRecM f a array = tailRecM2 go a 0
636+
where
637+
go res i
638+
| i >= length array = pure (Done res)
639+
| otherwise = do
640+
res' <- f res (unsafePartial (unsafeIndex array i))
641+
pure (Loop { a: res', b: i + 1 })
642+
643+
-- | Find the element of an array at the specified index.
644+
unsafeIndex :: forall a. Partial => Array a -> Int -> a
645+
unsafeIndex = unsafeIndexImpl
646+
647+
foreign import unsafeIndexImpl :: forall a. Array a -> Int -> a

src/Data/Array/Partial.js

Lines changed: 0 additions & 7 deletions
This file was deleted.

src/Data/Array/Partial.purs

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,14 @@
11
-- | Partial helper functions for working with immutable arrays.
22
module Data.Array.Partial
3-
( unsafeIndex
4-
, head
3+
( head
54
, tail
65
, last
76
, init
87
) where
98

109
import Prelude
1110

12-
import Data.Array (length, slice)
13-
14-
-- | Find the element of an array at the specified index.
15-
unsafeIndex :: forall a. Partial => Array a -> Int -> a
16-
unsafeIndex = unsafeIndexImpl
17-
18-
foreign import unsafeIndexImpl :: forall a. Array a -> Int -> a
11+
import Data.Array (length, slice, unsafeIndex)
1912

2013
-- | Get the first element of a non-empty array.
2114
-- |

0 commit comments

Comments
 (0)