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 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
49 -- * Type extension for unary type constructors
61 import Data.Generics.Basics
63 ------------------------------------------------------------------------------
65 -- Combinators to "make" generic functions
66 -- We use type-safe cast in a number of ways to make generic functions.
68 ------------------------------------------------------------------------------
70 -- | Make a generic transformation;
71 -- start from a type-specific case;
72 -- preserve the term otherwise
80 mkT f = case cast f of
85 -- | Make a generic query;
86 -- start from a type-specific case;
87 -- return a constant otherwise
96 (r `mkQ` br) a = case cast a of
101 -- | Make a generic monadic transformation;
102 -- start from a type-specific case;
103 -- resort to return otherwise
117 For the remaining definitions, we stick to a more concise style, i.e.,
118 we fold maybies with "maybe" instead of case ... of ..., and we also
119 use a point-free style whenever possible.
124 -- | Make a generic monadic transformation for MonadPlus;
125 -- use \"const mzero\" (i.e., failure) instead of return as default.
127 mkMp :: ( MonadPlus m
134 mkMp = extM (const mzero)
137 -- | Make a generic builder;
138 -- start from a type-specific ase;
139 -- resort to no build (i.e., mzero) otherwise
146 mkR f = mzero `extR` f
149 -- | Flexible type extension
150 ext0 :: (Typeable a, Typeable b) => c a -> c b -> c a
151 ext0 def ext = maybe def id (cast0 ext)
154 -- | Extend a generic transformation by a type-specific case
162 extT f = maybe f id . cast
165 -- | Extend a generic query by a type-specific case
173 extQ f g a = maybe (f a) g (cast a)
176 -- | Extend a generic monadic transformation by a type-specific case
181 => (a -> m a) -> (b -> m b) -> a -> m a
182 extM def ext = unM ((M def) `ext0` (M ext))
185 -- | Extend a generic MonadPlus transformation by a type-specific case
186 extMp :: ( MonadPlus m
190 => (a -> m a) -> (b -> m b) -> a -> m a
194 -- | Extend a generic builder
199 extB a = maybe a id . cast
202 -- | Extend a generic reader
208 extR def ext = unR ((R def) `ext0` (R ext))
212 ------------------------------------------------------------------------------
214 -- Type synonyms for generic function types
216 ------------------------------------------------------------------------------
219 -- | Generic transformations,
220 -- i.e., take an \"a\" and return an \"a\"
222 type GenericT = forall a. Data a => a -> a
225 -- | Generic queries of type \"r\",
226 -- i.e., take any \"a\" and return an \"r\"
228 type GenericQ r = forall a. Data a => a -> r
231 -- | Generic monadic transformations,
232 -- i.e., take an \"a\" and compute an \"a\"
234 type GenericM m = forall a. Data a => a -> m a
237 -- | Generic builders
238 -- i.e., produce an \"a\".
240 type GenericB = forall a. Data a => a
243 -- | Generic readers, say monadic builders,
244 -- i.e., produce an \"a\" with the help of a monad \"m\".
246 type GenericR m = forall a. Data a => m a
249 -- | The general scheme underlying generic functions
250 -- assumed by gfoldl; there are isomorphisms such as
251 -- GenericT = Generic T.
253 type Generic c = forall a. Data a => a -> c a
256 -- | Wrapped generic functions;
257 -- recall: [Generic c] would be legal but [Generic' c] not.
259 data Generic' c = Generic' { unGeneric' :: Generic c }
262 -- | Other first-class polymorphic wrappers
263 newtype GenericT' = GT { unGT :: Data a => a -> a }
264 newtype GenericQ' r = GQ { unGQ :: GenericQ r }
265 newtype GenericM' m = GM { unGM :: Data a => a -> m a }
268 -- | Left-biased choice on maybies
269 orElse :: Maybe a -> Maybe a -> Maybe a
270 x `orElse` y = case x of
277 The following variations take "orElse" to the function
278 level. Furthermore, we generalise from "Maybe" to any
279 "MonadPlus". This makes sense for monadic transformations and
280 queries. We say that the resulting combinators modell choice. We also
281 provide a prime example of choice, that is, recovery from failure. In
282 the case of transformations, we recover via return whereas for
283 queries a given constant is returned.
287 -- | Choice for monadic transformations
288 choiceMp :: MonadPlus m => GenericM m -> GenericM m -> GenericM m
289 choiceMp f g x = f x `mplus` g x
292 -- | Choice for monadic queries
293 choiceQ :: MonadPlus m => GenericQ (m r) -> GenericQ (m r) -> GenericQ (m r)
294 choiceQ f g x = f x `mplus` g x
297 -- | Recover from the failure of monadic transformation by identity
298 recoverMp :: MonadPlus m => GenericM m -> GenericM m
299 recoverMp f = f `choiceMp` return
302 -- | Recover from the failure of monadic query by a constant
303 recoverQ :: MonadPlus m => r -> GenericQ (m r) -> GenericQ (m r)
304 recoverQ r f = f `choiceQ` const (return r)
308 ------------------------------------------------------------------------------
312 ------------------------------------------------------------------------------
314 -- | Construct an initial term with undefined immediate subterms
315 -- and then map over the skeleton to fill in proper terms.
318 -> (forall a. Data a => a)
320 gunfoldB c f = gmapT (const f) (fromConstr c)
323 -- | Monadic variation on \"gunfoldB\"
324 gunfoldR :: (Monad m, Data a)
326 -> (forall a. Data a => m a)
328 gunfoldR c f = gmapM (const f) $ fromConstr c
332 ------------------------------------------------------------------------------
334 -- Type extension for unary type constructors
336 ------------------------------------------------------------------------------
340 -- | Flexible type extension
341 ext1 :: (Data a, Typeable1 t)
343 -> (forall a. Data a => c (t a))
345 ext1 def ext = maybe def id (cast0to1 ext)
348 -- | Type extension of transformations for unary type constructors
349 ext1T :: (Data d, Typeable1 t)
350 => (forall d. Data d => d -> d)
351 -> (forall d. Data d => t d -> t d)
353 ext1T def ext = unT ((T def) `ext1` (T ext))
356 -- | Type extension of monadic transformations for type constructors
357 ext1M :: (Monad m, Data d, Typeable1 t)
358 => (forall d. Data d => d -> m d)
359 -> (forall d. Data d => t d -> m (t d))
361 ext1M def ext = unM ((M def) `ext1` (M ext))
364 -- | Type extension of queries for type constructors
365 ext1Q :: (Data d, Typeable1 t)
367 -> (forall d. Data d => t d -> q)
369 ext1Q def ext = unQ ((Q def) `ext1` (Q ext))
372 -- | Type extension of readers for type constructors
373 ext1R :: (Monad m, Data d, Typeable1 t)
375 -> (forall d. Data d => m (t d))
377 ext1R def ext = unR ((R def) `ext1` (R ext))
381 ------------------------------------------------------------------------------
383 -- Type constructors for type-level lambdas
385 ------------------------------------------------------------------------------
388 -- | The type constructor for transformations
389 newtype T x = T { unT :: x -> x }
391 -- | The type constructor for transformations
392 newtype M m x = M { unM :: x -> m x }
394 -- | The type constructor for queries
395 newtype Q q x = Q { unQ :: x -> q }
397 -- | The type constructor for readers
398 newtype R m x = R { unR :: m x }