Skip to content

Commit d1808d7

Browse files
author
Bhavik Mehta
authored
Merge pull request #78 from tweag/map-accums
Add mapAccumL and mapAccumR
2 parents c197fff + c2f45cf commit d1808d7

File tree

1 file changed

+26
-0
lines changed

1 file changed

+26
-0
lines changed

src/Data/Functor/Linear/Internal/Traversable.hs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ module Data.Functor.Linear.Internal.Traversable
1313
-- $ traversable
1414
Traversable(..)
1515
, mapM, sequenceA, for, forM
16+
, mapAccumL, mapAccumR
1617
) where
1718

1819
import qualified Control.Monad.Linear.Internal as Control
@@ -53,6 +54,31 @@ forM :: (Traversable t, Control.Monad m) => t a ->. (a ->. m b) -> m (t b)
5354
forM = for
5455
{-# INLINE forM #-}
5556

57+
mapAccumL :: Traversable t => (a ->. b ->. (a,c)) -> a ->. t b ->. (a, t c)
58+
mapAccumL f s t = swap $ Control.runState (traverse (\b -> Control.state $ \i -> swap $ f i b) t) s
59+
60+
mapAccumR :: Traversable t => (a ->. b ->. (a,c)) -> a ->. t b ->. (a, t c)
61+
mapAccumR f s t = swap $ runStateR (traverse (\b -> StateR $ \i -> swap $ f i b) t) s
62+
63+
swap :: (a,b) ->. (b,a)
64+
swap (x,y) = (y,x)
65+
66+
-- right-to-left state transformer
67+
newtype StateR s a = StateR (s ->. (a, s))
68+
deriving (Data.Functor, Data.Applicative) via Control.Data (StateR s)
69+
70+
runStateR :: StateR s a ->. s ->. (a, s)
71+
runStateR (StateR f) = f
72+
73+
instance Control.Functor (StateR s) where
74+
fmap f (StateR x) = StateR $ (\(a, s') -> (f a, s')) . x
75+
76+
instance Control.Applicative (StateR s) where
77+
pure x = StateR $ \s -> (x,s)
78+
StateR f <*> StateR x = StateR (go . Control.fmap f . x)
79+
where go :: (a, (a ->. b, s)) ->. (b, s)
80+
go (a, (h, s'')) = (h a, s'')
81+
5682
------------------------
5783
-- Standard instances --
5884
------------------------

0 commit comments

Comments
 (0)