module Data.Data.Extended
    ( module Data.Data

    , grecQ
    , grecT
    ) where

import           Data.Data

-- | Recursively find all values of a certain type.
grecQ :: (Data a, Data b) => a -> [b]
grecQ :: forall a b. (Data a, Data b) => a -> [b]
grecQ = forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a u. Data a => (forall d. Data d => d -> u) -> a -> [u]
gmapQ (\d
x -> forall b a. b -> (a -> b) -> Maybe a -> b
maybe forall a. a -> a
id (:) (forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast d
x) forall a b. (a -> b) -> a -> b
$ forall a b. (Data a, Data b) => a -> [b]
grecQ d
x)

-- | Recursively apply an update to a certain type.
grecT :: (Data a, Data b) => (a -> a) -> b -> b
grecT :: forall a b. (Data a, Data b) => (a -> a) -> b -> b
grecT a -> a
f b
x = forall a. Data a => (forall b. Data b => b -> b) -> a -> a
gmapT (forall a b. (Data a, Data b) => (a -> a) -> b -> b
grecT a -> a
f) (forall a b. (Typeable a, Typeable b) => (a -> a) -> b -> b
castMap a -> a
f b
x)

castMap :: (Typeable a, Typeable b) => (a -> a) -> b -> b
castMap :: forall a b. (Typeable a, Typeable b) => (a -> a) -> b -> b
castMap a -> a
f b
x = case forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast b
x of
    Maybe a
Nothing -> b
x
    Just a
y  -> case forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast (a -> a
f a
y) of
        Maybe b
Nothing -> b
x
        Just b
z  -> b
z