-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | GHC.Generics-based Language.Haskell.TH.Syntax.lift implementation
--   
--   This package provides a <a>GHC.Generics</a>-based
--   <tt>genericLiftWithPkg</tt> function (intended for GHC 7.10 and
--   earlier), as well as a <tt>genericLift</tt> function (only available
--   on GHC 8.0 and later), both of which can be used for providing a
--   <tt>Language.Haskell.TH.Syntax.lift</tt> implementation. See the
--   documentation in the <a>Language.Haskell.TH.Lift.Generics</a> module
--   to get started.
--   
--   Credit goes to Matthew Pickering for <a>suggesting this idea</a>.
--   
--   Note that due to API limitations, <a>GHC.Generics</a> wasn't powerful
--   enough to come up with the entirety of a <a>lift</a> implementation
--   prior to GHC 8.0. For this reason, <tt>genericLiftWithPkg</tt>
--   requires you to produce the package name yourself, which proves to be
--   no small feat (see the documentation for more info).
--   
--   Luckily, you don't have to jump through as many hoops on GHC 8.0 and
--   later: simply use the <tt>genericLift</tt> function, and life is good.
@package lift-generics
@version 0.1.2


-- | <a>GHC.Generics</a>-based approach to implementing <a>lift</a>.
module Language.Haskell.TH.Lift.Generics

-- | <a>GHC.Generics</a>-based <a>lift</a> implementation.
--   
--   API limitations of early versions of GHC (7.10 and earlier) require
--   the user to produce the package name themselves. This isn't as easy to
--   come up with as it sounds, because GHC 7.10 uses a hashed package ID
--   for a name. To make things worse, if you produce the wrong package
--   name, you might get bizarre compilation errors!
--   
--   There's no need to fear, though—the code sample below shows an example
--   of how to properly use <a>genericLiftWithPkg</a> without shooting
--   yourself in the foot:
--   
--   <pre>
--   {-# LANGUAGE CPP, DeriveGeneric #-}
--   -- part of package foobar
--   module Foo where
--   
--   import GHC.Generics
--   import Language.Haskell.Lift.Generics
--   
--   #ifndef CURRENT_PACKAGE_KEY
--   import Data.Version (showVersion)
--   import Paths_foobar (version)
--   #endif
--   
--   pkgName :: String
--   #ifdef CURRENT_PACKAGE_KEY
--   pkgName = CURRENT_PACKAGE_KEY
--   #else
--   pkgName = "foobar-" ++ showVersion version
--   #endif
--   
--   data Foo = Foo Int Char String
--     deriving Generic
--   
--   instance Lift Foo where
--     lift = genericLiftWithPkg pkgName
--   </pre>
--   
--   As you can see, this trick only works if (1) the current package key
--   is known (i.e., the <a>Lift</a> instance is defined in the same
--   package as the datatype), or (2) you're dealing with a package that
--   has a fixed package name (e.g., <tt>base</tt>, <tt>ghc-prim</tt>,
--   <tt>template-haskell</tt>, etc.).
--   
--   Once the <tt>Lift Foo</tt> instance is defined, you can splice
--   <tt>Foo</tt> values directly into Haskell source code:
--   
--   <pre>
--   {-# LANGUAGE TemplateHaskell #-}
--   module Bar where
--   
--   import Foo
--   import Language.Haskell.TH.Syntax
--   
--   foo :: Foo
--   foo = $(lift (Foo 1 <tt>a</tt> "baz"))
--   </pre>
genericLiftWithPkg :: (Generic a, GLift (Rep a)) => String -> a -> Q Exp

-- | <a>GHC.Generics</a>-based <a>lift</a> implementation. Only available
--   on GHC 8.0 and later due to API limitations of earlier GHC versions.
--   
--   Unlike <a>genericLiftWithPkg</a>, this function does all of the work
--   for you:
--   
--   <pre>
--   {-# LANGUAGE DeriveGeneric #-}
--   module Foo where
--   
--   import GHC.Generics
--   import Language.Haskell.Lift.Generics
--   
--   data Foo = Foo Int Char String
--     deriving Generic
--   
--   instance Lift Foo where
--     lift = genericLift
--   </pre>
--   
--   Now you can splice <tt>Foo</tt> values directly into Haskell source
--   code:
--   
--   <pre>
--   {-# LANGUAGE TemplateHaskell #-}
--   module Bar where
--   
--   import Foo
--   import Language.Haskell.TH.Syntax
--   
--   foo :: Foo
--   foo = $(lift (Foo 1 <tt>a</tt> "baz"))
--   </pre>
genericLift :: (Generic a, GLift (Rep a)) => a -> Q Exp

-- | Class of generic representation types which can be converted to
--   Template Haskell expressions. You shouldn't need to use this typeclass
--   directly; it is only exported for educational purposes.
class GLift f
glift :: GLift f => String -> f a -> Q Exp

-- | Class of generic representation types which can be converted to
--   Template Haskell expressions, given a package and module name. You
--   shouldn't need to use this typeclass directly; it is only exported for
--   educational purposes.
class GLiftDatatype f
gliftWith :: GLiftDatatype f => String -> String -> f a -> Q Exp

-- | Class of generic representation types which can be converted to a list
--   of Template Haskell expressions (which represent a constructors'
--   arguments). You shouldn't need to use this typeclass directly; it is
--   only exported for educational purposes.
class GLiftArgs f
gliftArgs :: GLiftArgs f => f a -> [Q Exp]

-- | A <a>Lift</a> instance can have any of its values turned into a
--   Template Haskell expression. This is needed when a value used within a
--   Template Haskell quotation is bound outside the Oxford brackets
--   (<tt>[| ... |]</tt>) but not at the top level. As an example:
--   
--   <pre>
--   add1 :: Int -&gt; Q Exp
--   add1 x = [| x + 1 |]
--   </pre>
--   
--   Template Haskell has no way of knowing what value <tt>x</tt> will take
--   on at splice-time, so it requires the type of <tt>x</tt> to be an
--   instance of <a>Lift</a>.
--   
--   A <a>Lift</a> instance must satisfy <tt>$(lift x) ≡ x</tt> for all
--   <tt>x</tt>, where <tt>$(...)</tt> is a Template Haskell splice.
--   
--   <a>Lift</a> instances can be derived automatically by use of the
--   <tt>-XDeriveLift</tt> GHC language extension:
--   
--   <pre>
--   {-# LANGUAGE DeriveLift #-}
--   module Foo where
--   
--   import Language.Haskell.TH.Syntax
--   
--   data Bar a = Bar1 a (Bar a) | Bar2 String
--     deriving Lift
--   </pre>
class Lift t

-- | Turn a value into a Template Haskell expression, suitable for use in a
--   splice.
lift :: Lift t => t -> Q Exp
instance (GHC.Generics.Constructor c, Language.Haskell.TH.Lift.Generics.GLiftArgs f) => Language.Haskell.TH.Lift.Generics.GLiftDatatype (GHC.Generics.C1 c f)
instance Language.Haskell.TH.Lift.Generics.GLiftArgs GHC.Generics.V1
instance Language.Haskell.TH.Lift.Generics.GLiftArgs GHC.Generics.U1
instance Language.Haskell.TH.Syntax.Lift c => Language.Haskell.TH.Lift.Generics.GLiftArgs (GHC.Generics.K1 i c)
instance Language.Haskell.TH.Lift.Generics.GLiftArgs f => Language.Haskell.TH.Lift.Generics.GLiftArgs (GHC.Generics.S1 s f)
instance (Language.Haskell.TH.Lift.Generics.GLiftArgs f, Language.Haskell.TH.Lift.Generics.GLiftArgs g) => Language.Haskell.TH.Lift.Generics.GLiftArgs (f GHC.Generics.:*: g)
instance Language.Haskell.TH.Lift.Generics.GLiftArgs GHC.Generics.UAddr
instance Language.Haskell.TH.Lift.Generics.GLiftArgs GHC.Generics.UChar
instance Language.Haskell.TH.Lift.Generics.GLiftArgs GHC.Generics.UDouble
instance Language.Haskell.TH.Lift.Generics.GLiftArgs GHC.Generics.UFloat
instance Language.Haskell.TH.Lift.Generics.GLiftArgs GHC.Generics.UInt
instance Language.Haskell.TH.Lift.Generics.GLiftArgs GHC.Generics.UWord
instance (GHC.Generics.Datatype d, Language.Haskell.TH.Lift.Generics.GLiftDatatype f) => Language.Haskell.TH.Lift.Generics.GLift (GHC.Generics.D1 d f)
instance (Language.Haskell.TH.Lift.Generics.GLiftDatatype f, Language.Haskell.TH.Lift.Generics.GLiftDatatype g) => Language.Haskell.TH.Lift.Generics.GLiftDatatype (f GHC.Generics.:+: g)
