-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Backward- (and forward-)compatible Quote and Code types -- -- This package defines a Language.Haskell.TH.Syntax.Compat -- module, which backports the Quote and Code types to -- work across a wide range of template-haskell versions. On -- recent versions of template-haskell (2.17.0.0 or later), this -- module simply reexports Quote and Code from -- Language.Haskell.TH.Syntax. Refer to the Haddocks for -- Language.Haskell.TH.Syntax.Compat for examples of how to use -- this module. @package th-compat @version 0.1 -- | This module exists to make it possible to define code that works -- across a wide range of template-haskell versions with as -- little CPP as possible. To that end, this module currently backports -- the following template-haskell constructs: -- --
-- -- Refer to the Haddocks below for examples of how to use each of these -- in a backwards-compatible way. module Language.Haskell.TH.Syntax.Compat -- | The Quote class implements the minimal interface which is -- necessary for desugaring quotations. -- ---- f = $(do -- nm1 <- newName "x" -- let nm2 = mkName "x" -- return (LamE [VarP nm1] (LamE [VarP nm2] (VarE nm1))) -- ) ---- -- will produce the splice -- --
-- f = \x0 -> \x -> x0 ---- -- In particular, the occurrence VarE nm1 refers to the binding -- VarP nm1, and is not captured by the binding VarP -- nm2. -- -- Although names generated by newName cannot be -- captured, they can capture other names. For example, this: -- --
-- g = $(do -- nm1 <- newName "x" -- let nm2 = mkName "x" -- return (LamE [VarP nm2] (LamE [VarP nm1] (VarE nm2))) -- ) ---- -- will produce the splice -- --
-- g = \x -> \x0 -> x0 ---- -- since the occurrence VarE nm2 is captured by the innermost -- binding of x, namely VarP nm1. newName :: Quote m => String -> m Name -- | Use a Q computation in a Quote context. This function is -- only safe when the Q computation performs actions from the -- Quote instance for Q or any of Quote's subclasses -- (Functor, Applicative, and Monad). Attempting to -- perform actions from the MonadFail, MonadIO, or -- Quasi instances for Q will result in runtime errors. -- -- This is useful when you have some Q-valued functions that only -- performs actions from Quote and wish to generalise it from -- Q to Quote without having to rewrite the internals of -- the function. This is especially handy for code defined in terms of -- combinators from Language.Haskell.TH.Lib, which were all -- hard-coded to Q prior to template-haskell-2.17.0.0. -- For instance, consider this function: -- --
-- apply :: Exp -> Exp -> Q Exp -- apply f x = appE (return x) (return y) ---- -- There are two ways to generalize this function to use Quote in -- a backwards-compatible way. One way to do so is to rewrite -- apply to avoid the use of appE, like so: -- --
-- applyQuote :: Quote m => Exp -> Exp -> m Exp -- applyQuote f x = return (AppE x y) ---- -- For a small example like applyQuote, there isn't much work -- involved. But this can become tiresome for larger examples. In such -- cases, unsafeQToQuote can do the heavy lifting for you. For -- example, applyQuote can also be defined as: -- --
-- applyQuote :: Quote m => Exp -> Exp -> m Exp -- applyQuote f x = unsafeQToQuote (apply f x) --unsafeQToQuote :: Quote m => Q a -> m a -- | Discard the type annotation and produce a plain Template Haskell -- expression -- -- Levity-polymorphic since template-haskell-2.16.0.0. -- -- This is a variant of the unTypeQ function that is always -- guaranteed to use a Quote constraint, even on old versions of -- template-haskell. -- -- As this function interacts with typed Template Haskell, this function -- is only defined on template-haskell-2.9.0.0 (GHC 7.8) or -- later. unTypeQQuote :: forall a m. Quote m => m (TExp a) -> m Exp -- | Annotate the Template Haskell expression with a type -- -- This is unsafe because GHC cannot check for you that the expression -- really does have the type you claim it has. -- -- Levity-polymorphic since template-haskell-2.16.0.0. -- -- This is a variant of the unsafeTExpCoerce function that is -- always guaranteed to use a Quote constraint, even on old -- versions of template-haskell. -- -- As this function interacts with typed Template Haskell, this function -- is only defined on template-haskell-2.9.0.0 (GHC 7.8) or -- later. unsafeTExpCoerceQuote :: forall a m. Quote m => m Exp -> m (TExp a) -- | Turn a value into a Template Haskell expression, suitable for use in a -- splice. -- -- This is a variant of the lift method of Lift that is -- always guaranteed to use a Quote constraint, even on old -- versions of template-haskell. -- -- Levity-polymorphic since template-haskell-2.17.0.0. liftQuote :: forall t m. (Lift t, Quote m) => t -> m Exp -- | Turn a value into a Template Haskell typed expression, suitable for -- use in a typed splice. -- -- This is a variant of the liftTyped method of Lift that -- is always guaranteed to use a Quote constraint and return a -- Code, even on old versions of template-haskell. -- -- As this function interacts with typed Template Haskell, this function -- is only defined on template-haskell-2.9.0.0 (GHC 7.8) or -- later. While the liftTyped method of Lift was first -- introduced in template-haskell-2.16.0.0, we are able to -- backport it back to template-haskell-2.9.0.0 by making use of -- the lift method on older versions of template-haskell. -- This crucially relies on the Lift law that lift x -- ≡ unTypeQ (liftTyped x) to work, so beware if -- you use liftTypedQuote with an unlawful Lift instance. -- -- Levity-polymorphic since template-haskell-2.17.0.0. liftTypedQuote :: forall t m. (Lift t, Quote m) => t -> Code m t -- | This is a variant of the liftString function that is always -- guaranteed to use a Quote constraint, even on old versions of -- template-haskell. liftStringQuote :: Quote m => String -> m Exp -- | Levity-polymorphic since template-haskell-2.16.0.0. newtype Code m a Code :: m (TExp a) -> Code m a -- | Underlying monadic value [examineCode] :: Code m a -> m (TExp a) type CodeQ = Code Q -- | A class that allows one to smooth over the differences between -- Code m a (the type of typed Template Haskell -- quotations on template-haskell-2.17.0.0 or later) and -- m (TExp a) (the type of typed Template -- Haskell quotations on older versions of template-haskell). -- Here are two examples that demonstrate how to use each method of -- IsCode: -- --
-- {-# LANGUAGE TemplateHaskell #-}
--
-- import Language.Haskell.TH
-- import Language.Haskell.TH.Syntax.Compat
--
-- -- toCode will ensure that the end result is a Code, regardless of
-- -- whether the quote itself returns a Code or a TExp.
-- myCode :: Code Q Int
-- myCode = toCode [|| 42 ||]
--
-- -- fromCode will ensure that the input Code is suitable for splicing
-- (i.e., it will return a Code or a TExp depending on the
--
--
-- template-haskell version in use). fortyTwo :: Int fortyTwo =
-- $$(fromCode myCode)
--
-- Levity-polymorphic since template-haskell-2.16.0.0.
class IsCode q a c | c -> a q
-- | Convert something to a Code.
toCode :: IsCode q a c => c -> Code q a
-- | Convert to something from a Code.
fromCode :: IsCode q a c => Code q a -> c
-- | Unsafely convert an untyped code representation into a typed code
-- representation.
--
-- Levity-polymorphic since template-haskell-2.16.0.0.
unsafeCodeCoerce :: forall a m. Quote m => m Exp -> Code m a
-- | Lift a monadic action producing code into the typed Code
-- representation
--
-- Levity-polymorphic since template-haskell-2.16.0.0.
liftCode :: forall a m. m (TExp a) -> Code m a
-- | Extract the untyped representation from the typed representation
--
-- Levity-polymorphic since template-haskell-2.16.0.0.
unTypeCode :: forall a m. Quote m => Code m a -> m Exp
-- | Modify the ambient monad used during code generation. For example, you
-- can use hoistCode to handle a state effect: handleState ::
-- Code (StateT Int Q) a -> Code Q a handleState = hoistCode (flip
-- runState 0)
--
-- Levity-polymorphic since template-haskell-2.16.0.0.
hoistCode :: forall m n a. Monad m => (forall x. m x -> n x) -> Code m a -> Code n a
-- | Variant of (>>=) which allows effectful computations to be
-- injected into code generation.
--
-- Levity-polymorphic since template-haskell-2.16.0.0.
bindCode :: forall m a b. Monad m => m a -> (a -> Code m b) -> Code m b
-- | Variant of (>>) which allows effectful computations to be
-- injected into code generation.
--
-- Levity-polymorphic since template-haskell-2.16.0.0.
bindCode_ :: forall m a b. Monad m => m a -> Code m b -> Code m b
-- | A useful combinator for embedding monadic actions into Code
-- myCode :: ... => Code m a myCode = joinCode $ do x <-
-- someSideEffect return (makeCodeWith x)
--
-- Levity-polymorphic since template-haskell-2.16.0.0.
joinCode :: forall m a. Monad m => m (Code m a) -> Code m a
-- | Splice m a is a type alias for:
--
-- -- instance Lift Text where -- lift = appE (varE 'pack) . stringE . unpack -- #if ( (2) < 2 || (2) == 2 && (17) < 14 || (2) == 2 && (17) == 14 && (0) <= 0) -- liftTyped = unsafeCodeCoerce . lift -- #elif ( (2) < 2 || (2) == 2 && (16) < 14 || (2) == 2 && (16) == 14 && (0) <= 0) -- liftTyped = unsafeTExpCoerce . lift -- #endif ---- -- The precise details of how this lift implementation works are -- not important, only that it is something that DeriveLift -- could not generate. The main point of this example is to illustrate -- how tiresome it is to write the CPP necessary to define -- liftTyped in a way that works across multiple versions of -- template-haskell. With liftTypedFromUntypedSplice, -- however, this becomes slightly easier to manage: -- --
-- instance Lift Text where -- lift = appE (varE 'pack) . stringE . unpack -- #if ( (2) < 2 || (2) == 2 && (16) < 14 || (2) == 2 && (16) == 14 && (0) <= 0) -- liftTyped = liftTypedFromUntypedSplice -- #endif ---- -- Note that due to the way this function is defined, this will only work -- for Lift instances t such that (t :: Type). -- If you wish to manually define liftTyped for a type with a -- different kind, you will have to use unsafeSpliceCoerce to -- overcome levity polymorphism restrictions. liftTypedFromUntypedSplice :: (Lift t, Quote m) => t -> Splice m t -- | Unsafely convert an untyped code representation into a typed code -- representation, where: -- --
-- instance Lift Int# where -- lift x = litE (intPrimL (fromIntegral (I# x))) -- #if ( (2) < 2 || (2) == 2 && (16) < 14 || (2) == 2 && (16) == 14 && (0) <= 0) -- liftTyped x = unsafeSpliceCoerce (lift x) -- #endif ---- -- Levity-polymorphic since template-haskell-2.16.0.0. unsafeSpliceCoerce :: forall a m. Quote m => m Exp -> Splice m a instance GHC.Base.Monad m => GHC.Base.Monad (Language.Haskell.TH.Syntax.Compat.QuoteToQuasi m) instance GHC.Base.Applicative m => GHC.Base.Applicative (Language.Haskell.TH.Syntax.Compat.QuoteToQuasi m) instance GHC.Base.Functor m => GHC.Base.Functor (Language.Haskell.TH.Syntax.Compat.QuoteToQuasi m) instance Language.Haskell.TH.Syntax.Compat.Quote q => Language.Haskell.TH.Syntax.Compat.IsCode q a (Language.Haskell.TH.Syntax.Compat.Code q a) instance (texp Data.Type.Equality.~ Language.Haskell.TH.Syntax.TExp a) => Language.Haskell.TH.Syntax.Compat.IsCode Language.Haskell.TH.Syntax.Q a (Language.Haskell.TH.Syntax.Q texp) instance GHC.Base.Monad m => Control.Monad.Fail.MonadFail (Language.Haskell.TH.Syntax.Compat.QuoteToQuasi m) instance GHC.Base.Monad m => Control.Monad.IO.Class.MonadIO (Language.Haskell.TH.Syntax.Compat.QuoteToQuasi m) instance Language.Haskell.TH.Syntax.Compat.Quote m => Language.Haskell.TH.Syntax.Quasi (Language.Haskell.TH.Syntax.Compat.QuoteToQuasi m) instance Language.Haskell.TH.Syntax.Compat.Quote Language.Haskell.TH.Syntax.Q