X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=Data%2FGenerics%2FSchemes.hs;h=5234b01a4804197c1e382e776fdb143bfd58476b;hb=9185a42d2848131d1272e79cf1e04430fb96b6d0;hp=c9aa40fac803cb08b89b90d1acb1cd32f9876715;hpb=83819904a18aa04e78ad1476a1640cce8388f470;p=ghc-base.git diff --git a/Data/Generics/Schemes.hs b/Data/Generics/Schemes.hs index c9aa40f..5234b01 100644 --- a/Data/Generics/Schemes.hs +++ b/Data/Generics/Schemes.hs @@ -9,13 +9,13 @@ -- Portability : non-portable -- -- \"Scrap your boilerplate\" --- Generic programming in Haskell --- See . +-- See . The present module provides +-- frequently used generic traversal schemes. -- ----------------------------------------------------------------------------- module Data.Generics.Schemes ( - -- * Frequently used generic traversal schemes everywhere, everywhere', everywhereBut, @@ -25,17 +25,26 @@ module Data.Generics.Schemes ( listify, something, 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) @@ -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 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