{-# LANGUAGE CPP #-}
{-# LANGUAGE TemplateHaskellQuotes #-}
#ifdef TRUSTWORTHY
# if MIN_VERSION_template_haskell(2,12,0)
{-# LANGUAGE Safe #-}
# else
{-# LANGUAGE Trustworthy #-}
# endif
#endif
#include "lens-common.h"
module Control.Lens.Internal.TH where
import Control.Lens.Iso
import Control.Lens.Prism
import Control.Lens.Review
import Control.Lens.Type
import Control.Lens.Wrapped
import Data.Functor.Contravariant
import qualified Data.Set as Set
import Data.Set (Set)
import Language.Haskell.TH
import qualified Language.Haskell.TH.Datatype as D
import qualified Language.Haskell.TH.Datatype.TyVarBndr as D
appsT :: TypeQ -> [TypeQ] -> TypeQ
appsT = foldl appT
appsE1 :: ExpQ -> [ExpQ] -> ExpQ
appsE1 = foldl appE
toTupleT :: [TypeQ] -> TypeQ
toTupleT [x] = x
toTupleT xs = appsT (tupleT (length xs)) xs
toTupleE :: [ExpQ] -> ExpQ
toTupleE [x] = x
toTupleE xs = tupE xs
toTupleP :: [PatQ] -> PatQ
toTupleP [x] = x
toTupleP xs = tupP xs
conAppsT :: Name -> [Type] -> Type
conAppsT conName = foldl AppT (ConT conName)
newNames :: String -> Int -> Q [Name]
newNames base n = sequence [ newName (base++show i) | i <- [1..n] ]
unfoldType :: Type -> (Type, [Type])
unfoldType = go []
where
go :: [Type] -> Type -> (Type, [Type])
go acc (ForallT _ _ ty) = go acc ty
go acc (AppT ty1 ty2) = go (ty2:acc) ty1
go acc (SigT ty _) = go acc ty
go acc (ParensT ty) = go acc ty
#if MIN_VERSION_template_haskell(2,15,0)
go acc (AppKindT ty _) = go acc ty
#endif
go acc ty = (ty, acc)
datatypeTypeKinded :: D.DatatypeInfo -> Type
datatypeTypeKinded di
= foldl AppT (ConT (D.datatypeName di))
$ dropSigsIfNonDataFam di
$ D.datatypeInstTypes di
dropSigsIfNonDataFam :: D.DatatypeInfo -> [Type] -> [Type]
dropSigsIfNonDataFam di
| isDataFamily (D.datatypeVariant di) = id
| otherwise = map dropSig
where
dropSig :: Type -> Type
dropSig (SigT t k) | null (D.freeVariables k) = t
dropSig t = t
quantifyType :: Cxt -> Type -> Type
quantifyType = quantifyType' Set.empty
quantifyType' :: Set Name -> Cxt -> Type -> Type
quantifyType' exclude c t = ForallT vs c t
where
vs = filter (\tvb -> D.tvName tvb `Set.notMember` exclude)
$ D.changeTVFlags D.SpecifiedSpec
$ D.freeVariablesWellScoped (t:c)
tvbToType :: D.TyVarBndr_ flag -> Type
tvbToType = D.elimTV VarT (SigT . VarT)
unSigT :: Type -> Type
unSigT (SigT t _) = t
unSigT t = t
isDataFamily :: D.DatatypeVariant -> Bool
isDataFamily D.Datatype = False
isDataFamily D.Newtype = False
isDataFamily D.DataInstance = True
isDataFamily D.NewtypeInstance = True
#if MIN_VERSION_th_abstraction(0,5,0)
isDataFamily D.TypeData = False
#endif
traversalTypeName :: Name
traversalTypeName = ''Traversal
traversal'TypeName :: Name
traversal'TypeName = ''Traversal'
lensTypeName :: Name
lensTypeName = ''Lens
lens'TypeName :: Name
lens'TypeName = ''Lens'
isoTypeName :: Name
isoTypeName = ''Iso
iso'TypeName :: Name
iso'TypeName = ''Iso'
getterTypeName :: Name
getterTypeName = ''Getter
foldTypeName :: Name
foldTypeName = ''Fold
prismTypeName :: Name
prismTypeName = ''Prism
prism'TypeName :: Name
prism'TypeName = ''Prism'
reviewTypeName :: Name
reviewTypeName = ''Review
wrappedTypeName :: Name
wrappedTypeName = ''Wrapped
unwrappedTypeName :: Name
unwrappedTypeName = ''Unwrapped
rewrappedTypeName :: Name
rewrappedTypeName = ''Rewrapped
_wrapped'ValName :: Name
_wrapped'ValName = '_Wrapped'
isoValName :: Name
isoValName = 'iso
prismValName :: Name
prismValName = 'prism
untoValName :: Name
untoValName = 'unto
phantomValName :: Name
phantomValName = 'phantom2
phantom2 :: (Functor f, Contravariant f) => f a -> f b
phantom2 = phantom
{-# INLINE phantom2 #-}
composeValName :: Name
composeValName = '(.)
idValName :: Name
idValName = 'id
fmapValName :: Name
fmapValName = 'fmap
pureValName :: Name
pureValName = 'pure
apValName :: Name
apValName = '(<*>)
rightDataName :: Name
rightDataName = 'Right
leftDataName :: Name
leftDataName = 'Left
inlinePragma :: Name -> [DecQ]
inlinePragma methodName = [pragInlD methodName Inline FunLike AllPhases]