-- 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.2 -- | 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 (r :: RuntimeRep) (a :: TYPE r) 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 (r :: RuntimeRep) (a :: TYPE r) 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 :: TYPE (r :: RuntimeRep)) Code :: m (TExp a) -> Code m (a :: TYPE (r :: RuntimeRep)) -- | Underlying monadic value [examineCode] :: Code m (a :: TYPE (r :: RuntimeRep)) -> m (TExp a) type CodeQ = Code Q :: (TYPE r -> *) -- | 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 :: TYPE r) 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 (r :: RuntimeRep) (a :: TYPE r) 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 (r :: RuntimeRep) (a :: TYPE r) 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 (r :: RuntimeRep) (a :: TYPE r) 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 (r :: RuntimeRep) (a :: TYPE r). 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 (r :: RuntimeRep) (b :: TYPE r). 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 (r :: RuntimeRep) (b :: TYPE r). 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 (r :: RuntimeRep) (a :: TYPE r). 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. -- -- Levity-polymorphic since template-haskell-2.16.0.0. type Splice m (a :: TYPE r) = 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 :: TYPE r) = Splice Q a -- | A variant of bindCode that works over Splices. Because -- this function uses Splice, the 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.) -- -- Levity-polymorphic since template-haskell-2.16.0.0. bindSplice :: forall m a (r :: RuntimeRep) (b :: TYPE r). Monad m => m a -> (a -> Splice m b) -> Splice m b -- | A variant of bindCode_ that works over Splices. Because -- this function uses Splice, the 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.) -- -- Levity-polymorphic since template-haskell-2.16.0.0. bindSplice_ :: forall m a (r :: RuntimeRep) (b :: TYPE r). Monad m => m a -> Splice m b -> Splice m b -- | A variant of examineCode that takes a Splice as an -- argument. Because this function takes a Splice as an argyment, -- the 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.) -- -- Levity-polymorphic since template-haskell-2.16.0.0. examineSplice :: forall (r :: RuntimeRep) m (a :: TYPE r). Splice m a -> m (TExp a) -- | A variant of hoistCode that works over Splices. Because -- this function uses Splice, the 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.) -- -- Levity-polymorphic since template-haskell-2.16.0.0. hoistSplice :: forall m n (r :: RuntimeRep) (a :: TYPE r). Monad m => (forall x. m x -> n x) -> Splice m a -> Splice n a -- | A variant of joinCode that works over Splices. Because -- this function uses Splice, the 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.) -- -- Levity-polymorphic since template-haskell-2.16.0.0. joinSplice :: forall m (r :: RuntimeRep) (a :: TYPE r). Monad m => m (Splice m a) -> Splice m a -- | A variant of liftCode that returns a Splice. Because -- this function returns a Splice, 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.) -- -- Levity-polymorphic since template-haskell-2.16.0.0. liftSplice :: forall (r :: RuntimeRep) (a :: TYPE r) m. m (TExp a) -> Splice m 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 especially 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 MIN_VERSION_template_haskell(2,17,0)
--     liftTyped = unsafeCodeCoerce . lift
--   #elif MIN_VERSION_template_haskell(2,16,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 MIN_VERSION_template_haskell(2,16,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 splice representation into a typed -- Splice representation. Because this function returns a -- Splice, 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.) -- -- This is especially useful for minimizing CPP when: -- --
    --
  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 MIN_VERSION_template_haskell(2,16,0)
--     liftTyped x = unsafeSpliceCoerce (lift x)
--   #endif
--   
-- -- Levity-polymorphic since template-haskell-2.16.0.0. unsafeSpliceCoerce :: forall (r :: RuntimeRep) (a :: TYPE r) m. Quote m => m Exp -> Splice m a -- | A variant of unTypeCode that takes a Splice as an -- argument. Because this function takes a Splice as an argyment, -- the 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.) -- -- Levity-polymorphic since template-haskell-2.16.0.0. unTypeSplice :: forall (r :: RuntimeRep) (a :: TYPE r) m. Quote m => Splice m a -> m Exp 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 GHC.Types.~ 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