1 -----------------------------------------------------------------------------
3 -- Module : Data.Generics.Aliases
4 -- Copyright : (c) The University of Glasgow, CWI 2001--2004
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 ext0, 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 -- * Type extension for unary type constructors
57 import Data.Generics.Basics
59 ------------------------------------------------------------------------------
61 -- Combinators to "make" generic functions
62 -- We use type-safe cast in a number of ways to make generic functions.
64 ------------------------------------------------------------------------------
66 -- | Make a generic transformation;
67 -- start from a type-specific case;
68 -- preserve the term otherwise
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
111 For the remaining definitions, we stick to a more concise style, i.e.,
112 we fold maybies with "maybe" instead of case ... of ..., and we also
113 use a point-free style whenever possible.
118 -- | Make a generic monadic transformation for MonadPlus;
119 -- use \"const mzero\" (i.e., failure) instead of return as default.
121 mkMp :: ( MonadPlus m
128 mkMp = extM (const mzero)
131 -- | Make a generic builder;
132 -- start from a type-specific ase;
133 -- resort to no build (i.e., mzero) otherwise
140 mkR f = mzero `extR` f
143 -- | Flexible type extension
144 ext0 :: (Typeable a, Typeable b) => c a -> c b -> c a
145 ext0 def ext = maybe def id (gcast ext)
148 -- | Extend a generic transformation by a type-specific case
156 extT def ext = unT ((T def) `ext0` (T ext))
159 -- | Extend a generic query by a type-specific case
167 extQ f g a = maybe (f a) g (cast a)
170 -- | Extend a generic monadic transformation by a type-specific case
175 => (a -> m a) -> (b -> m b) -> a -> m a
176 extM def ext = unM ((M def) `ext0` (M ext))
179 -- | Extend a generic MonadPlus transformation by a type-specific case
180 extMp :: ( MonadPlus m
184 => (a -> m a) -> (b -> m b) -> a -> m a
188 -- | Extend a generic builder
193 extB a = maybe a id . cast
196 -- | Extend a generic reader
202 extR def ext = unR ((R def) `ext0` (R ext))
206 ------------------------------------------------------------------------------
208 -- Type synonyms for generic function types
210 ------------------------------------------------------------------------------
213 -- | Generic transformations,
214 -- i.e., take an \"a\" and return an \"a\"
216 type GenericT = forall a. Data a => a -> a
219 -- | Generic queries of type \"r\",
220 -- i.e., take any \"a\" and return an \"r\"
222 type GenericQ r = forall a. Data a => a -> r
225 -- | Generic monadic transformations,
226 -- i.e., take an \"a\" and compute an \"a\"
228 type GenericM m = forall a. Data a => a -> m a
231 -- | Generic builders
232 -- i.e., produce an \"a\".
234 type GenericB = forall a. Data a => a
237 -- | Generic readers, say monadic builders,
238 -- i.e., produce an \"a\" with the help of a monad \"m\".
240 type GenericR m = forall a. Data a => m a
243 -- | The general scheme underlying generic functions
244 -- assumed by gfoldl; there are isomorphisms such as
245 -- GenericT = Generic T.
247 type Generic c = forall a. Data a => a -> c a
250 -- | Wrapped generic functions;
251 -- recall: [Generic c] would be legal but [Generic' c] not.
253 data Generic' c = Generic' { unGeneric' :: Generic c }
256 -- | Other first-class polymorphic wrappers
257 newtype GenericT' = GT { unGT :: Data a => a -> a }
258 newtype GenericQ' r = GQ { unGQ :: GenericQ r }
259 newtype GenericM' m = GM { unGM :: Data a => a -> m a }
262 -- | Left-biased choice on maybies
263 orElse :: Maybe a -> Maybe a -> Maybe a
264 x `orElse` y = case x of
271 The following variations take "orElse" to the function
272 level. Furthermore, we generalise from "Maybe" to any
273 "MonadPlus". This makes sense for monadic transformations and
274 queries. We say that the resulting combinators modell choice. We also
275 provide a prime example of choice, that is, recovery from failure. In
276 the case of transformations, we recover via return whereas for
277 queries a given constant is returned.
281 -- | Choice for monadic transformations
282 choiceMp :: MonadPlus m => GenericM m -> GenericM m -> GenericM m
283 choiceMp f g x = f x `mplus` g x
286 -- | Choice for monadic queries
287 choiceQ :: MonadPlus m => GenericQ (m r) -> GenericQ (m r) -> GenericQ (m r)
288 choiceQ f g x = f x `mplus` g x
291 -- | Recover from the failure of monadic transformation by identity
292 recoverMp :: MonadPlus m => GenericM m -> GenericM m
293 recoverMp f = f `choiceMp` return
296 -- | Recover from the failure of monadic query by a constant
297 recoverQ :: MonadPlus m => r -> GenericQ (m r) -> GenericQ (m r)
298 recoverQ r f = f `choiceQ` const (return r)
302 ------------------------------------------------------------------------------
304 -- Type extension for unary type constructors
306 ------------------------------------------------------------------------------
310 -- | Flexible type extension
311 ext1 :: (Data a, Typeable1 t)
313 -> (forall a. Data a => c (t a))
315 ext1 def ext = maybe def id (dataCast1 ext)
318 -- | Type extension of transformations for unary type constructors
319 ext1T :: (Data d, Typeable1 t)
320 => (forall d. Data d => d -> d)
321 -> (forall d. Data d => t d -> t d)
323 ext1T def ext = unT ((T def) `ext1` (T ext))
326 -- | Type extension of monadic transformations for type constructors
327 ext1M :: (Monad m, Data d, Typeable1 t)
328 => (forall d. Data d => d -> m d)
329 -> (forall d. Data d => t d -> m (t d))
331 ext1M def ext = unM ((M def) `ext1` (M ext))
334 -- | Type extension of queries for type constructors
335 ext1Q :: (Data d, Typeable1 t)
337 -> (forall d. Data d => t d -> q)
339 ext1Q def ext = unQ ((Q def) `ext1` (Q ext))
342 -- | Type extension of readers for type constructors
343 ext1R :: (Monad m, Data d, Typeable1 t)
345 -> (forall d. Data d => m (t d))
347 ext1R def ext = unR ((R def) `ext1` (R ext))
351 ------------------------------------------------------------------------------
353 -- Type constructors for type-level lambdas
355 ------------------------------------------------------------------------------
358 -- | The type constructor for transformations
359 newtype T x = T { unT :: x -> x }
361 -- | The type constructor for transformations
362 newtype M m x = M { unM :: x -> m x }
364 -- | The type constructor for queries
365 newtype Q q x = Q { unQ :: x -> q }
367 -- | The type constructor for readers
368 newtype R m x = R { unR :: m x }