packages feed

th-lift 0.7.2 → 0.7.5

raw patch · 4 files changed

+150/−34 lines, 4 filesdep +ghc-primdep ~template-haskellPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: ghc-prim

Dependency ranges changed: template-haskell

API changes (from Hackage documentation)

- Language.Haskell.TH.Lift: instance Integral a => Lift (Ratio a)
- Language.Haskell.TH.Lift: instance Lift ()
- Language.Haskell.TH.Lift: instance Lift ModName
- Language.Haskell.TH.Lift: instance Lift Name
- Language.Haskell.TH.Lift: instance Lift NameFlavour
- Language.Haskell.TH.Lift: instance Lift NameSpace
- Language.Haskell.TH.Lift: instance Lift OccName
- Language.Haskell.TH.Lift: instance Lift PkgName
+ Language.Haskell.TH.Lift: instance Language.Haskell.TH.Syntax.Lift Language.Haskell.TH.Syntax.ModName
+ Language.Haskell.TH.Lift: instance Language.Haskell.TH.Syntax.Lift Language.Haskell.TH.Syntax.Name
+ Language.Haskell.TH.Lift: instance Language.Haskell.TH.Syntax.Lift Language.Haskell.TH.Syntax.NameFlavour
+ Language.Haskell.TH.Lift: instance Language.Haskell.TH.Syntax.Lift Language.Haskell.TH.Syntax.NameSpace
+ Language.Haskell.TH.Lift: instance Language.Haskell.TH.Syntax.Lift Language.Haskell.TH.Syntax.OccName
+ Language.Haskell.TH.Lift: instance Language.Haskell.TH.Syntax.Lift Language.Haskell.TH.Syntax.PkgName
+ Language.Haskell.TH.Lift: makeLift :: Name -> Q Exp
+ Language.Haskell.TH.Lift: makeLift' :: Info -> Q Exp

Files

src/Language/Haskell/TH/Lift.hs view
@@ -11,6 +11,8 @@   , deriveLiftMany   , deriveLift'   , deriveLiftMany'+  , makeLift+  , makeLift'   , Lift(..)   ) where @@ -18,16 +20,23 @@ import Data.PackedString (PackedString, packString, unpackPS) #endif /* MIN_VERSION_template_haskell(2,4,0) */ -#if __GLASGOW_HASKELL__ < 710-import GHC.Exts (Int(..))-#endif+import GHC.Base (unpackCString#)+import GHC.Exts (Double(..), Float(..), Int(..), Word(..))+import GHC.Prim (Addr#, Double#, Float#, Int#, Word#)+#if MIN_VERSION_template_haskell(2,11,0)+import GHC.Exts (Char(..))+import GHC.Prim (Char#)+#endif /* !(MIN_VERSION_template_haskell(2,11,0)) */ +#if MIN_VERSION_template_haskell(2,8,0)+import Data.Char (ord)+#endif /* !(MIN_VERSION_template_haskell(2,8,0)) */ #if !(MIN_VERSION_template_haskell(2,10,0)) import Data.Ratio (Ratio) #endif /* !(MIN_VERSION_template_haskell(2,10,0)) */ import Language.Haskell.TH import Language.Haskell.TH.Syntax-import Control.Monad ((<=<))+import Control.Monad ((<=<), zipWithM) #if MIN_VERSION_template_haskell(2,9,0) import Data.Maybe (catMaybes) #endif /* MIN_VERSION_template_haskell(2,9,0) */@@ -51,14 +60,24 @@ deriveLiftMany' :: [Info] -> Q [Dec] deriveLiftMany' = mapM deriveLiftOne +-- | Generates a lambda expresson which behaves like 'lift' (without requiring+-- a 'Lift' instance). Example:+--+-- @+-- newtype Fix f = In { out :: f (Fix f) }+--+-- instance Lift (f (Fix f)) => Lift (Fix f) where+--   lift = $(makeLift ''Fix)+-- @+makeLift :: Name -> Q Exp+makeLift = makeLift' <=< reify++-- | Like 'makeLift', but using a custom reification function.+makeLift' :: Info -> Q Exp+makeLift' i = withInfo i $ \_ n _ cons -> makeLiftOne n cons+ deriveLiftOne :: Info -> Q Dec-deriveLiftOne i =-    case i of-      TyConI (DataD dcx n vsk cons _) ->-        liftInstance dcx n (map unTyVarBndr vsk) cons-      TyConI (NewtypeD dcx n vsk con _) ->-        liftInstance dcx n (map unTyVarBndr vsk) [con]-      _ -> error (modName ++ ".deriveLift: unhandled: " ++ pprint i)+deriveLiftOne i = withInfo i liftInstance   where     liftInstance dcx n vs cons = do #if MIN_VERSION_template_haskell(2,9,0)@@ -73,7 +92,7 @@ #endif       instanceD (ctxt dcx phvars vs)                 (conT ''Lift `appT` typ n (map fst vs))-                [funD 'lift (map doCons cons)]+                [funD 'lift [clause [] (normalB (makeLiftOne n cons)) []]]     typ n = foldl appT (conT n) . map varT     -- Only consider *-kinded type variables, because Lift instances cannot     -- meaningfully be given to types of other kinds. Further, filter out type@@ -81,40 +100,97 @@     ctxt dcx phvars =         fmap (dcx ++) . cxt . concatMap liftPred . filter (`notElem` phvars) #if MIN_VERSION_template_haskell(2,10,0)-    unTyVarBndr (PlainTV v) = (v, StarT)-    unTyVarBndr (KindedTV v k) = (v, k)     liftPred (v, StarT) = [conT ''Lift `appT` varT v]     liftPred (_, _) = [] #elif MIN_VERSION_template_haskell(2,8,0)-    unTyVarBndr (PlainTV v) = (v, StarT)-    unTyVarBndr (KindedTV v k) = (v, k)     liftPred (v, StarT) = [classP ''Lift [varT v]]     liftPred (_, _) = [] #elif MIN_VERSION_template_haskell(2,4,0)-    unTyVarBndr (PlainTV v) = (v, StarK)-    unTyVarBndr (KindedTV v k) = (v, k)     liftPred (v, StarK) = [classP ''Lift [varT v]]     liftPred (_, _) = []-#else /* template-haskell < 2.4.0 */-    unTyVarBndr v = v+#else /* !(MIN_VERSION_template_haskell(2,4,0)) */     liftPred n = conT ''Lift `appT` varT n #endif -doCons :: Con -> Q Clause+makeLiftOne :: Name -> [Con] -> Q Exp+makeLiftOne n cons = do+  e <- newName "e"+  lam1E (varP e) $ caseE (varE e) $ consMatches n cons++consMatches :: Name -> [Con] -> [Q Match]+consMatches n [] = [match wildP (normalB e) []]+  where+    e = [| errorQExp $(stringE ("Can't lift value of empty datatype " ++ nameBase n)) |]+consMatches _ cons = map doCons cons++doCons :: Con -> Q Match doCons (NormalC c sts) = do-    let ns = zipWith (\_ i -> "x" ++ show (i :: Int)) sts [0..]-        con = [| conE c |]-        args = [ [| lift $(varE (mkName n)) |] | n <- ns ]+    ns <- zipWithM (\_ i -> newName ('x':show (i :: Int))) sts [0..]+    let con = [| conE c |]+        args = [ liftVar n t | (n, (_, t)) <- zip ns sts ]         e = foldl (\e1 e2 -> [| appE $e1 $e2 |]) con args-    clause [conP c (map (varP . mkName) ns)] (normalB e) []+    match (conP c (map varP ns)) (normalB e) [] doCons (RecC c sts) = doCons $ NormalC c [(s, t) | (_, s, t) <- sts]-doCons (InfixC _sty1 c _sty2) = do+doCons (InfixC sty1 c sty2) = do+    x0 <- newName "x0"+    x1 <- newName "x1"     let con = [| conE c |]-        left = [| lift $(varE (mkName "x0")) |]-        right = [| lift $(varE (mkName "x1")) |]+        left = liftVar x0 (snd sty1)+        right = liftVar x1 (snd sty2)         e = [| infixApp $left $con $right |]-    clause [infixP (varP (mkName "x0")) c (varP (mkName "x1"))] (normalB e) []+    match (infixP (varP x0) c (varP x1)) (normalB e) [] doCons (ForallC _ _ c) = doCons c++liftVar :: Name -> Type -> Q Exp+liftVar varName (ConT tyName)+#if MIN_VERSION_template_haskell(2,8,0)+  | tyName == ''Addr#   = [| litE (stringPrimL (map (fromIntegral . ord)+                                                    (unpackCString# $var))) |]+#else /* !(MIN_VERSION_template_haskell(2,8,0)) */+  | tyName == ''Addr#   = [| litE (stringPrimL (unpackCString# $var))       |]+#endif+#if MIN_VERSION_template_haskell(2,11,0)+  | tyName == ''Char#   = [| litE (charPrimL               (C# $var))  |]+#endif  /* !(MIN_VERSION_template_haskell(2,11,0)) */+  | tyName == ''Double# = [| litE (doublePrimL (toRational (D# $var))) |]+  | tyName == ''Float#  = [| litE (floatPrimL  (toRational (F# $var))) |]+  | tyName == ''Int#    = [| litE (intPrimL    (toInteger  (I# $var))) |]+  | tyName == ''Word#   = [| litE (wordPrimL   (toInteger  (W# $var))) |]+  where+    var :: Q Exp+    var = varE varName+liftVar varName _ = [| lift $(varE varName) |]++withInfo :: Info+#if MIN_VERSION_template_haskell(2,4,0)+         -> (Cxt -> Name -> [(Name, Kind)] -> [Con] -> Q a)+#else /* !(MIN_VERSION_template_haskell(2,4,0)) */+         -> (Cxt -> Name -> [Name]         -> [Con] -> Q a)+#endif+         -> Q a+withInfo i f = case i of+    TyConI (DataD dcx n vsk cons _) ->+        f dcx n (map unTyVarBndr vsk) cons+    TyConI (NewtypeD dcx n vsk con _) ->+        f dcx n (map unTyVarBndr vsk) [con]+    _ -> error (modName ++ ".deriveLift: unhandled: " ++ pprint i)+  where+#if MIN_VERSION_template_haskell(2,8,0)+    unTyVarBndr (PlainTV v) = (v, StarT)+    unTyVarBndr (KindedTV v k) = (v, k)+#elif MIN_VERSION_template_haskell(2,4,0)+    unTyVarBndr (PlainTV v) = (v, StarK)+    unTyVarBndr (KindedTV v k) = (v, k)+#else /* !(MIN_VERSION_template_haskell(2,4,0)) */+    unTyVarBndr :: Name -> Name+    unTyVarBndr v = v+#endif++-- A type-restricted version of error that ensures makeLift always returns a+-- value of type Q Exp, even when used on an empty datatype.+errorQExp :: String -> Q Exp+errorQExp = error+{-# INLINE errorQExp #-}  instance Lift Name where   lift (Name occName nameFlavour) = [| Name occName nameFlavour |]
t/Foo.hs view
@@ -1,7 +1,17 @@ {-# LANGUAGE CPP #-}+{-# LANGUAGE EmptyDataDecls #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE UndecidableInstances #-} module Foo where +import GHC.Prim (Double#, Float#, Int#, Word#)+#if MIN_VERSION_template_haskell(2,11,0)+import GHC.Prim (Char#)+#endif+ import Language.Haskell.TH.Lift  -- Phantom type parameters can't be dealt with poperly on GHC < 7.8.@@ -15,5 +25,25 @@ newtype Rec a = Rec { field :: a }                 deriving Show +data Empty a++data Unboxed = Unboxed {+-- Template Haskell couldn't handle unlifted chars on GHC < 8.0+#if MIN_VERSION_template_haskell(2,11,0)+  primChar   :: Char#,+#endif+  primDouble :: Double#,+  primFloat  :: Float#,+  primInt    :: Int#,+  primWord   :: Word#+  } deriving Show++newtype Fix f = In { out :: f (Fix f) }+deriving instance Show (f (Fix f)) => Show (Fix f)+ $(deriveLift ''Foo) $(deriveLift ''Rec)+$(deriveLift ''Empty)+$(deriveLift ''Unboxed)+instance Lift (f (Fix f)) => Lift (Fix f) where+  lift = $(makeLift ''Fix)
t/Test.hs view
@@ -1,3 +1,5 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE MagicHash #-} {-# LANGUAGE TemplateHaskell #-} module Main (main) where @@ -8,3 +10,9 @@ main = do print $( lift (Foo "str1" 'c') )           print $( lift (Bar "str2") )           print $( lift (Rec {field = 'a'}) )+          print $( lift (Unboxed+#if MIN_VERSION_template_haskell(2,11,0)+                          'a'#+#endif+                          1.0## 1.0# 1# 1##) )+          print $( lift (In { out = Nothing }) )
th-lift.cabal view
@@ -1,5 +1,5 @@ Name:               th-lift-Version:            0.7.2+Version:            0.7.5 Cabal-Version:      >= 1.8 License:            BSD3 License-Files:      COPYING, BSD3, GPL-2@@ -11,7 +11,7 @@ Description:   Derive Template Haskell's Lift class for datatypes. Category:           Language-Tested-With:        GHC==7.4, GHC==7.6, GHC==7.8+Tested-With:        GHC==7.4.2, GHC==7.6.3, GHC==7.8.4, GHC==7.10.2 build-type:         Simple Extra-source-files: Changelog @@ -23,14 +23,15 @@   Exposed-modules: Language.Haskell.TH.Lift   Extensions:      CPP, TemplateHaskell, MagicHash, TypeSynonymInstances, FlexibleInstances   Hs-Source-Dirs:  src-  Build-Depends:   base >= 3 && < 5+  Build-Depends:   base >= 3 && < 5,+                   ghc-prim    ghc-options:     -Wall   if impl(ghc < 6.12)     Build-Depends: packedstring == 0.1.*,                    template-haskell >= 2.2 && < 2.4   else-    Build-Depends: template-haskell >= 2.4 && < 2.11+    Build-Depends: template-haskell >= 2.4 && < 2.12  Test-Suite test   Type:             exitcode-stdio-1.0@@ -39,9 +40,10 @@   other-modules:    Foo   ghc-options:      -Wall   Build-Depends:    base >= 3 && < 5,+                    ghc-prim,                     th-lift   if impl(ghc < 6.12)     Build-Depends: packedstring == 0.1.*,                    template-haskell >= 2.2 && < 2.4   else-    Build-Depends: template-haskell >= 2.4 && < 2.11+    Build-Depends: template-haskell >= 2.4 && < 2.12