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 :: a -> [b]
grecQ = [[b]] -> [b]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[b]] -> [b]) -> (a -> [[b]]) -> a -> [b]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall d. Data d => d -> [b]) -> a -> [[b]]
forall a u. Data a => (forall d. Data d => d -> u) -> a -> [u]
gmapQ (\d
x -> ([b] -> [b]) -> (b -> [b] -> [b]) -> Maybe b -> [b] -> [b]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [b] -> [b]
forall a. a -> a
id (:) (d -> Maybe b
forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast d
x) ([b] -> [b]) -> [b] -> [b]
forall a b. (a -> b) -> a -> b
$ d -> [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 :: (a -> a) -> b -> b
grecT a -> a
f b
x = (forall b. Data b => b -> b) -> b -> b
forall a. Data a => (forall b. Data b => b -> b) -> a -> a
gmapT ((a -> a) -> b -> b
forall a b. (Data a, Data b) => (a -> a) -> b -> b
grecT a -> a
f) ((a -> a) -> b -> b
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 :: (a -> a) -> b -> b
castMap a -> a
f b
x = case b -> Maybe a
forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast b
x of
    Maybe a
Nothing -> b
x
    Just a
y  -> case a -> Maybe b
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