Skip to content

Commit e680771

Browse files
matthewleonpaf31
authored andcommitted
stack-safe foldl (#93)
* stack-safe foldl * name TCOd foldl fodlRec * add stack-safe foldl'
1 parent c213455 commit e680771

File tree

1 file changed

+22
-0
lines changed

1 file changed

+22
-0
lines changed

src/Control/Monad/List/Trans.purs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ module Control.Monad.List.Trans
99
, dropWhile
1010
, filter
1111
, foldl
12+
, foldlRec
1213
, foldl'
14+
, foldlRec'
1315
, fromEffect
1416
, head
1517
, iterate
@@ -39,6 +41,7 @@ import Control.Alternative (class Alternative)
3941
import Control.Monad.Eff.Class (class MonadEff, liftEff)
4042
import Control.Monad.Trans.Class (class MonadTrans, lift)
4143
import Control.MonadPlus (class MonadPlus)
44+
import Control.Monad.Rec.Class as MR
4245
import Control.MonadZero (class MonadZero)
4346
import Control.Plus (class Plus)
4447

@@ -203,6 +206,15 @@ foldl' f = loop where
203206
g Nothing = pure b
204207
g (Just (Tuple a as)) = (f b a) >>= (flip loop as)
205208

209+
-- | Fold a list from the left, accumulating the result (effectfully) using the specified function.
210+
-- | Uses tail call optimization.
211+
foldlRec' :: forall f a b. MR.MonadRec f => (b -> a -> f b) -> b -> ListT f a -> f b
212+
foldlRec' f = MR.tailRecM2 loop where
213+
loop b l = uncons l >>= g
214+
where
215+
g Nothing = pure (MR.Done b)
216+
g (Just (Tuple a as)) = (f b a) >>= \b' -> pure (MR.Loop {a: b', b: as})
217+
206218
-- | Fold a list from the left, accumulating the result using the specified function.
207219
foldl :: forall f a b. Monad f => (b -> a -> b) -> b -> ListT f a -> f b
208220
foldl f = loop where
@@ -211,6 +223,16 @@ foldl f = loop where
211223
g Nothing = pure b
212224
g (Just (Tuple a as)) = loop (f b a) as
213225

226+
-- | Fold a list from the left, accumulating the result using the specified function.
227+
-- | Uses tail call optimization.
228+
foldlRec :: forall f a b. MR.MonadRec f => (b -> a -> b) -> b -> ListT f a -> f b
229+
foldlRec f = MR.tailRecM2 loop
230+
where
231+
loop b l = uncons l >>= g
232+
where
233+
g Nothing = pure (MR.Done b)
234+
g (Just (Tuple a as)) = pure (MR.Loop {a: f b a, b: as})
235+
214236
-- | Fold a list from the left, accumulating the list of results using the specified function.
215237
scanl :: forall f a b. Monad f => (b -> a -> b) -> b -> ListT f a -> ListT f b
216238
scanl f b l = unfold g (Tuple b l)

0 commit comments

Comments
 (0)