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
33 -- * Inredients of generic functions
36 -- * Function combinators on generic functions
42 -- * Operators for (over-appreciated) unfolding
52 import Data.Generics.Basics
54 ------------------------------------------------------------------------------
56 -- Combinators to "make" generic functions
57 -- We use type-safe cast in a number of ways to make generic functions.
59 ------------------------------------------------------------------------------
61 -- | Make a generic transformation;
62 -- start from a type-specific case;
63 -- preserve the term otherwise
71 mkT f = case cast f of
76 -- | Make a generic query;
77 -- start from a type-specific case;
78 -- return a constant otherwise
87 (r `mkQ` br) a = case cast a of
92 -- | Make a generic monadic transformation;
93 -- start from a type-specific case;
94 -- resort to return otherwise
103 mkM f = case castarr f of
110 For the remaining definitions, we stick to a more concise style, i.e.,
111 we fold maybies with "maybe" instead of case ... of ..., and we also
112 use a point-free style whenever possible.
117 -- | Make a generic monadic transformation for MonadPlus;
118 -- use \"const mzero\" (i.e., failure) instead of return as default.
120 mkMp :: ( MonadPlus m
127 mkMp = maybe (const mzero) id . castarr
130 -- | Make a generic builder;
131 -- start from a type-specific ase;
132 -- resort to no build (i.e., mzero) otherwise
139 mkR = maybe mzero id . castss
142 -- | Extend a generic transformation by a type-specific case
150 extT f = maybe f id . cast
153 -- | Extend a generic query by a type-specific case
161 extQ f g a = maybe (f a) g (cast a)
164 -- | Extend a generic monadic transformation by a type-specific case
169 => (a -> m a) -> (b -> m b) -> a -> m a
170 extM f = maybe f id . castarr
173 -- | Extend a generic MonadPlus transformation by a type-specific case
174 extMp :: ( MonadPlus m
178 => (a -> m a) -> (b -> m b) -> a -> m a
182 -- | Extend a generic builder
187 extB a = maybe a id . cast
190 -- | Extend a generic reader
196 extR f = maybe f id . castss
199 ------------------------------------------------------------------------------
201 -- Type synonyms for generic function types
203 ------------------------------------------------------------------------------
206 -- | Generic transformations,
207 -- i.e., take an \"a\" and return an \"a\"
209 type GenericT = forall a. Data a => a -> a
212 -- | Generic queries of type \"r\",
213 -- i.e., take any \"a\" and return an \"r\"
215 type GenericQ r = forall a. Data a => a -> r
218 -- | Generic monadic transformations,
219 -- i.e., take an \"a\" and compute an \"a\"
221 type GenericM m = forall a. Data a => a -> m a
224 -- | Generic builders
225 -- i.e., produce an \"a\".
227 type GenericB = forall a. Data a => a
230 -- | Generic readers, say monadic builders,
231 -- i.e., produce an \"a\" with the help of a monad \"m\".
233 type GenericR m = forall a. Data a => m a
236 -- | The general scheme underlying generic functions
237 -- assumed by gfoldl; there are isomorphisms such as
238 -- GenericT = Generic ID.
240 type Generic c = forall a. Data a => a -> c a
243 -- | Wrapped generic functions;
244 -- recall: [Generic c] would be legal but [Generic' c] not.
246 data Generic' c = Generic' { unGeneric' :: Generic c }
250 -- | Left-biased choice on maybies
251 orElse :: Maybe a -> Maybe a -> Maybe a
252 x `orElse` y = case x of
259 The following variations take "orElse" to the function
260 level. Furthermore, we generalise from "Maybe" to any
261 "MonadPlus". This makes sense for monadic transformations and
262 queries. We say that the resulting combinators modell choice. We also
263 provide a prime example of choice, that is, recovery from failure. In
264 the case of transformations, we recover via return whereas for
265 queries a given constant is returned.
269 -- | Choice for monadic transformations
270 choiceMp :: MonadPlus m => GenericM m -> GenericM m -> GenericM m
271 choiceMp f g x = f x `mplus` g x
274 -- | Choice for monadic queries
275 choiceQ :: MonadPlus m => GenericQ (m r) -> GenericQ (m r) -> GenericQ (m r)
276 choiceQ f g x = f x `mplus` g x
279 -- | Recover from the failure of monadic transformation by identity
280 recoverMp :: MonadPlus m => GenericM m -> GenericM m
281 recoverMp f = f `choiceMp` return
284 -- | Recover from the failure of monadic query by a constant
285 recoverQ :: MonadPlus m => r -> GenericQ (m r) -> GenericQ (m r)
286 recoverQ r f = f `choiceQ` const (return r)
290 ------------------------------------------------------------------------------
294 ------------------------------------------------------------------------------
296 -- | Construct an initial term with undefined immediate subterms
297 -- and then map over the skeleton to fill in proper terms.
300 -> (forall a. Data a => a)
302 gunfoldB c f = gmapT (const f) (fromConstr c)
305 -- | Monadic variation on \"gunfoldB\"
306 gunfoldR :: (Monad m, Data a)
308 -> (forall a. Data a => m a)
310 gunfoldR c f = gmapM (const f) $ fromConstr c