-- Stability : experimental
-- Portability : non-portable
--
--- "Scrap your boilerplate" --- Generic programming in Haskell
--- See <http://www.cs.vu.nl/boilerplate/>.
+-- \"Scrap your boilerplate\" --- Generic programming in Haskell
+-- See <http://www.cs.vu.nl/boilerplate/>. The present module provides
+-- the Data class with its primitives for generic programming.
--
-----------------------------------------------------------------------------
gmapQr,
gmapM,
gmapMp,
-
- -- * Generic unfolding defined in terms of gfoldl and fromConstr
- gunfoldM -- :: Monad m => ... -> m a
+ gmapMo,
) where
k (Mp c) x
= Mp ( c >>= \(h,b) ->
(f x >>= \x' -> return (h x',True))
- `mplus` return (h x, b)
- )
+ `mplus` return (h x,b)
+ )
+
+ -- | Transformation of one immediate subterm with success
+ gmapMo :: MonadPlus m => (forall a. Data a => a -> m a) -> a -> m a
+
+{-
+
+We use the same pairing trick as for gmapMp,
+i.e., we use an extra Bool component to keep track of the
+fact whether an immediate subterm was processed successfully.
+However, we cut of mapping over subterms once a first subterm
+was transformed successfully.
+
+-}
+
+ gmapMo f x = unMp (gfoldl k z x) >>= \(x',b) ->
+ if b then return x' else mzero
+ where
+ z g = Mp (return (g,False))
+ k (Mp c) x
+ = Mp ( c >>= \(h,b) -> if b
+ then return (h x,b)
+ else (f x >>= \x' -> return (h x',True))
+ `mplus` return (h x,b)
+ )
-- | The identity type constructor needed for the definition of gmapT
1 -> (undefined,undefined)
dataTypeOf _ = productDataType
+--
+-- Yet another polymorphic datatype constructor.
+-- No surprises.
+--
+
+
+leftConstr = mkConstr 1 "Left" Prefix
+rightConstr = mkConstr 2 "Right" Prefix
+eitherDataType = mkDataType [leftConstr,rightConstr]
+
+instance (Data a, Data b) => Data (Either a b) where
+ gfoldl f z (Left a) = z Left `f` a
+ gfoldl f z (Right a) = z Right `f` a
+ toConstr (Left _) = leftConstr
+ toConstr (Right _) = rightConstr
+ fromConstr c = case conIndex c of
+ 1 -> Left undefined
+ 2 -> Right undefined
+ dataTypeOf _ = eitherDataType
+
{-
toConstr _ = FunConstr
fromConstr _ = undefined
dataTypeOf _ = FunType
-
-
-------------------------------------------------------------------------------
---
--- Generic unfolding
---
-------------------------------------------------------------------------------
-
--- | Construct an initial with undefined immediate subterms
--- and then map over the skeleton to fill in proper terms.
---
-gunfoldM :: (Monad m, Data a)
- => Constr
- -> (forall a. Data a => m a)
- -> m a
-gunfoldM c f = gmapM (const f) $ fromConstr c