-- 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. -- ---- 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: -- --
-- 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: -- --
-- 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