-----------------------------------------------------------------------------
-- |
-- Module : Data.Generics.Basics
--- Copyright : (c) The University of Glasgow, CWI 2001--2003
+-- Copyright : (c) The University of Glasgow, CWI 2001--2004
-- License : BSD-style (see the file libraries/base/LICENSE)
--
-- Maintainer : libraries@haskell.org
gfoldl, -- :: ... -> a -> c a
toConstr, -- :: a -> Constr
fromConstr, -- :: Constr -> a
- dataTypeOf -- :: a -> DataType
-
+ dataTypeOf, -- :: a -> DataType
+ cast0to1, -- mediate types and unary type constructors
+ cast0to2 -- mediate types and binary type constructors
),
-- * Constructor representations
gmapQ,
gmapQl,
gmapQr,
+ gmapQi,
gmapM,
gmapMp,
gmapMo,
------------------------------------------------------------------------------
-
+#ifdef __HADDOCK__
+import Prelude
+#endif
import Data.Typeable
import Data.Maybe
import Control.Monad
+
------------------------------------------------------------------------------
--
-- The Data class
--
gfoldl _ z = z
-
-- | Obtaining the constructor from a given datum.
-- For proper terms, this is meant to be the top-level constructor.
-- Primitive datatypes are here viewed as potentially infinite sets of
dataTypeOf :: a -> DataType
+
+------------------------------------------------------------------------------
+--
+-- Mediate types and type constructors
+--
+------------------------------------------------------------------------------
+
+ -- | Mediate types and unary type constructors
+ cast0to1 :: Typeable1 t
+ => (forall a. Data a => c (t a))
+ -> Maybe (c a)
+ cast0to1 _ = Nothing
+
+ -- | Mediate types and binary type constructors
+ cast0to2 :: Typeable2 t
+ => (forall a b. (Data a, Data b) => c (t a b))
+ -> Maybe (c a)
+ cast0to2 _ = Nothing
+
+
+
------------------------------------------------------------------------------
--
-- Typical generic maps defined in terms of gfoldl
where
k (Qr c) x = Qr (\r -> c (f x `o` r))
+
-- | A generic query that processes the immediate subterms and returns a list
gmapQ :: (forall a. Data a => a -> u) -> a -> [u]
gmapQ f = gmapQr (:) [] f
+ -- | A generic query that processes one child by index (zero-based)
+ gmapQi :: Int -> (forall a. Data a => a -> u) -> a -> u
+ gmapQi i f x = case gfoldl k z x of { Qi _ (Just q) -> q }
+ where
+ k (Qi i' q) a = Qi (i'+1) (if i==i' then Just (f a) else q)
+ z f = Qi 0 Nothing
+
+
-- | A generic monadic transformation that maps over the immediate subterms
gmapM :: Monad m => (forall a. Data a => a -> m a) -> a -> m a
newtype CONST c a = CONST { unCONST :: c }
+-- | Type constructor for adding counters to queries
+data Qi q a = Qi Int (Maybe q)
+
+
-- | The type constructor used in definition of gmapQr
newtype Qr r a = Qr { unQr :: r -> r }
dataTypeOf _ = StringType
--
--- Bool as the most trivial algebraic datatype;
+-- () as the most trivial algebraic datatype;
+-- define top-level definitions for representations.
+--
+
+emptyTupleConstr = mkConstr 1 "()" Prefix
+unitDataType = mkDataType [emptyTupleConstr]
+
+instance Data () where
+ toConstr _ = emptyTupleConstr
+ fromConstr c | conIndex c == 1 = ()
+ dataTypeOf _ = unitDataType
+
+--
+-- Bool as another trivial algebraic datatype;
-- define top-level definitions for representations.
--
1 -> []
2 -> undefined:undefined
dataTypeOf _ = listDataType
+ cast0to1 = cast1
--
-- The gmaps are given as an illustration.
1 -> Nothing
2 -> Just undefined
dataTypeOf _ = maybeDataType
+ cast0to1 = cast1
+
--
-- Yet another polymorphic datatype constructor.
fromConstr c = case conIndex c of
1 -> (undefined,undefined)
dataTypeOf _ = productDataType
+ cast0to2 = cast2
+
--
-- Yet another polymorphic datatype constructor.
-- No surprises.
--
+
+tripleConstr = mkConstr 1 "(,,)" Infix
+tripleDataType = mkDataType [tripleConstr]
+instance (Data a, Data b, Data c) => Data (a,b,c) where
+ gfoldl f z (a,b,c) = z (,,) `f` a `f` b `f` c
+ toConstr _ = tripleConstr
+ fromConstr c = case conIndex c of
+ 1 -> (undefined,undefined,undefined)
+ dataTypeOf _ = tripleDataType
+
+quadrupleConstr = mkConstr 1 "(,,,)" Infix
+quadrupleDataType = mkDataType [quadrupleConstr]
+
+instance (Data a, Data b, Data c, Data d) => Data (a,b,c,d) where
+ gfoldl f z (a,b,c,d) = z (,,,) `f` a `f` b `f` c `f` d
+ toConstr _ = quadrupleConstr
+ fromConstr c = case conIndex c of
+ 1 -> (undefined,undefined,undefined,undefined)
+ dataTypeOf _ = quadrupleDataType
+
+
+--
+-- Yet another polymorphic datatype constructor.
+-- No surprises.
+--
leftConstr = mkConstr 1 "Left" Prefix
rightConstr = mkConstr 2 "Right" Prefix
1 -> Left undefined
2 -> Right undefined
dataTypeOf _ = eitherDataType
+ cast0to2 = cast2
{-
-}
-- A last resort for functions
-instance (Typeable a, Typeable b) => Data (a -> b) where
+instance (Data a, Data b) => Data (a -> b) where
toConstr _ = FunConstr
fromConstr _ = undefined
dataTypeOf _ = FunType
+ cast0to2 = cast2