X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=Data%2FGenerics%2FSchemes.hs;h=c783d4adf1edcdf6a9d308561c71b06413f283f8;hb=0d6c1599c246100deb2fa54315811ed94d1a300c;hp=f88445c0f3385c66758f975c2e605604834528cd;hpb=9cee8583f9df2bd87dff1d5461bdfdb2cc094de6;p=ghc-base.git diff --git a/Data/Generics/Schemes.hs b/Data/Generics/Schemes.hs index f88445c..c783d4a 100644 --- a/Data/Generics/Schemes.hs +++ b/Data/Generics/Schemes.hs @@ -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, Data 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