-- 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. The
--   makeRelativeToProject utility is also backported. On recent
--   versions of template-haskell (2.17.0.0 or later), this module
--   simply reexports definitions 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.6

-- | 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:
--   
--   
--   
- The Quote class
--   
- The Code type
--   
- The getPackageRoot and makeRelativeToProject utility
--   functions
--   
--   
--   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.
--   
--   
--   
- The Monad m superclass is needed to stitch together the
--   different AST fragments.
--   
- newName is used when desugaring binding structures such as
--   lambdas to generate fresh names.
--   
--   
--   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 :: Type -> Type)

-- | 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 :: (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 :: Type -> Type). (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

-- | Represents an expression which has type a, built in monadic
--   context m. Built on top of TExp, typed expressions
--   allow for type-safe splicing via:
--   
--   
--   
- typed quotes, written as [|| ... ||] where ...
--   is an expression; if that expression has type a, then the
--   quotation has type Quote m => Code m a
--   
- typed splices inside of typed quotes, written as $$(...)
--   where ... is an arbitrary expression of type Quote m
--   => Code m a
--   
--   
--   Traditional expression quotes and splices let us construct ill-typed
--   expressions:
--   
--   
--   >>> fmap ppr $ runQ (unTypeCode [| True == $( [| "foo" |] ) |])
--   GHC.Types.True GHC.Classes.== "foo"
--   
--   >>> GHC.Types.True GHC.Classes.== "foo"
--   <interactive> error:
--       • Couldn't match expected type ‘Bool’ with actual type ‘[Char]’
--       • In the second argument of ‘(==)’, namely ‘"foo"’
--         In the expression: True == "foo"
--         In an equation for ‘it’: it = True == "foo"
--   
--   
--   With typed expressions, the type error occurs when constructing
--   the Template Haskell expression:
--   
--   
--   >>> fmap ppr $ runQ (unTypeCode [|| True == $$( [|| "foo" ||] ) ||])
--   <interactive> error:
--       • Couldn't match type ‘[Char]’ with ‘Bool’
--         Expected type: Code Q Bool
--           Actual type: Code Q [Char]
--       • In the Template Haskell quotation [|| "foo" ||]
--         In the expression: [|| "foo" ||]
--         In the Template Haskell splice $$([|| "foo" ||])
--   
newtype Code (m :: Type -> Type) (a :: TYPE r)
Code :: m (TExp a) -> Code (m :: Type -> Type) (a :: TYPE r)

-- | Underlying monadic value
[examineCode] :: Code (m :: Type -> Type) (a :: TYPE r) -> 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 :: Type -> Type) (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.
unsafeCodeCoerce :: forall a m. Quote m => m Exp -> Code m a

-- | Lift a monadic action producing code into the typed Code
--   representation
liftCode :: forall a m. m (TExp a) -> Code m a

-- | Extract the untyped representation from the typed representation
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) 
hoistCode :: 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.
bindCode :: Monad m => m a -> (a -> Code m b) -> Code m b

-- | Variant of (>>) which allows effectful computations to be
--   injected into code generation.
bindCode_ :: 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) 
joinCode :: Monad m => m (Code m a) -> Code m a

-- | Splice m a is a type alias for:
--   
--   
--   
- Code m a, if using
--   template-haskell-2.17.0.0 or later, or
--   
- m (TExp a), if using an older version of
--   template-haskell.
--   
--   
--   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 = Code

-- | SpliceQ a is a type alias for:
--   
--   
--   
- Code Q a, if using
--   template-haskell-2.17.0.0 or later, or
--   
- Q (TExp a), if using an older version of
--   template-haskell.
--   
--   
--   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 = Splice Q

-- | 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 :: 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_ :: 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 :: 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 :: 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 :: 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 a m. m (TExp a) -> Splice m a

-- | A variant of liftTypedQuote that is:
--   
--   
--   
- Always implemented in terms of lift behind the scenes,
--   and
--   
- 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.)
--   
--   
--   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 :: forall t (m :: Type -> Type). (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:
--   
--   
--   
- You need to implement liftTyped in a hand-written
--   Lift instance where the corresponding lift
--   implementation cannot be derived, and
--   
- The data type receiving a Lift instance has a kind besides
--   Type.
--   
--   
--   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 a 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 a m. Quote m => Splice m a -> m Exp

-- | Lift a TExp a into a Splice. This is useful
--   when splicing in the result of a computation into a typed QuasiQuoter.
--   
--   One example is traverseing over a list of elements and
--   returning an expression from each element.
--   
--   
--   mkInt :: String -> Q (TExp Int)
--   mkInt str = [|| length $$str ||]
--   
--   mkInts :: [String] -> Q [TExp Int]
--   mkInts = traverse mkInt
--   
--   
--   This gives us a list of TExp, not a TExp of a list. We
--   can push the list inside the type with this function:
--   
--   
--   listTE :: [TExp a] -> TExp [a]
--   listTE = TExp . ListE . map unType
--   
--   
--   In a do block using liftSplice, we can bind the
--   resulting
--   
--   TExp [Int] out of the expression.
--   
--   
--   foo :: Q (TExp Int)
--   foo = do
--        ints <- mkInts ["hello", "world", "goodybe", "bob"]
--        [|| sum $$(pure (listTE ints)) ||]
--   
--   
--   Prior to GHC 9, with the Q type, we can write pure
--   :: TExp a -> Q (TExp a), which is a valid
--   thing to use in a typed quasiquoter. However, after GHC 9, this code
--   will fail to type check. There is no Applicative instance for
--   Code m a, so we need another way to splice it in.
--   
--   A GHC 9 only solution can use Code :: m (TExp a)
--   -> Code m a and pure together, like: Code .
--   pure.
--   
--   With expToSplice, we can splice it in a backwards compatible
--   way. A fully backwards- and forwards-compatible example looks like
--   this:
--   
--   
--   mkInt :: String -> Q Int
--   mkInt str = examineSplice [|| length $$str ||]
--   
--   mkInts :: [String] -> Q [TExp Int]
--   mkInts = traverse mkInt
--   
--   foo :: SpliceQ Int
--   foo = liftSplice $ do
--        ints <- mkInts ["hello", "world", "goodybe", "bob"]
--        examineSplice [|| sum $$(expToSplice (listTE ints)) ||]
--   
expToSplice :: forall (m :: Type -> Type) a. Applicative m => TExp a -> Splice m a

-- | Get the package root for the current package which is being compiled.
--   This can be set explicitly with the -package-root flag but is normally
--   just the current working directory.
--   
--   The motivation for this flag is to provide a principled means to
--   remove the assumption from splices that they will be executed in the
--   directory where the cabal file resides. Projects such as
--   haskell-language-server can't and don't change directory when
--   compiling files but instead set the -package-root flag appropriately.
getPackageRoot :: Q FilePath

-- | The input is a filepath, which if relative is offset by the package
--   root.
makeRelativeToProject :: FilePath -> Q FilePath
instance GHC.Internal.Base.Applicative m => GHC.Internal.Base.Applicative (Language.Haskell.TH.Syntax.Compat.QuoteToQuasi m)
instance GHC.Internal.Base.Functor m => GHC.Internal.Base.Functor (Language.Haskell.TH.Syntax.Compat.QuoteToQuasi m)
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 Language.Haskell.TH.Syntax.Quote q => Language.Haskell.TH.Syntax.Compat.IsCode q a (Language.Haskell.TH.Syntax.Code q a)
instance GHC.Internal.Base.Monad m => GHC.Internal.Control.Monad.Fail.MonadFail (Language.Haskell.TH.Syntax.Compat.QuoteToQuasi m)
instance GHC.Internal.Base.Monad m => Control.Monad.IO.Class.MonadIO (Language.Haskell.TH.Syntax.Compat.QuoteToQuasi m)
instance GHC.Internal.Base.Monad m => GHC.Internal.Base.Monad (Language.Haskell.TH.Syntax.Compat.QuoteToQuasi m)
instance Language.Haskell.TH.Syntax.Quote m => Language.Haskell.TH.Syntax.Quasi (Language.Haskell.TH.Syntax.Compat.QuoteToQuasi m)
