X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=Data%2FGenerics%2FSchemes.hs;h=4e75a823a020a01c338052ac03b94b00edf51579;hb=e0d697e559faf32d4b9f034c0968c1a299dd74c5;hp=c9aa40fac803cb08b89b90d1acb1cd32f9876715;hpb=83819904a18aa04e78ad1476a1640cce8388f470;p=ghc-base.git diff --git a/Data/Generics/Schemes.hs b/Data/Generics/Schemes.hs index c9aa40f..4e75a82 100644 --- a/Data/Generics/Schemes.hs +++ b/Data/Generics/Schemes.hs @@ -6,36 +6,45 @@ -- -- Maintainer : libraries@haskell.org -- Stability : experimental --- Portability : non-portable +-- Portability : non-portable (local universal quantification) -- -- \"Scrap your boilerplate\" --- Generic programming in Haskell --- See . +-- See . The present module provides +-- frequently used generic traversal schemes. -- ----------------------------------------------------------------------------- -module Data.Generics.Schemes ( +module Data.Generics.Schemes ( - -- * Frequently used generic traversal schemes everywhere, everywhere', everywhereBut, everywhereM, somewhere, - everything, - listify, + everything, + listify, something, - synthesize, + synthesize, + gsize, + glength, + gdepth, + gcount, + gnodecount, + gtypecount, + gfindtype ) where ------------------------------------------------------------------------------ +#ifdef __HADDOCK__ +import Prelude +#endif import Data.Generics.Basics import Data.Generics.Aliases import Control.Monad - -- | Apply a transformation everywhere in bottom-up manner everywhere :: (forall a. Data a => a -> a) -> (forall a. Data a => a -> a) @@ -89,7 +98,7 @@ everything :: (r -> r -> r) -> GenericQ r -> GenericQ r -- use gmapQ to recurse into immediate subterms; -- use ordinary foldl to reduce list of intermediate results -- -everything k f x +everything k f x = foldl k (f x) (gmapQ (everything k f) x) @@ -111,7 +120,49 @@ something = everything orElse -- | Bottom-up synthesis of a data structure; -- 1st argument z is the initial element for the synthesis; -- 2nd argument o is for reduction of results from subterms; --- 3rd argument f updates the sythesised data according to the given term +-- 3rd argument f updates the synthesised data according to the given term -- -synthesize :: s -> (s -> s -> s) -> GenericQ (s -> s) -> GenericQ s +synthesize :: s -> (t -> s -> s) -> GenericQ (s -> t) -> GenericQ t synthesize z o f x = f x (foldr o z (gmapQ (synthesize z o f) x)) + + +-- | Compute size of an arbitrary data structure +gsize :: Data a => a -> Int +gsize t = 1 + sum (gmapQ gsize t) + + +-- | Count the number of immediate subterms of the given term +glength :: GenericQ Int +glength = length . gmapQ (const ()) + + +-- | Determine depth of the given term +gdepth :: GenericQ Int +gdepth = (+) 1 . foldr max 0 . gmapQ gdepth + + +-- | Determine the number of all suitable nodes in a given term +gcount :: GenericQ Bool -> GenericQ Int +gcount p = everything (+) (\x -> if p x then 1 else 0) + + +-- | Determine the number of all nodes in a given term +gnodecount :: GenericQ Int +gnodecount = gcount (const True) + + +-- | Determine the number of nodes of a given type in a given term +gtypecount :: Typeable a => a -> GenericQ Int +gtypecount (_::a) = gcount (False `mkQ` (\(_::a) -> True)) + + +-- | Find (unambiguously) an immediate subterm of a given type +gfindtype :: (Data x, Typeable y) => x -> Maybe y +gfindtype = singleton + . foldl unJust [] + . gmapQ (Nothing `mkQ` Just) + where + unJust l (Just x) = x:l + unJust l Nothing = l + singleton [s] = Just s + singleton _ = Nothing