[project @ 2003-07-24 16:24:21 by ralf]
[ghc-base.git] / Data / Generics / Types.hs
1 -----------------------------------------------------------------------------
2 -- |
3 -- Module      :  Data.Generics.Types
4 -- Copyright   :  (c) The University of Glasgow, CWI 2001--2003
5 -- License     :  BSD-style (see the file libraries/base/LICENSE)
6 -- 
7 -- Maintainer  :  libraries@haskell.org
8 -- Stability   :  experimental
9 -- Portability :  non-portable
10 --
11 -- "Scrap your boilerplate" --- Generic programming in Haskell 
12 -- See <http://www.cs.vu.nl/boilerplate/>.
13 --
14 -----------------------------------------------------------------------------
15
16 module Data.Generics.Types ( 
17
18         -- * Generic operations to reify types
19         constrArity,
20         typeReachableFrom,
21
22  ) where
23
24
25 ------------------------------------------------------------------------------
26
27
28 import Data.Generics.Basics
29 import Data.Generics.Aliases
30 import Data.Generics.Counts
31
32
33
34 -- Generic type functions,
35 -- i.e., functions mapping types to values
36 --
37 type GTypeFun r  = forall a. Typeable a => TypeFun a r
38
39
40
41 ------------------------------------------------------------------------------
42 --
43 --      Compute arity of a constructor against a type argument
44 --
45 ------------------------------------------------------------------------------
46
47
48 constrArity :: Data a => (a -> ()) -> Constr -> Int
49 constrArity ta c = glength $ withType (fromConstr c) ta
50
51
52 ------------------------------------------------------------------------------
53 --
54 --      Reachability relation on types
55 --
56 ------------------------------------------------------------------------------
57
58 --
59 -- Test if nodes of type "a" are reachable from nodes of type "b".
60 -- This is a naive, inefficient encoding.
61 -- As of writing, it does not even cope with recursive types.
62 --
63 typeReachableFrom :: (Data a, Data b) => TypeVal a -> TypeVal b -> Bool
64 typeReachableFrom (a::TypeVal a) (b::TypeVal b) =
65   or ( sameType a b
66      : map (recurse . fromConstr) (dataTypeCons $ dataTypeOf b)
67      )
68   where
69
70     -- See if a is reachable from immediate subterms of a kind of b 
71     recurse :: b -> Bool
72     recurse = or
73             . gmapL ( typeReachableFrom a 
74                     . typeValOf
75                     )