instance of Lift for Exp

Duncan Coutts <[email protected]>
Newsgroups gmane.comp.lang.haskell.template
Message-ID <1086720298.10002.29.camel@localhost>
Hi all,

the Exp type is not an instance of the Lift class. This is the sensible
thing most of the time so that you do not lift an expression when you
meant to splice it instead.

However in my experience it's sometimes useful (particularly when
writing code that generates code), so attached is a module which makes
it an instance. Like Text.Show.Functions, you should only import it if
you want it, not import it by default.

If people find this useful, I'd be quite happy to have it added to the
standard GHC TH libs. I've named it Language.Haskell.TH.LiftExp and
released it under GHC's BSD-style licence.

Issues:
      * At the moment it also exports instances for Ratio, Maybe,
        PackedString, (,) and (,,). In my opinion these instances should
        be exported from Language.Haskell.TH already in which case they
        could be deleted from this module. (Exporting the instance for
        PackedString and Ratio is not strictly necessary and perhaps not
        desirable.)
      * The encoding for unboxed integers is not pleasant. (Unboxed Ints
        are used in the definition of Name). If anyone can find a more
        straightforward encoding please tell me.

Duncan

_______________________________________________
template-haskell mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/template-haskell
LiftExp.hs (text/x-haskell, 6.2 KB)
{-# OPTIONS -fglasgow-exts #-}
        -- Need GlaExts for the Int# used in Name
-----------------------------------------------------------------------------
-- |
-- Module      :  Language.Haskell.Syntax.LiftExp
-- Copyright   :  (c) Duncan Coutts
-- License     :  BSD-style (see the file libraries/base/LICENSE)
-- 
-- Maintainer  :  [email protected]
-- Stability   :  experimental
-- Portability :  portable
--
-- Optional instance of 'Language.Haskell.Syntax.Lift' for 'ExpQ'.
--
-----------------------------------------------------------------------------

module Language.Haskell.TH.LiftExp () where

import Language.Haskell.TH
import Language.Haskell.TH.Syntax (Name(..), NameSpace(..),
                                   NameFlavour(..), Lift(..))

import Data.PackedString (PackedString, packString, unpackPS)
import qualified GHC.Base (Int(..), Int#)

import Control.Monad (liftM)
import Data.Ratio (Ratio, (%), numerator, denominator)

-----------------------
--
-- Lift instances for Exp and other TH types

instance Lift Exp where
  lift (VarE name)       = [| VarE name |]
  lift (ConE name)       = [| ConE name |]
  lift (LitE lit)        = [| LitE lit  |]
  lift (AppE e1 e2)      = [| AppE e1 e2 |]
  lift (InfixE e1 op e2) = [| InfixE e1 op e2 |]
  lift (LamE pats e)     = [| LamE pats e |]
  lift (TupE es)         = [| TupE es |]
  lift (CondE e1 e2 e3)  = [| CondE e1 e2 e3 |]
  lift (LetE decls e)    = [| LetE decls e |]
  lift (CaseE e matches) = [| CaseE e matches |]
  lift (DoE stmts)       = [| DoE   stmts |]
  lift (CompE stmts)     = [| CompE stmts |]
  lift (ArithSeqE range) = [| ArithSeqE range |]
  lift (ListE es)        = [| ListE es |]
  lift (SigE e t)        = [| SigE e t |]
  lift (RecConE name fs) = [| RecConE name fs |]
  lift (RecUpdE e fs)    = [| RecUpdE e fs |]

instance Lift Name where
  lift (Name occ flavour) = [| Name occ flavour |]

instance Lift NameFlavour where
  lift  NameS                    = [| NameS |]
  lift (NameU n)                 = [| NameU |] `appE` encodeUnboxedInt n
  lift (NameG nameSpace modName) = [| NameG nameSpace modName |]

instance Lift NameSpace where
  lift VarName   = [| VarName |]
  lift DataName  = [| DataName |]
  lift TcClsName = [| TcClsName |]

instance Lift Lit where
  lift (CharL c)       = [| CharL c |]
  lift (StringL s)     = [| StringL |] `appE` litE (stringL s)
  lift (IntegerL n)    = [| IntegerL n |]
  lift (RationalL q)   = [| RationalL q |]
  lift (IntPrimL  n)   = [| IntPrimL n  |]
  lift (FloatPrimL q)  = [| FloatPrimL q |]
  lift (DoublePrimL q) = [| DoublePrimL q |]

instance Lift Pat where
  lift (LitP lit)            = [| LitP lit |]
  lift (VarP name)           = [| VarP name |]
  lift (TupP pats)           = [| TupP pats |]
  lift (ConP name pats)      = [| ConP name pats |]
  lift (TildeP pat)          = [| TildeP pat |]
  lift (AsP name pat)        = [| AsP name pat |]
  lift (WildP)               = [| WildP |]
  lift (RecP name fieldPats) = [| RecP name fieldPats |]
  lift (ListP pats)          = [| ListP pats |]

instance Lift Dec where
  lift (FunD name clauses)          = [| FunD name clauses |]
  lift (ValD pat body decs)         = [| ValD pat body decs |]
  lift (DataD   tys name names1 cons names2) = [| DataD tys name names1 cons names2 |]
  lift (NewtypeD tys name names1 con names2) = [| NewtypeD tys name names1 con names2 |]
  lift (TySynD name names ty)       = [| TySynD name names ty |]
  lift (ClassD tys name names decs) = [| ClassD tys name names decs |]
  lift (InstanceD tys ty decs)      = [| InstanceD tys ty decs |]
  lift (SigD name ty)               = [| SigD name ty |]
  lift (ForeignD fdecl)             = [| ForeignD fdecl |]

instance Lift Clause where
  lift (Clause pats body decls) = [| Clause pats body decls |]

instance Lift Body where
  lift (GuardedB ees) = [| GuardedB ees |]
  lift (NormalB e)    = [| NormalB e |]

instance Lift Match where
  lift (Match pat body decls) = [| Match pat body decls |]
  
instance Lift Stmt where
  lift (BindS pat e) = [| BindS pat e |]
  lift (LetS  decs)  = [| LetS decs |]
  lift (NoBindS e)   = [| NoBindS e |]
  lift (ParS stmtss) = [| ParS stmtss |]

instance Lift Range where
  lift (FromR     e)          = [| FromR e |]
  lift (FromThenR e1 e2)      = [| FromThenR e1 e2 |]
  lift (FromToR   e1 e2)      = [| FromToR e1 e2 |]
  lift (FromThenToR e1 e2 e3) = [| FromThenToR e1 e2 e3 |]

instance Lift Type where
  lift (ForallT names tys ty) = [| ForallT names tys ty |]
  lift (VarT name)    = [| VarT name |]
  lift (ConT name)    = [| VarT name |]
  lift (TupleT n)     = [| TupleT n |]
  lift  ArrowT        = [| ArrowT |]
  lift  ListT         = [| ListT  |]
  lift (AppT ty1 ty2) = [| AppT ty1 ty2 |]

instance Lift Con where
  lift (NormalC name  sts) = [| NormalC name sts |]
  lift (RecC    name vsts) = [| RecC    name vsts |]
  lift (InfixC s1 name s2) = [| InfixC s1 name s2 |]

instance Lift Strict where
  lift IsStrict  = [| IsStrict |]
  lift NotStrict = [| NotStrict |]

instance Lift Foreign where
  lift (ImportF cconv safty s name ty) = [| ImportF cconv safty s name ty |]

instance Lift Callconv where
  lift CCall   = [| CCall |]
  lift StdCall = [| StdCall |]

instance Lift Safety where
  lift Unsafe     = [| Unsafe |] 
  lift Safe       = [| Safe |]
  lift Threadsafe = [| Threadsafe |]

-----------------------
--
-- Various general encodings

-- This one is not very nice
encodeUnboxedInt :: GHC.Base.Int# -> ExpQ
encodeUnboxedInt n = let n' :: Int = fromIntegral (GHC.Base.I# n)
                      in [| \(GHC.Base.I# i) -> i |] `appE` [| n' |]

-- These two could be in the standard TH libs but the point is debatable.
-- They are not strictly necessary but make the code above neater.
instance Lift PackedString where
  lift s = [| packString |] `appE` litE (stringL $ unpackPS s)

instance (Integral a, Lift a) => Lift (Ratio a) where
  lift q = let n = numerator q
               d = denominator q
            in [| n % d |]

-- These ones should be in the standard TH libs
instance Lift a => Lift (Maybe a) where
  lift Nothing  = [| Nothing |]
  lift (Just e) = [| Just e |]

instance (Lift a, Lift b) => Lift (a,b) where
  lift (a,b) = [| (a,b) |]

instance (Lift a, Lift b, Lift c) => Lift (a,b,c) where
  lift (a,b,c) = [| (a,b,c) |]
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.