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