1 -----------------------------------------------------------------------------
3 -- Module : Data.Generics.Aliases
4 -- Copyright : (c) The University of Glasgow, CWI 2001--2003
5 -- License : BSD-style (see the file libraries/base/LICENSE)
7 -- Maintainer : libraries@haskell.org
8 -- Stability : experimental
9 -- Portability : non-portable
11 -- \"Scrap your boilerplate\" --- Generic programming in Haskell
12 -- See <http://www.cs.vu.nl/boilerplate/>. The present module provides
13 -- a number of declarations for typical generic function types,
14 -- corresponding type case, and others.
16 -----------------------------------------------------------------------------
18 module Data.Generics.Aliases (
20 -- * Combinators to \"make\" generic functions via cast
21 mkT, mkQ, mkM, mkMp, mkR,
22 extT, extQ, extM, extMp, extB, extR,
24 -- * Type synonyms for generic function types
36 -- * Inredients of generic functions
39 -- * Function combinators on generic functions
45 -- * Operators for (over-appreciated) unfolding
55 import Data.Generics.Basics
57 ------------------------------------------------------------------------------
59 -- Combinators to "make" generic functions
60 -- We use type-safe cast in a number of ways to make generic functions.
62 ------------------------------------------------------------------------------
64 -- | Make a generic transformation;
65 -- start from a type-specific case;
66 -- preserve the term otherwise
74 mkT f = case cast f of
79 -- | Make a generic query;
80 -- start from a type-specific case;
81 -- return a constant otherwise
90 (r `mkQ` br) a = case cast a of
95 -- | Make a generic monadic transformation;
96 -- start from a type-specific case;
97 -- resort to return otherwise
106 mkM f = case castarr f of
113 For the remaining definitions, we stick to a more concise style, i.e.,
114 we fold maybies with "maybe" instead of case ... of ..., and we also
115 use a point-free style whenever possible.
120 -- | Make a generic monadic transformation for MonadPlus;
121 -- use \"const mzero\" (i.e., failure) instead of return as default.
123 mkMp :: ( MonadPlus m
130 mkMp = maybe (const mzero) id . castarr
133 -- | Make a generic builder;
134 -- start from a type-specific ase;
135 -- resort to no build (i.e., mzero) otherwise
142 mkR = maybe mzero id . castss
145 -- | Extend a generic transformation by a type-specific case
153 extT f = maybe f id . cast
156 -- | Extend a generic query by a type-specific case
164 extQ f g a = maybe (f a) g (cast a)
167 -- | Extend a generic monadic transformation by a type-specific case
172 => (a -> m a) -> (b -> m b) -> a -> m a
173 extM f = maybe f id . castarr
176 -- | Extend a generic MonadPlus transformation by a type-specific case
177 extMp :: ( MonadPlus m
181 => (a -> m a) -> (b -> m b) -> a -> m a
185 -- | Extend a generic builder
190 extB a = maybe a id . cast
193 -- | Extend a generic reader
199 extR f = maybe f id . castss
202 ------------------------------------------------------------------------------
204 -- Type synonyms for generic function types
206 ------------------------------------------------------------------------------
209 -- | Generic transformations,
210 -- i.e., take an \"a\" and return an \"a\"
212 type GenericT = forall a. Data a => a -> a
215 -- | Generic queries of type \"r\",
216 -- i.e., take any \"a\" and return an \"r\"
218 type GenericQ r = forall a. Data a => a -> r
221 -- | Generic monadic transformations,
222 -- i.e., take an \"a\" and compute an \"a\"
224 type GenericM m = forall a. Data a => a -> m a
227 -- | Generic builders
228 -- i.e., produce an \"a\".
230 type GenericB = forall a. Data a => a
233 -- | Generic readers, say monadic builders,
234 -- i.e., produce an \"a\" with the help of a monad \"m\".
236 type GenericR m = forall a. Data a => m a
239 -- | The general scheme underlying generic functions
240 -- assumed by gfoldl; there are isomorphisms such as
241 -- GenericT = Generic ID.
243 type Generic c = forall a. Data a => a -> c a
246 -- | Wrapped generic functions;
247 -- recall: [Generic c] would be legal but [Generic' c] not.
249 data Generic' c = Generic' { unGeneric' :: Generic c }
252 -- | Other first-class polymorphic wrappers
253 newtype GenericT' = GenericT' { unGenericT' :: Data a => a -> a }
254 newtype GenericQ' r = GenericQ' { unGenericQ' :: GenericQ r }
255 newtype GenericM' m = GenericM' { unGenericM' :: Data a => a -> m a }
258 -- | Left-biased choice on maybies
259 orElse :: Maybe a -> Maybe a -> Maybe a
260 x `orElse` y = case x of
267 The following variations take "orElse" to the function
268 level. Furthermore, we generalise from "Maybe" to any
269 "MonadPlus". This makes sense for monadic transformations and
270 queries. We say that the resulting combinators modell choice. We also
271 provide a prime example of choice, that is, recovery from failure. In
272 the case of transformations, we recover via return whereas for
273 queries a given constant is returned.
277 -- | Choice for monadic transformations
278 choiceMp :: MonadPlus m => GenericM m -> GenericM m -> GenericM m
279 choiceMp f g x = f x `mplus` g x
282 -- | Choice for monadic queries
283 choiceQ :: MonadPlus m => GenericQ (m r) -> GenericQ (m r) -> GenericQ (m r)
284 choiceQ f g x = f x `mplus` g x
287 -- | Recover from the failure of monadic transformation by identity
288 recoverMp :: MonadPlus m => GenericM m -> GenericM m
289 recoverMp f = f `choiceMp` return
292 -- | Recover from the failure of monadic query by a constant
293 recoverQ :: MonadPlus m => r -> GenericQ (m r) -> GenericQ (m r)
294 recoverQ r f = f `choiceQ` const (return r)
298 ------------------------------------------------------------------------------
302 ------------------------------------------------------------------------------
304 -- | Construct an initial term with undefined immediate subterms
305 -- and then map over the skeleton to fill in proper terms.
308 -> (forall a. Data a => a)
310 gunfoldB c f = gmapT (const f) (fromConstr c)
313 -- | Monadic variation on \"gunfoldB\"
314 gunfoldR :: (Monad m, Data a)
316 -> (forall a. Data a => m a)
318 gunfoldR c f = gmapM (const f) $ fromConstr c