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 -- * 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
83 -- | Make a generic query;
84 -- start from a type-specific case;
85 -- return a constant otherwise
94 (r `mkQ` br) a = case cast a of
99 -- | Make a generic monadic transformation;
100 -- start from a type-specific case;
101 -- resort to return otherwise
115 For the remaining definitions, we stick to a more concise style, i.e.,
116 we fold maybies with "maybe" instead of case ... of ..., and we also
117 use a point-free style whenever possible.
122 -- | Make a generic monadic transformation for MonadPlus;
123 -- use \"const mzero\" (i.e., failure) instead of return as default.
125 mkMp :: ( MonadPlus m
132 mkMp = extM (const mzero)
135 -- | Make a generic builder;
136 -- start from a type-specific ase;
137 -- resort to no build (i.e., mzero) otherwise
144 mkR f = mzero `extR` f
147 -- | Flexible type extension
148 ext0 :: (Typeable a, Typeable b) => c a -> c b -> c a
149 ext0 def ext = maybe def id (gcast ext)
152 -- | Extend a generic transformation by a type-specific case
160 extT def ext = unT ((T def) `ext0` (T ext))
163 -- | Extend a generic query by a type-specific case
171 extQ f g a = maybe (f a) g (cast a)
174 -- | Extend a generic monadic transformation by a type-specific case
179 => (a -> m a) -> (b -> m b) -> a -> m a
180 extM def ext = unM ((M def) `ext0` (M ext))
183 -- | Extend a generic MonadPlus transformation by a type-specific case
184 extMp :: ( MonadPlus m
188 => (a -> m a) -> (b -> m b) -> a -> m a
192 -- | Extend a generic builder
197 extB a = maybe a id . cast
200 -- | Extend a generic reader
206 extR def ext = unR ((R def) `ext0` (R ext))
210 ------------------------------------------------------------------------------
212 -- Type synonyms for generic function types
214 ------------------------------------------------------------------------------
217 -- | Generic transformations,
218 -- i.e., take an \"a\" and return an \"a\"
220 type GenericT = forall a. Data a => a -> a
223 -- | Generic queries of type \"r\",
224 -- i.e., take any \"a\" and return an \"r\"
226 type GenericQ r = forall a. Data a => a -> r
229 -- | Generic monadic transformations,
230 -- i.e., take an \"a\" and compute an \"a\"
232 type GenericM m = forall a. Data a => a -> m a
235 -- | Generic builders
236 -- i.e., produce an \"a\".
238 type GenericB = forall a. Data a => a
241 -- | Generic readers, say monadic builders,
242 -- i.e., produce an \"a\" with the help of a monad \"m\".
244 type GenericR m = forall a. Data a => m a
247 -- | The general scheme underlying generic functions
248 -- assumed by gfoldl; there are isomorphisms such as
249 -- GenericT = Generic T.
251 type Generic c = forall a. Data a => a -> c a
254 -- | Wrapped generic functions;
255 -- recall: [Generic c] would be legal but [Generic' c] not.
257 data Generic' c = Generic' { unGeneric' :: Generic c }
260 -- | Other first-class polymorphic wrappers
261 newtype GenericT' = GT { unGT :: Data a => a -> a }
262 newtype GenericQ' r = GQ { unGQ :: GenericQ r }
263 newtype GenericM' m = GM { unGM :: Data a => a -> m a }
266 -- | Left-biased choice on maybies
267 orElse :: Maybe a -> Maybe a -> Maybe a
268 x `orElse` y = case x of
275 The following variations take "orElse" to the function
276 level. Furthermore, we generalise from "Maybe" to any
277 "MonadPlus". This makes sense for monadic transformations and
278 queries. We say that the resulting combinators modell choice. We also
279 provide a prime example of choice, that is, recovery from failure. In
280 the case of transformations, we recover via return whereas for
281 queries a given constant is returned.
285 -- | Choice for monadic transformations
286 choiceMp :: MonadPlus m => GenericM m -> GenericM m -> GenericM m
287 choiceMp f g x = f x `mplus` g x
290 -- | Choice for monadic queries
291 choiceQ :: MonadPlus m => GenericQ (m r) -> GenericQ (m r) -> GenericQ (m r)
292 choiceQ f g x = f x `mplus` g x
295 -- | Recover from the failure of monadic transformation by identity
296 recoverMp :: MonadPlus m => GenericM m -> GenericM m
297 recoverMp f = f `choiceMp` return
300 -- | Recover from the failure of monadic query by a constant
301 recoverQ :: MonadPlus m => r -> GenericQ (m r) -> GenericQ (m r)
302 recoverQ r f = f `choiceQ` const (return r)
306 ------------------------------------------------------------------------------
310 ------------------------------------------------------------------------------
312 -- | Construct an initial term with undefined immediate subterms
313 -- and then map over the skeleton to fill in proper terms.
316 -> (forall a. Data a => a)
318 gunfoldB c f = gmapT (const f) (fromConstr c)
321 -- | Monadic variation on \"gunfoldB\"
322 gunfoldR :: (Monad m, Data a)
324 -> (forall a. Data a => m a)
326 gunfoldR c f = gmapM (const f) $ fromConstr c
330 ------------------------------------------------------------------------------
332 -- Type extension for unary type constructors
334 ------------------------------------------------------------------------------
338 -- | Flexible type extension
339 ext1 :: (Data a, Typeable1 t)
341 -> (forall a. Data a => c (t a))
343 ext1 def ext = maybe def id (dataCast1 ext)
346 -- | Type extension of transformations for unary type constructors
347 ext1T :: (Data d, Typeable1 t)
348 => (forall d. Data d => d -> d)
349 -> (forall d. Data d => t d -> t d)
351 ext1T def ext = unT ((T def) `ext1` (T ext))
354 -- | Type extension of monadic transformations for type constructors
355 ext1M :: (Monad m, Data d, Typeable1 t)
356 => (forall d. Data d => d -> m d)
357 -> (forall d. Data d => t d -> m (t d))
359 ext1M def ext = unM ((M def) `ext1` (M ext))
362 -- | Type extension of queries for type constructors
363 ext1Q :: (Data d, Typeable1 t)
365 -> (forall d. Data d => t d -> q)
367 ext1Q def ext = unQ ((Q def) `ext1` (Q ext))
370 -- | Type extension of readers for type constructors
371 ext1R :: (Monad m, Data d, Typeable1 t)
373 -> (forall d. Data d => m (t d))
375 ext1R def ext = unR ((R def) `ext1` (R ext))
379 ------------------------------------------------------------------------------
381 -- Type constructors for type-level lambdas
383 ------------------------------------------------------------------------------
386 -- | The type constructor for transformations
387 newtype T x = T { unT :: x -> x }
389 -- | The type constructor for transformations
390 newtype M m x = M { unM :: x -> m x }
392 -- | The type constructor for queries
393 newtype Q q x = Q { unQ :: x -> q }
395 -- | The type constructor for readers
396 newtype R m x = R { unR :: m x }