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, mkB,
22 extT, extQ, extM, extMp, extB,
24 -- * Type synonyms for generic function types
32 -- * Inredients of generic functions
35 -- * Function combinators on generic functions
45 import Data.Generics.Basics
49 ------------------------------------------------------------------------------
51 -- Combinators to "make" generic functions
52 -- We use type-safe cast in a number of ways to make generic functions.
54 ------------------------------------------------------------------------------
56 -- | Make a generic transformation;
57 -- start from a type-specific case;
58 -- preserve the term otherwise
60 mkT :: (Typeable a, Typeable b) => (b -> b) -> a -> a
61 mkT f = case cast f of
66 -- | Make a generic query;
67 -- start from a type-specific case;
68 -- return a constant otherwise
70 mkQ :: (Typeable a, Typeable b) => r -> (b -> r) -> a -> r
71 (r `mkQ` br) a = case cast a of
76 -- | Make a generic monadic transformation;
77 -- start from a type-specific case;
78 -- resort to return otherwise
84 => (b -> m b) -> a -> m a
85 mkM f = case castarr f of
92 For the remaining definitions, we stick to a more concise style, i.e.,
93 we fold maybies with "maybe" instead of case ... of ..., and we also
94 use a point-free style whenever possible.
99 -- | Make a generic monadic transformation for MonadPlus;
100 -- use \"const mzero\" (i.e., failure) instead of return as default.
102 mkMp :: ( MonadPlus m,
106 => (b -> m b) -> a -> m a
107 mkMp = maybe (const mzero) id . castarr
110 -- | Make a generic builder;
111 -- start from a type-specific ase;
112 -- resort to no build (i.e., mzero) otherwise
114 mkB :: ( MonadPlus m,
119 mkB = maybe mzero id . castss
122 -- | Extend a generic transformation by a type-specific case
123 extT :: (Typeable a, Typeable b) => (a -> a) -> (b -> b) -> a -> a
124 extT f = maybe f id . cast
127 -- | Extend a generic query by a type-specific case
128 extQ :: (Typeable a, Typeable b) => (a -> q) -> (b -> q) -> a -> q
129 extQ f g a = maybe (f a) g (cast a)
132 -- | Extend a generic monadic transformation by a type-specific case
137 => (a -> m a) -> (b -> m b) -> a -> m a
138 extM f = maybe f id . castarr
141 -- | Extend a generic MonadPlus transformation by a type-specific case
142 extMp :: ( MonadPlus m,
146 => (a -> m a) -> (b -> m b) -> a -> m a
151 -- | Extend a generic builder by a type-specific case
157 extB f = maybe f id . castss
160 ------------------------------------------------------------------------------
162 -- Type synonyms for generic function types
164 ------------------------------------------------------------------------------
167 -- | Generic transformations,
168 -- i.e., take an \"a\" and return an \"a\"
170 type GenericT = forall a. Data a => a -> a
173 -- | Generic queries of type \"r\",
174 -- i.e., take any \"a\" and return an \"r\"
176 type GenericQ r = forall a. Data a => a -> r
179 -- | Generic monadic transformations,
180 -- i.e., take an \"a\" and compute an \"a\"
182 type GenericM m = forall a. Data a => a -> m a
185 -- | Generic monadic builders with input i,
186 -- i.e., produce an \"a\" with the help of a monad \"m\".
188 type GenericB m = forall a. Data a => m a
191 -- | The general scheme underlying generic functions
192 -- assumed by gfoldl; there are isomorphisms such as
193 -- GenericT = Generic ID.
195 type Generic c = forall a. Data a => a -> c a
198 -- | Wrapped generic functions;
199 -- recall: [Generic c] would be legal but [Generic' c] not.
201 data Generic' c = Generic' { unGeneric' :: Generic c }
205 -- | Left-biased choice on maybies
206 orElse :: Maybe a -> Maybe a -> Maybe a
207 x `orElse` y = case x of
214 The following variations take "orElse" to the function
215 level. Furthermore, we generalise from "Maybe" to any
216 "MonadPlus". This makes sense for monadic transformations and
217 queries. We say that the resulting combinators modell choice. We also
218 provide a prime example of choice, that is, recovery from failure. In
219 the case of transformations, we recover via return whereas for
220 queries a given constant is returned.
224 -- | Choice for monadic transformations
225 choiceMp :: MonadPlus m => GenericM m -> GenericM m -> GenericM m
226 choiceMp f g x = f x `mplus` g x
229 -- | Choice for monadic queries
230 choiceQ :: MonadPlus m => GenericQ (m r) -> GenericQ (m r) -> GenericQ (m r)
231 choiceQ f g x = f x `mplus` g x
234 -- | Recover from the failure of monadic transformation by identity
235 recoverMp :: MonadPlus m => GenericM m -> GenericM m
236 recoverMp f = f `choiceMp` return
239 -- | Recover from the failure of monadic query by a constant
240 recoverQ :: MonadPlus m => r -> GenericQ (m r) -> GenericQ (m r)
241 recoverQ r f = f `choiceQ` const (return r)