Skip to content

Commit

Permalink
stack-safe foldl (#93)
Browse files Browse the repository at this point in the history
* stack-safe foldl

* name TCOd foldl fodlRec

* add stack-safe foldl'
  • Loading branch information
matthewleon authored and paf31 committed Mar 30, 2017
1 parent c213455 commit e680771
Showing 1 changed file with 22 additions and 0 deletions.
22 changes: 22 additions & 0 deletions src/Control/Monad/List/Trans.purs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ module Control.Monad.List.Trans
, dropWhile
, filter
, foldl
, foldlRec
, foldl'
, foldlRec'
, fromEffect
, head
, iterate
Expand Down Expand Up @@ -39,6 +41,7 @@ import Control.Alternative (class Alternative)
import Control.Monad.Eff.Class (class MonadEff, liftEff)
import Control.Monad.Trans.Class (class MonadTrans, lift)
import Control.MonadPlus (class MonadPlus)
import Control.Monad.Rec.Class as MR
import Control.MonadZero (class MonadZero)
import Control.Plus (class Plus)

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

-- | Fold a list from the left, accumulating the result (effectfully) using the specified function.
-- | Uses tail call optimization.
foldlRec' :: forall f a b. MR.MonadRec f => (b -> a -> f b) -> b -> ListT f a -> f b
foldlRec' f = MR.tailRecM2 loop where
loop b l = uncons l >>= g
where
g Nothing = pure (MR.Done b)
g (Just (Tuple a as)) = (f b a) >>= \b' -> pure (MR.Loop {a: b', b: as})

-- | Fold a list from the left, accumulating the result using the specified function.
foldl :: forall f a b. Monad f => (b -> a -> b) -> b -> ListT f a -> f b
foldl f = loop where
Expand All @@ -211,6 +223,16 @@ foldl f = loop where
g Nothing = pure b
g (Just (Tuple a as)) = loop (f b a) as

-- | Fold a list from the left, accumulating the result using the specified function.
-- | Uses tail call optimization.
foldlRec :: forall f a b. MR.MonadRec f => (b -> a -> b) -> b -> ListT f a -> f b
foldlRec f = MR.tailRecM2 loop
where
loop b l = uncons l >>= g
where
g Nothing = pure (MR.Done b)
g (Just (Tuple a as)) = pure (MR.Loop {a: f b a, b: as})

-- | Fold a list from the left, accumulating the list of results using the specified function.
scanl :: forall f a b. Monad f => (b -> a -> b) -> b -> ListT f a -> ListT f b
scanl f b l = unfold g (Tuple b l)
Expand Down

0 comments on commit e680771

Please sign in to comment.