-- | -- Module : Foundation.Primitive.Mappable -- License : BSD-style -- Maintainer : Nicolas Di Prima -- Stability : experimental -- Portability : portable -- -- Class of collection that can be traversed from left to right, -- performing an action on each element. -- module Foundation.Collection.Mappable ( Mappable(..) , sequence_ , traverse_ , mapM_ , forM , forM_ ) where import Foundation.Internal.Base import qualified Data.Traversable import Foundation.Array.Boxed (Array) -- | Functors representing data structures that can be traversed from -- left to right. -- -- Mostly like base's `Traversable` but applied to collections only. -- class Functor collection => Mappable collection where {-# MINIMAL traverse | sequenceA #-} -- | Map each element of a structure to an action, evaluate these actions -- from left to right, and collect the results. For a version that ignores -- the results see 'Foundation.Collection.traverse_'. traverse :: Applicative f => (a -> f b) -> collection a -> f (collection b) traverse f = sequenceA . fmap f -- | Evaluate each actions of the given collections, from left to right, -- and collect the results. For a version that ignores the results, see -- `Foundation.Collection.sequenceA_` sequenceA :: Applicative f => collection (f a) -> f (collection a) sequenceA = traverse id -- | Map each element of the collection to an action, evaluate these actions -- from left to right, and collect the results. For a version that ignores -- the results see 'Foundation.Collection.mapM_'. mapM :: (Applicative m, Monad m) => (a -> m b) -> collection a -> m (collection b) mapM = traverse -- | Evaluate each actions of the given collections, from left to right, -- and collect the results. For a version that ignores the results, see -- `Foundation.Collection.sequence_` sequence :: (Applicative m, Monad m) => collection (m a) -> m (collection a) sequence = sequenceA -- | Map each element of a collection to an action, evaluate these -- actions from left to right, and ignore the results. For a version -- that doesn't ignore the results see 'Foundation.Collection.traverse` traverse_ :: (Mappable col, Applicative f) => (a -> f b) -> col a -> f () traverse_ f col = traverse f col *> pure () -- | Evaluate each action in the collection from left to right, and -- ignore the results. For a version that doesn't ignore the results -- see 'Foundation.Collection.sequenceA'. sequenceA_ :: (Mappable col, Applicative f) => col (f a) -> f () sequenceA_ col = sequenceA col *> pure () -- | Map each element of a collection to a monadic action, evaluate -- these actions from left to right, and ignore the results. For a -- version that doesn't ignore the results see -- 'Foundation.Collection.mapM'. mapM_ :: (Mappable col, Applicative m, Monad m) => (a -> m b) -> col a -> m () mapM_ f c = mapM f c *> return () -- | Evaluate each monadic action in the collection from left to right, -- and ignore the results. For a version that doesn't ignore the -- results see 'Foundation.Collection.sequence'. sequence_ :: (Mappable col, Applicative m, Monad m) => col (m a) -> m () sequence_ c = sequence c *> return () -- | 'forM' is 'mapM' with its arguments flipped. For a version that -- ignores the results see 'Foundation.Collection.forM_'. forM :: (Mappable col, Applicative m, Monad m) => col a -> (a -> m b) -> m (col b) forM = flip mapM -- | 'forM_' is 'mapM_' with its arguments flipped. For a version that -- doesn't ignore the results see 'Foundation.Collection.forM'. forM_ :: (Mappable col, Applicative m, Monad m) => col a -> (a -> m b) -> m () forM_ = flip mapM_ ---------------------------- -- Foldable instances ---------------------------- instance Mappable [] where {-# INLINE traverse #-} traverse = Data.Traversable.traverse instance Mappable Array where -- | TODO: to optimise traverse f arr = fromList <$> traverse f (toList arr)