-- Portability : non-portable
--
-- \"Scrap your boilerplate\" --- Generic programming in Haskell
--- See <http://www.cs.vu.nl/boilerplate/>.
+-- See <http://www.cs.vu.nl/boilerplate/>. The present module provides
+-- a number of declarations for typical generic function types,
+-- corresponding type case, and others.
--
-----------------------------------------------------------------------------
module Data.Generics.Aliases (
-- * Combinators to \"make\" generic functions via cast
- mkT, mkQ, mkM, mkMp, mkB,
- extT, extQ, extM, extMp, extB,
+ mkT, mkQ, mkM, mkMp, mkR,
+ extT, extQ, extM, extMp, extB, extR,
-- * Type synonyms for generic function types
GenericT,
GenericQ,
GenericM,
GenericB,
+ GenericR,
Generic,
Generic'(..),
recoverMp,
recoverQ,
choiceMp,
- choiceQ
+ choiceQ,
- ) where
+ -- * Operators for (over-appreciated) unfolding
+ gunfoldB,
+ gunfoldR
+ ) where
+#ifdef __HADDOCK__
+import Prelude
+#endif
import Control.Monad
import Data.Generics.Basics
-
-
------------------------------------------------------------------------------
--
-- Combinators to "make" generic functions
-- start from a type-specific case;
-- preserve the term otherwise
--
-mkT :: (Typeable a, Typeable b) => (b -> b) -> a -> a
+mkT :: ( Typeable a
+ , Typeable b
+ )
+ => (b -> b)
+ -> a
+ -> a
mkT f = case cast f of
Just g -> g
Nothing -> id
-- start from a type-specific case;
-- return a constant otherwise
--
-mkQ :: (Typeable a, Typeable b) => r -> (b -> r) -> a -> r
+mkQ :: ( Typeable a
+ , Typeable b
+ )
+ => r
+ -> (b -> r)
+ -> a
+ -> r
(r `mkQ` br) a = case cast a of
Just b -> br b
Nothing -> r
-- start from a type-specific case;
-- resort to return otherwise
--
-mkM :: ( Monad m,
- Typeable a,
- Typeable b
+mkM :: ( Monad m
+ , Typeable a
+ , Typeable b
)
- => (b -> m b) -> a -> m a
+ => (b -> m b)
+ -> a
+ -> m a
mkM f = case castarr f of
Just g -> g
Nothing -> return
-- | Make a generic monadic transformation for MonadPlus;
-- use \"const mzero\" (i.e., failure) instead of return as default.
--
-mkMp :: ( MonadPlus m,
- Typeable a,
- Typeable b
+mkMp :: ( MonadPlus m
+ , Typeable a
+ , Typeable b
)
- => (b -> m b) -> a -> m a
+ => (b -> m b)
+ -> a
+ -> m a
mkMp = maybe (const mzero) id . castarr
-- start from a type-specific ase;
-- resort to no build (i.e., mzero) otherwise
--
-mkB :: ( MonadPlus m,
- Typeable a,
- Typeable b
+mkR :: ( MonadPlus m
+ , Typeable a
+ , Typeable b
)
=> m b -> m a
-mkB = maybe mzero id . castss
+mkR = maybe mzero id . castss
-- | Extend a generic transformation by a type-specific case
-extT :: (Typeable a, Typeable b) => (a -> a) -> (b -> b) -> a -> a
+extT :: ( Typeable a
+ , Typeable b
+ )
+ => (a -> a)
+ -> (b -> b)
+ -> a
+ -> a
extT f = maybe f id . cast
-- | Extend a generic query by a type-specific case
-extQ :: (Typeable a, Typeable b) => (a -> q) -> (b -> q) -> a -> q
+extQ :: ( Typeable a
+ , Typeable b
+ )
+ => (a -> q)
+ -> (b -> q)
+ -> a
+ -> q
extQ f g a = maybe (f a) g (cast a)
-- | Extend a generic monadic transformation by a type-specific case
-extM :: ( Monad m,
- Typeable a,
- Typeable b
+extM :: ( Monad m
+ , Typeable a
+ , Typeable b
)
=> (a -> m a) -> (b -> m b) -> a -> m a
extM f = maybe f id . castarr
-- | Extend a generic MonadPlus transformation by a type-specific case
-extMp :: ( MonadPlus m,
- Typeable a,
- Typeable b
+extMp :: ( MonadPlus m
+ , Typeable a
+ , Typeable b
)
=> (a -> m a) -> (b -> m b) -> a -> m a
extMp = extM
+-- | Extend a generic builder
+extB :: ( Typeable a
+ , Typeable b
+ )
+ => a -> b -> a
+extB a = maybe a id . cast
--- | Extend a generic builder by a type-specific case
-extB :: (Monad m,
- Typeable a,
- Typeable b
+
+-- | Extend a generic reader
+extR :: ( Monad m
+ , Typeable a
+ , Typeable b
)
=> m a -> m b -> m a
-extB f = maybe f id . castss
+extR f = maybe f id . castss
------------------------------------------------------------------------------
type GenericM m = forall a. Data a => a -> m a
--- | Generic monadic builders with input i,
+-- | Generic builders
+-- i.e., produce an \"a\".
+--
+type GenericB = forall a. Data a => a
+
+
+-- | Generic readers, say monadic builders,
-- i.e., produce an \"a\" with the help of a monad \"m\".
--
-type GenericB m = forall a. Data a => m a
+type GenericR m = forall a. Data a => m a
-- | The general scheme underlying generic functions
-- | Recover from the failure of monadic query by a constant
recoverQ :: MonadPlus m => r -> GenericQ (m r) -> GenericQ (m r)
recoverQ r f = f `choiceQ` const (return r)
+
+
+
+------------------------------------------------------------------------------
+--
+-- Generic unfolding
+--
+------------------------------------------------------------------------------
+
+-- | Construct an initial term with undefined immediate subterms
+-- and then map over the skeleton to fill in proper terms.
+gunfoldB :: Data a
+ => Constr
+ -> (forall a. Data a => a)
+ -> a
+gunfoldB c f = gmapT (const f) (fromConstr c)
+
+
+-- | Monadic variation on \"gunfoldB\"
+gunfoldR :: (Monad m, Data a)
+ => Constr
+ -> (forall a. Data a => m a)
+ -> m a
+gunfoldR c f = gmapM (const f) $ fromConstr c