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/>.
14 -----------------------------------------------------------------------------
16 module Data.Generics.Aliases (
18 -- * Combinators to \"make\" generic functions via cast
19 mkT, mkQ, mkM, mkMp, mkB,
20 extT, extQ, extM, extMp, extB,
22 -- * Type synonyms for generic function types
30 -- * Inredients of generic functions
33 -- * Function combinators on generic functions
43 import Data.Generics.Basics
47 ------------------------------------------------------------------------------
49 -- Combinators to "make" generic functions
50 -- We use type-safe cast in a number of ways to make generic functions.
52 ------------------------------------------------------------------------------
54 -- | Make a generic transformation;
55 -- start from a type-specific case;
56 -- preserve the term otherwise
58 mkT :: (Typeable a, Typeable b) => (b -> b) -> a -> a
59 mkT f = case cast f of
64 -- | Make a generic query;
65 -- start from a type-specific case;
66 -- return a constant otherwise
68 mkQ :: (Typeable a, Typeable b) => r -> (b -> r) -> a -> r
69 (r `mkQ` br) a = case cast a of
74 -- | Make a generic monadic transformation;
75 -- start from a type-specific case;
76 -- resort to return otherwise
84 => (b -> m b) -> a -> m a
85 mkM f = case cast 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,
108 => (b -> m b) -> a -> m a
109 mkMp = maybe (const mzero) id . cast
112 -- | Make a generic builder;
113 -- start from a type-specific ase;
114 -- resort to no build (i.e., mzero) otherwise
116 mkB :: ( MonadPlus m,
123 mkB = maybe mzero id . cast
126 -- | Extend a generic transformation by a type-specific case
127 extT :: (Typeable a, Typeable b) => (a -> a) -> (b -> b) -> a -> a
128 extT f = maybe f id . cast
131 -- | Extend a generic query by a type-specific case
132 extQ :: (Typeable a, Typeable b) => (a -> q) -> (b -> q) -> a -> q
133 extQ f g a = maybe (f a) g (cast a)
136 -- | Extend a generic monadic transformation by a type-specific case
137 extM :: (Typeable a, Typeable b,
138 Typeable (m a), Typeable (m b),
140 => (a -> m a) -> (b -> m b) -> a -> m a
141 extM f = maybe f id . cast
144 -- | Extend a generic MonadPlus transformation by a type-specific case
145 extMp :: ( MonadPlus m,
151 => (a -> m a) -> (b -> m b) -> a -> m a
156 -- | Extend a generic builder by a type-specific case
164 extB f = maybe f id . cast
167 ------------------------------------------------------------------------------
169 -- Type synonyms for generic function types
171 ------------------------------------------------------------------------------
174 -- | Generic transformations,
175 -- i.e., take an \"a\" and return an \"a\"
177 type GenericT = forall a. Data a => a -> a
180 -- | Generic queries of type \"r\",
181 -- i.e., take any \"a\" and return an \"r\"
183 type GenericQ r = forall a. Data a => a -> r
186 -- | Generic monadic transformations,
187 -- i.e., take an \"a\" and compute an \"a\"
189 type GenericM m = forall a. Data a => a -> m a
192 -- | Generic monadic builders with input i,
193 -- i.e., produce an \"a\" with the help of a monad \"m\".
195 type GenericB m = forall a. Data a => m a
198 -- | The general scheme underlying generic functions
199 -- assumed by gfoldl; there are isomorphisms such as
200 -- GenericT = Generic ID.
202 type Generic c = forall a. Data a => a -> c a
205 -- | Wrapped generic functions;
206 -- recall: [Generic c] would be legal but [Generic' c] not.
208 data Generic' c = Generic' { unGeneric' :: Generic c }
212 -- | Left-biased choice on maybies
213 orElse :: Maybe a -> Maybe a -> Maybe a
214 x `orElse` y = case x of
221 The following variations take "orElse" to the function
222 level. Furthermore, we generalise from "Maybe" to any
223 "MonadPlus". This makes sense for monadic transformations and
224 queries. We say that the resulting combinators modell choice. We also
225 provide a prime example of choice, that is, recovery from failure. In
226 the case of transformations, we recover via return whereas for
227 queries a given constant is returned.
231 -- | Choice for monadic transformations
232 choiceMp :: MonadPlus m => GenericM m -> GenericM m -> GenericM m
233 choiceMp f g x = f x `mplus` g x
236 -- | Choice for monadic queries
237 choiceQ :: MonadPlus m => GenericQ (m r) -> GenericQ (m r) -> GenericQ (m r)
238 choiceQ f g x = f x `mplus` g x
241 -- | Recover from the failure of monadic transformation by identity
242 recoverMp :: MonadPlus m => GenericM m -> GenericM m
243 recoverMp f = f `choiceMp` return
246 -- | Recover from the failure of monadic query by a constant
247 recoverQ :: MonadPlus m => r -> GenericQ (m r) -> GenericQ (m r)
248 recoverQ r f = f `choiceQ` const (return r)