-- 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. -- -- -- -- Therefore the type of an untyped quotation in GHC is `Quote m => m -- Exp` -- -- For many years the type of a quotation was fixed to be `Q Exp` but by -- more precisely specifying the minimal interface it enables the -- Exp to be extracted purely from the quotation without -- interacting with Q. class (Monad m) => Quote m -- | Generate a fresh name, which cannot be captured. -- -- For example, this: -- --
--   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: -- -- -- -- This should be used with caution, as its definition differs depending -- on which version of template-haskell you are using. It is -- mostly useful for contexts in which one is writing a definition that -- is intended to be used directly in a typed Template Haskell splice, as -- the types of TH splices differ between template-haskell -- versions as well. One example of a type that uses Splice is the -- type signature for lifTypedFromUntypedSplice. -- -- Levity-polymorphic since template-haskell-2.16.0.0. type Splice m a = m (TExp a) -- | SpliceQ a is a type alias for: -- -- -- -- This should be used with caution, as its definition differs depending -- on which version of template-haskell you are using. It is -- mostly useful for contexts in which one is writing a definition that -- is intended to be used directly in a typed Template Haskell splice, as -- the types of TH splices differ between template-haskell -- versions as well. -- -- Levity-polymorphic since template-haskell-2.16.0.0. type SpliceQ a = Splice Q a -- | A variant of liftTypedQuote that is: -- --
    --
  1. Always implemented in terms of lift behind the scenes, -- and
  2. --
  3. Returns a Splice. This means that the return type of this -- function will be different depending on which version of -- template-haskell you are using. (See the Haddocks for -- Splice for more information on this point.)
  4. --
-- -- This is primarily useful for minimizing CPP in one particular -- scenario: implementing liftTyped in hand-written Lift -- instances where the corresponding lift implementation cannot be -- derived. For instance, consider this example from the text -- library: -- --
--   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: -- -- -- -- This is primarily useful for minimizing CPP when the following two -- conditions are met: -- --
    --
  1. You need to implement liftTyped in a hand-written -- Lift instance where the corresponding lift -- implementation cannot be derived, and
  2. --
  3. The data type receiving a Lift instance has a kind -- besides Type.
  4. --
-- -- Condition (2) is important because while it is possible to simply -- define 'Syntax.liftTyped = liftTypedFromUntypedSplice -- for Lift instances t such that (t :: Type), -- this will not work for types with different types, such as unboxed -- types or unlifted newtypes. This is because GHC restrictions prevent -- defining liftTypedFromUntypedSplice in a levity polymorphic -- fashion, so one must use unsafeSpliceCoerce to work around -- these restrictions. Here is an example of how to use -- unsafeSpliceCoerce: -- --
--   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