lift-generics-0.1.2: GHC.Generics-based Language.Haskell.TH.Syntax.lift implementation

Copyright(C) 2015-2017 Ryan Scott
LicenseBSD-style (see the file LICENSE)
MaintainerRyan Scott
Safe HaskellNone
LanguageHaskell2010

Language.Haskell.TH.Lift.Generics

Contents

Description

GHC.Generics-based approach to implementing lift.

Synopsis

Documentation

genericLiftWithPkg :: (Generic a, GLift (Rep a)) => String -> a -> Q Exp Source #

GHC.Generics-based lift 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 genericLiftWithPkg without shooting yourself in the foot:

{-# 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

As you can see, this trick only works if (1) the current package key is known (i.e., the Lift 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., base, ghc-prim, template-haskell, etc.).

Once the Lift Foo instance is defined, you can splice Foo values directly into Haskell source code:

{-# LANGUAGE TemplateHaskell #-}
module Bar where

import Foo
import Language.Haskell.TH.Syntax

foo :: Foo
foo = $(lift (Foo 1 a "baz"))

genericLift :: (Generic a, GLift (Rep a)) => a -> Q Exp Source #

GHC.Generics-based lift implementation. Only available on GHC 8.0 and later due to API limitations of earlier GHC versions.

Unlike genericLiftWithPkg, this function does all of the work for you:

{-# 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

Now you can splice Foo values directly into Haskell source code:

{-# LANGUAGE TemplateHaskell #-}
module Bar where

import Foo
import Language.Haskell.TH.Syntax

foo :: Foo
foo = $(lift (Foo 1 a "baz"))

class GLift f where Source #

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.

Minimal complete definition

glift

Methods

glift :: String -> f a -> Q Exp Source #

Instances

(Datatype Meta d, GLiftDatatype f) => GLift (D1 d f) Source # 

Methods

glift :: String -> D1 d f a -> Q Exp Source #

class GLiftDatatype f where Source #

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.

Minimal complete definition

gliftWith

Methods

gliftWith :: String -> String -> f a -> Q Exp Source #

Instances

(GLiftDatatype f, GLiftDatatype g) => GLiftDatatype ((:+:) f g) Source # 

Methods

gliftWith :: String -> String -> (f :+: g) a -> Q Exp Source #

(Constructor Meta c, GLiftArgs f) => GLiftDatatype (C1 c f) Source # 

Methods

gliftWith :: String -> String -> C1 c f a -> Q Exp Source #

class GLiftArgs f where Source #

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.

Minimal complete definition

gliftArgs

Methods

gliftArgs :: f a -> [Q Exp] Source #

Instances

GLiftArgs V1 Source # 

Methods

gliftArgs :: V1 a -> [Q Exp] Source #

GLiftArgs U1 Source # 

Methods

gliftArgs :: U1 a -> [Q Exp] Source #

GLiftArgs UAddr Source # 

Methods

gliftArgs :: UAddr a -> [Q Exp] Source #

GLiftArgs UChar Source # 

Methods

gliftArgs :: UChar a -> [Q Exp] Source #

GLiftArgs UDouble Source # 

Methods

gliftArgs :: UDouble a -> [Q Exp] Source #

GLiftArgs UFloat Source # 

Methods

gliftArgs :: UFloat a -> [Q Exp] Source #

GLiftArgs UInt Source # 

Methods

gliftArgs :: UInt a -> [Q Exp] Source #

GLiftArgs UWord Source # 

Methods

gliftArgs :: UWord a -> [Q Exp] Source #

Lift c => GLiftArgs (K1 i c) Source # 

Methods

gliftArgs :: K1 i c a -> [Q Exp] Source #

(GLiftArgs f, GLiftArgs g) => GLiftArgs ((:*:) f g) Source # 

Methods

gliftArgs :: (f :*: g) a -> [Q Exp] Source #

GLiftArgs f => GLiftArgs (S1 s f) Source # 

Methods

gliftArgs :: S1 s f a -> [Q Exp] Source #

Lift reexport

class Lift t where #

A Lift 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 ([| ... |]) but not at the top level. As an example:

add1 :: Int -> Q Exp
add1 x = [| x + 1 |]

Template Haskell has no way of knowing what value x will take on at splice-time, so it requires the type of x to be an instance of Lift.

Lift instances can be derived automatically by use of the -XDeriveLift GHC language extension:

{-# LANGUAGE DeriveLift #-}
module Foo where

import Language.Haskell.TH.Syntax

data Bar a = Bar1 a (Bar a) | Bar2 String
  deriving Lift

Methods

lift :: t -> Q Exp #

Turn a value into a Template Haskell expression, suitable for use in a splice.

Instances

Lift Bool 

Methods

lift :: Bool -> Q Exp #

Lift Char 

Methods

lift :: Char -> Q Exp #

Lift Double 

Methods

lift :: Double -> Q Exp #

Lift Float 

Methods

lift :: Float -> Q Exp #

Lift Int 

Methods

lift :: Int -> Q Exp #

Lift Int8 

Methods

lift :: Int8 -> Q Exp #

Lift Int16 

Methods

lift :: Int16 -> Q Exp #

Lift Int32 

Methods

lift :: Int32 -> Q Exp #

Lift Int64 

Methods

lift :: Int64 -> Q Exp #

Lift Integer 

Methods

lift :: Integer -> Q Exp #

Lift Word 

Methods

lift :: Word -> Q Exp #

Lift Word8 

Methods

lift :: Word8 -> Q Exp #

Lift Word16 

Methods

lift :: Word16 -> Q Exp #

Lift Word32 

Methods

lift :: Word32 -> Q Exp #

Lift Word64 

Methods

lift :: Word64 -> Q Exp #

Lift () 

Methods

lift :: () -> Q Exp #

Lift Natural 

Methods

lift :: Natural -> Q Exp #

Lift a => Lift [a] 

Methods

lift :: [a] -> Q Exp #

Lift a => Lift (Maybe a) 

Methods

lift :: Maybe a -> Q Exp #

Integral a => Lift (Ratio a) 

Methods

lift :: Ratio a -> Q Exp #

(Lift a, Lift b) => Lift (Either a b) 

Methods

lift :: Either a b -> Q Exp #

(Lift a, Lift b) => Lift (a, b) 

Methods

lift :: (a, b) -> Q Exp #

(Lift a, Lift b, Lift c) => Lift (a, b, c) 

Methods

lift :: (a, b, c) -> Q Exp #

(Lift a, Lift b, Lift c, Lift d) => Lift (a, b, c, d) 

Methods

lift :: (a, b, c, d) -> Q Exp #

(Lift a, Lift b, Lift c, Lift d, Lift e) => Lift (a, b, c, d, e) 

Methods

lift :: (a, b, c, d, e) -> Q Exp #

(Lift a, Lift b, Lift c, Lift d, Lift e, Lift f) => Lift (a, b, c, d, e, f) 

Methods

lift :: (a, b, c, d, e, f) -> Q Exp #

(Lift a, Lift b, Lift c, Lift d, Lift e, Lift f, Lift g) => Lift (a, b, c, d, e, f, g) 

Methods

lift :: (a, b, c, d, e, f, g) -> Q Exp #