module Optics.TH.Internal.Utils where
import Data.Maybe
import Language.Haskell.TH
import qualified Data.Map as M
import qualified Data.Set as S
import qualified Language.Haskell.TH.Datatype as D
import Data.Set.Optics
import Language.Haskell.TH.Optics.Internal
import Optics.Core
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)
bndrName :: TyVarBndr -> Name
bndrName (PlainTV n ) = n
bndrName (KindedTV n _) = n
newNames :: String -> Int -> Q [Name]
newNames base n = sequence [ newName (base++show i) | i <- [1..n] ]
eqSubst :: Type -> String -> Q (Type, Pred)
eqSubst ty n = do
placeholder <- VarT <$> newName n
pure (placeholder, D.equalPred placeholder ty)
addKindVars :: D.DatatypeInfo -> Type -> Type
addKindVars = substType . M.fromList . mapMaybe var . D.datatypeInstTypes
where
var t@(SigT (VarT n) k)
| has typeVars k = Just (n, t)
| otherwise = Nothing
var _ = Nothing
quantifyType :: [TyVarBndr] -> Cxt -> Type -> Type
quantifyType = quantifyType' S.empty
quantifyType' :: S.Set Name -> [TyVarBndr] -> Cxt -> Type -> Type
quantifyType' exclude vars cx t = ForallT vs cx t
where
vs = filter (\v -> bndrName v `S.notMember` exclude)
. D.freeVariablesWellScoped
$ map bndrToType vars ++ S.toList (setOf typeVarsKinded t)
bndrToType (PlainTV n) = VarT n
bndrToType (KindedTV n k) = SigT (VarT n) k
inlinePragma :: Name -> [DecQ]
inlinePragma methodName = [pragInlD methodName Inline FunLike AllPhases]