+++ /dev/null
------------------------------------------------------------------------------
--- |
--- Module : Data.Generics.Aliases
--- Copyright : (c) The University of Glasgow, CWI 2001--2004
--- License : BSD-style (see the file libraries/base/LICENSE)
---
--- Maintainer : libraries@haskell.org
--- Stability : experimental
--- Portability : non-portable (local universal quantification)
---
--- \"Scrap your boilerplate\" --- Generic programming in Haskell
--- 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, mkR,
- ext0, extT, extQ, extM, extMp, extB, extR,
-
- -- * Type synonyms for generic function types
- GenericT,
- GenericQ,
- GenericM,
- GenericB,
- GenericR,
- Generic,
- Generic'(..),
- GenericT'(..),
- GenericQ'(..),
- GenericM'(..),
-
- -- * Inredients of generic functions
- orElse,
-
- -- * Function combinators on generic functions
- recoverMp,
- recoverQ,
- choiceMp,
- choiceQ,
-
- -- * Type extension for unary type constructors
- ext1T,
- ext1M,
- ext1Q,
- ext1R
-
- ) where
-
-#ifdef __HADDOCK__
-import Prelude
-#endif
-import Control.Monad
-import Data.Generics.Basics
-
-------------------------------------------------------------------------------
---
--- Combinators to "make" generic functions
--- We use type-safe cast in a number of ways to make generic functions.
---
-------------------------------------------------------------------------------
-
--- | Make a generic transformation;
--- start from a type-specific case;
--- preserve the term otherwise
---
-mkT :: ( Typeable a
- , Typeable b
- )
- => (b -> b)
- -> a
- -> a
-mkT = extT id
-
-
--- | Make a generic query;
--- start from a type-specific case;
--- return a constant otherwise
---
-mkQ :: ( Typeable a
- , Typeable b
- )
- => r
- -> (b -> r)
- -> a
- -> r
-(r `mkQ` br) a = case cast a of
- Just b -> br b
- Nothing -> r
-
-
--- | Make a generic monadic transformation;
--- start from a type-specific case;
--- resort to return otherwise
---
-mkM :: ( Monad m
- , Typeable a
- , Typeable b
- )
- => (b -> m b)
- -> a
- -> m a
-mkM = extM return
-
-
-{-
-
-For the remaining definitions, we stick to a more concise style, i.e.,
-we fold maybies with "maybe" instead of case ... of ..., and we also
-use a point-free style whenever possible.
-
--}
-
-
--- | 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
- )
- => (b -> m b)
- -> a
- -> m a
-mkMp = extM (const mzero)
-
-
--- | Make a generic builder;
--- start from a type-specific ase;
--- resort to no build (i.e., mzero) otherwise
---
-mkR :: ( MonadPlus m
- , Typeable a
- , Typeable b
- )
- => m b -> m a
-mkR f = mzero `extR` f
-
-
--- | Flexible type extension
-ext0 :: (Typeable a, Typeable b) => c a -> c b -> c a
-ext0 def ext = maybe def id (gcast ext)
-
-
--- | Extend a generic transformation by a type-specific case
-extT :: ( Typeable a
- , Typeable b
- )
- => (a -> a)
- -> (b -> b)
- -> a
- -> a
-extT def ext = unT ((T def) `ext0` (T ext))
-
-
--- | Extend a generic query by a type-specific case
-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
- )
- => (a -> m a) -> (b -> m b) -> a -> m a
-extM def ext = unM ((M def) `ext0` (M ext))
-
-
--- | Extend a generic MonadPlus transformation by a type-specific case
-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 reader
-extR :: ( Monad m
- , Typeable a
- , Typeable b
- )
- => m a -> m b -> m a
-extR def ext = unR ((R def) `ext0` (R ext))
-
-
-
-------------------------------------------------------------------------------
---
--- Type synonyms for generic function types
---
-------------------------------------------------------------------------------
-
-
--- | Generic transformations,
--- i.e., take an \"a\" and return an \"a\"
---
-type GenericT = forall a. Data a => a -> a
-
-
--- | Generic queries of type \"r\",
--- i.e., take any \"a\" and return an \"r\"
---
-type GenericQ r = forall a. Data a => a -> r
-
-
--- | Generic monadic transformations,
--- i.e., take an \"a\" and compute an \"a\"
---
-type GenericM m = forall a. Data a => a -> m a
-
-
--- | 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 GenericR m = forall a. Data a => m a
-
-
--- | The general scheme underlying generic functions
--- assumed by gfoldl; there are isomorphisms such as
--- GenericT = Generic T.
---
-type Generic c = forall a. Data a => a -> c a
-
-
--- | Wrapped generic functions;
--- recall: [Generic c] would be legal but [Generic' c] not.
---
-data Generic' c = Generic' { unGeneric' :: Generic c }
-
-
--- | Other first-class polymorphic wrappers
-newtype GenericT' = GT { unGT :: Data a => a -> a }
-newtype GenericQ' r = GQ { unGQ :: GenericQ r }
-newtype GenericM' m = GM { unGM :: Data a => a -> m a }
-
-
--- | Left-biased choice on maybies
-orElse :: Maybe a -> Maybe a -> Maybe a
-x `orElse` y = case x of
- Just _ -> x
- Nothing -> y
-
-
-{-
-
-The following variations take "orElse" to the function
-level. Furthermore, we generalise from "Maybe" to any
-"MonadPlus". This makes sense for monadic transformations and
-queries. We say that the resulting combinators modell choice. We also
-provide a prime example of choice, that is, recovery from failure. In
-the case of transformations, we recover via return whereas for
-queries a given constant is returned.
-
--}
-
--- | Choice for monadic transformations
-choiceMp :: MonadPlus m => GenericM m -> GenericM m -> GenericM m
-choiceMp f g x = f x `mplus` g x
-
-
--- | Choice for monadic queries
-choiceQ :: MonadPlus m => GenericQ (m r) -> GenericQ (m r) -> GenericQ (m r)
-choiceQ f g x = f x `mplus` g x
-
-
--- | Recover from the failure of monadic transformation by identity
-recoverMp :: MonadPlus m => GenericM m -> GenericM m
-recoverMp f = f `choiceMp` return
-
-
--- | 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)
-
-
-
-------------------------------------------------------------------------------
---
--- Type extension for unary type constructors
---
-------------------------------------------------------------------------------
-
-
-
--- | Flexible type extension
-ext1 :: (Data a, Typeable1 t)
- => c a
- -> (forall a. Data a => c (t a))
- -> c a
-ext1 def ext = maybe def id (dataCast1 ext)
-
-
--- | Type extension of transformations for unary type constructors
-ext1T :: (Data d, Typeable1 t)
- => (forall d. Data d => d -> d)
- -> (forall d. Data d => t d -> t d)
- -> d -> d
-ext1T def ext = unT ((T def) `ext1` (T ext))
-
-
--- | Type extension of monadic transformations for type constructors
-ext1M :: (Monad m, Data d, Typeable1 t)
- => (forall d. Data d => d -> m d)
- -> (forall d. Data d => t d -> m (t d))
- -> d -> m d
-ext1M def ext = unM ((M def) `ext1` (M ext))
-
-
--- | Type extension of queries for type constructors
-ext1Q :: (Data d, Typeable1 t)
- => (d -> q)
- -> (forall d. Data d => t d -> q)
- -> d -> q
-ext1Q def ext = unQ ((Q def) `ext1` (Q ext))
-
-
--- | Type extension of readers for type constructors
-ext1R :: (Monad m, Data d, Typeable1 t)
- => m d
- -> (forall d. Data d => m (t d))
- -> m d
-ext1R def ext = unR ((R def) `ext1` (R ext))
-
-
-
-------------------------------------------------------------------------------
---
--- Type constructors for type-level lambdas
---
-------------------------------------------------------------------------------
-
-
--- | The type constructor for transformations
-newtype T x = T { unT :: x -> x }
-
--- | The type constructor for transformations
-newtype M m x = M { unM :: x -> m x }
-
--- | The type constructor for queries
-newtype Q q x = Q { unQ :: x -> q }
-
--- | The type constructor for readers
-newtype R m x = R { unR :: m x }