------------------------------------------------------------------------------ -- | -- Maintainer : Ralf Laemmel, Joost Visser -- Stability : experimental -- Portability : portable -- -- This module is part of 'StrategyLib', a library of functional strategy -- combinators, including combinators for generic traversal. This module -- is basically a wrapper for the strategy primitives plus some extra -- basic strategy combinators that can be defined immediately in terms -- of the primitive ones. ------------------------------------------------------------------------------ module Data.Generics.Strafunski.StrategyLib.StrategyPrelude ( module Data.Generics.Strafunski.StrategyLib.Models.Deriving.StrategyPrimitives, module Data.Generics.Strafunski.StrategyLib.StrategyPrelude ) where import Data.Generics.Strafunski.StrategyLib.Models.Deriving.StrategyPrimitives import Control.Monad import Data.Monoid ------------------------------------------------------------------------------ -- * Useful defaults for strategy update (see 'adhocTU' and 'adhocTP'). -- | Type-preserving identity. Returns the incoming term without change. idTP :: Monad m => TP m idTP = paraTP return -- | Type-preserving failure. Always fails, independent of the incoming -- term. Uses 'MonadPlus' to model partiality. failTP :: MonadPlus m => TP m failTP = paraTP (const mzero) -- | Type-unifying failure. Always fails, independent of the incoming -- term. Uses 'MonadPlus' to model partiality. failTU :: MonadPlus m => TU a m failTU = paraTU (const mzero) -- | Type-unifying constant strategy. Always returns the argument value 'a', -- independent of the incoming term. constTU :: Monad m => a -> TU a m constTU a = paraTU (const (return a)) -- | Type-unifying monadic constant strategy. Always performs the argument -- computation 'a', independent of the incoming term. This is a monadic -- variation of 'constTU'. compTU :: Monad m => m a -> TU a m compTU a = paraTU (const a) ------------------------------------------------------------------------------ -- * Lift a function to a strategy type with failure as default -- | Apply the monomorphic, type-preserving argument function, if its -- input type matches the input term's type. Otherwise, fail. monoTP :: (Term a, MonadPlus m) => (a -> m a) -> TP m monoTP = adhocTP failTP -- | Apply the monomorphic, type-unifying argument function, if its -- input type matches the input term's type. Otherwise, fail. monoTU :: (Term a, MonadPlus m) => (a -> m b) -> TU b m monoTU = adhocTU failTU ------------------------------------------------------------------------------ -- * Function composition -- | Sequential ccomposition of monomorphic function and type-unifying strategy. -- In other words, after the type-unifying strategy 's' has been applied, -- the monomorphic function 'f' is applied to the resulting value. dotTU :: Monad m => (a -> b) -> TU a m -> TU b m dotTU f s = s `passTU` (constTU . f) -- | Parallel combination of two type-unifying strategies with a binary -- combinator. In other words, the values resulting from applying the -- type-unifying strategies are combined to a final value by applying -- the combinator 'o'. op2TU :: Monad m => (a -> b -> c) -> TU a m -> TU b m -> TU c m op2TU o s s' = s `passTU` \a -> s' `passTU` \b -> constTU (o a b) ------------------------------------------------------------------------------ -- * Reduce a strategy's performance to its effects -- | Reduce a type-preserving strategy to a type-unifying one that -- ignores its result term and returns void, but retains its -- monadic effects. voidTP :: Monad m => TP m -> TU () m voidTP s = s `seqTU` constTU () -- | Reduce a type-unifying strategy to a type-unifying one that -- ignores its result value and returns void, but retains its -- monadic effects. voidTU :: Monad m => TU u m -> TU () m voidTU s = s `passTU` \_ -> constTU () ------------------------------------------------------------------------------ -- * Shape test combinators -- | Test for constant term, i.e.\ having no subterms. con :: MonadPlus m => TP m con = allTP failTP -- | Test for compound term, i.e.\ having at least one subterm. com :: MonadPlus m => TP m com = oneTP idTP ------------------------------------------------------------------------------