[project @ 2003-07-24 15:28:06 by simonpj]
[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.Types
29 import Data.Generics.Basics
30 import Data.Generics.Aliases
31 import Data.Generics.Counts
32
33
34
35 -- Generic type functions,
36 -- i.e., functions mapping types to values
37 --
38 type GTypeFun r  = forall a. Typeable a => TypeFun a r
39
40
41
42 ------------------------------------------------------------------------------
43 --
44 --      Compute arity of a constructor against a type argument
45 --
46 ------------------------------------------------------------------------------
47
48
49 constrArity :: Data a => (a -> ()) -> Constr -> Int
50 constrArity ta c = glength $ withType (fromConstr c) ta
51
52
53 ------------------------------------------------------------------------------
54 --
55 --      Reachability relation on types
56 --
57 ------------------------------------------------------------------------------
58
59 --
60 -- Test if nodes of type "a" are reachable from nodes of type "b".
61 -- This is a naive, inefficient encoding.
62 -- As of writing, it does not even cope with recursive types.
63 --
64 typeReachableFrom :: (Data a, Data b) => TypeVal a -> TypeVal b -> Bool
65 typeReachableFrom (a::TypeVal a) (b::TypeVal b) =
66   or ( sameType a b
67      : map (recurse . fromConstr) (dataTypeCons $ dataTypeOf b)
68      )
69   where
70
71     -- See if a is reachable from immediate subterms of a kind of b 
72     recurse :: b -> Bool
73     recurse = or
74             . gmapL ( typeReachableFrom a 
75                     . typeValOf
76                     )