X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;ds=sidebyside;f=Data%2FTraversable.hs;h=f8fca1b6df1f52374473d6761c93a77edd24d703;hb=4c6a5640f35898d9f3526b98a5b89e6af9d793a9;hp=e133238889a6418007582a0b99ae563bbffa00e5;hpb=641f8d5964b2b02f4cd7b9081adf6596c6f4d4d7;p=haskell-directory.git diff --git a/Data/Traversable.hs b/Data/Traversable.hs index e133238..f8fca1b 100644 --- a/Data/Traversable.hs +++ b/Data/Traversable.hs @@ -10,12 +10,12 @@ -- -- Class of data structures that can be traversed from left to right. -- --- See also . +-- See also /Applicative Programming with Effects/, +-- by Conor McBride and Ross Paterson, online at +-- . module Data.Traversable ( Traversable(..), - sequenceA, - sequence, fmapDefault, foldMapDefault, ) where @@ -23,13 +23,14 @@ module Data.Traversable ( import Prelude hiding (mapM, sequence) import qualified Prelude (mapM) import Control.Applicative +import Data.Foldable (Foldable) import Data.Monoid (Monoid) import Data.Array -- | Functors representing data structures that can be traversed from -- left to right. -- --- Minimal complete definition: 'traverse'. +-- Minimal complete definition: 'traverse' or 'sequenceA'. -- -- Instances are similar to 'Functor', e.g. given a data type -- @@ -45,16 +46,27 @@ import Data.Array -- This is suitable even for abstract types, as the laws for '<*>' -- imply a form of associativity. -- -class Traversable t where +class (Functor t, Foldable t) => Traversable t where -- | Map each element of a structure to an action, evaluate -- these actions from left to right, and collect the results. traverse :: Applicative f => (a -> f b) -> t a -> f (t b) + traverse f = sequenceA . fmap f + + -- | Evaluate each action in the structure from left to right, + -- and collect the results. + sequenceA :: Applicative f => t (f a) -> f (t a) + sequenceA = traverse id -- | Map each element of a structure to an monadic action, evaluate -- these actions from left to right, and collect the results. mapM :: Monad m => (a -> m b) -> t a -> m (t b) mapM f = unwrapMonad . traverse (WrapMonad . f) + -- | Evaluate each monadic action in the structure from left to right, + -- and collect the results. + sequence :: Monad m => t (m a) -> m (t a) + sequence = mapM id + -- instances for Prelude types instance Traversable Maybe where @@ -72,24 +84,12 @@ instance Ix i => Traversable (Array i) where -- general functions --- | Evaluate each action in the structure from left to right, --- and collect the results. -sequenceA :: (Traversable t, Applicative f) => t (f a) -> f (t a) -sequenceA = traverse id - --- | Evaluate each monadic action in the structure from left to right, --- and collect the results. -sequence :: (Traversable t, Monad m) => t (m a) -> m (t a) -sequence = mapM id - --- | Any 'Traversable' can also be made an instance of 'Functor' by --- defining 'fmap' as 'fmapDefault'. +-- | This function may be used as a value for `fmap` in a `Functor` instance. fmapDefault :: Traversable t => (a -> b) -> t a -> t b fmapDefault f = getId . traverse (Id . f) --- | Any 'Traversable' can also be made an instance of --- 'Data.Foldable.Foldable' by defining 'Data.Foldable.foldMap' --- as 'foldMapDefault'. +-- | This function may be used as a value for `Data.Foldable.foldMap` +-- in a `Foldable` instance. foldMapDefault :: (Traversable t, Monoid m) => (a -> m) -> t a -> m foldMapDefault f = getConst . traverse (Const . f) @@ -97,6 +97,9 @@ foldMapDefault f = getConst . traverse (Const . f) newtype Id a = Id { getId :: a } +instance Functor Id where + fmap f (Id x) = Id (f x) + instance Applicative Id where pure = Id Id f <*> Id x = Id (f x)