{-# LANGUAGE CPP #-}
{-# LANGUAGE PatternGuards #-}
module Data.Functor.Invariant.TH (
deriveInvariant
, deriveInvariantOptions
, deriveInvariant2
, deriveInvariant2Options
, makeInvmap
, makeInvmapOptions
, makeInvmap2
, makeInvmap2Options
, Options(..)
, defaultOptions
) where
import Control.Monad (unless, when)
import Data.Functor.Invariant.TH.Internal
import qualified Data.List as List
import qualified Data.Map as Map ((!), fromList, keys, lookup, member, size)
import Data.Maybe
import Language.Haskell.TH.Datatype as Datatype
import Language.Haskell.TH.Datatype.TyVarBndr
import Language.Haskell.TH.Lib
import Language.Haskell.TH.Ppr
import Language.Haskell.TH.Syntax
newtype Options = Options
{ Options -> Bool
emptyCaseBehavior :: Bool
} deriving (Options -> Options -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Options -> Options -> Bool
$c/= :: Options -> Options -> Bool
== :: Options -> Options -> Bool
$c== :: Options -> Options -> Bool
Eq, Eq Options
Options -> Options -> Bool
Options -> Options -> Ordering
Options -> Options -> Options
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Options -> Options -> Options
$cmin :: Options -> Options -> Options
max :: Options -> Options -> Options
$cmax :: Options -> Options -> Options
>= :: Options -> Options -> Bool
$c>= :: Options -> Options -> Bool
> :: Options -> Options -> Bool
$c> :: Options -> Options -> Bool
<= :: Options -> Options -> Bool
$c<= :: Options -> Options -> Bool
< :: Options -> Options -> Bool
$c< :: Options -> Options -> Bool
compare :: Options -> Options -> Ordering
$ccompare :: Options -> Options -> Ordering
Ord, ReadPrec [Options]
ReadPrec Options
Int -> ReadS Options
ReadS [Options]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [Options]
$creadListPrec :: ReadPrec [Options]
readPrec :: ReadPrec Options
$creadPrec :: ReadPrec Options
readList :: ReadS [Options]
$creadList :: ReadS [Options]
readsPrec :: Int -> ReadS Options
$creadsPrec :: Int -> ReadS Options
Read, Int -> Options -> ShowS
[Options] -> ShowS
Options -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Options] -> ShowS
$cshowList :: [Options] -> ShowS
show :: Options -> String
$cshow :: Options -> String
showsPrec :: Int -> Options -> ShowS
$cshowsPrec :: Int -> Options -> ShowS
Show)
defaultOptions :: Options
defaultOptions :: Options
defaultOptions = Options { emptyCaseBehavior :: Bool
emptyCaseBehavior = Bool
False }
deriveInvariant :: Name -> Q [Dec]
deriveInvariant :: Name -> Q [Dec]
deriveInvariant = Options -> Name -> Q [Dec]
deriveInvariantOptions Options
defaultOptions
deriveInvariantOptions :: Options -> Name -> Q [Dec]
deriveInvariantOptions :: Options -> Name -> Q [Dec]
deriveInvariantOptions = InvariantClass -> Options -> Name -> Q [Dec]
deriveInvariantClass InvariantClass
Invariant
deriveInvariant2 :: Name -> Q [Dec]
deriveInvariant2 :: Name -> Q [Dec]
deriveInvariant2 = Options -> Name -> Q [Dec]
deriveInvariant2Options Options
defaultOptions
deriveInvariant2Options :: Options -> Name -> Q [Dec]
deriveInvariant2Options :: Options -> Name -> Q [Dec]
deriveInvariant2Options = InvariantClass -> Options -> Name -> Q [Dec]
deriveInvariantClass InvariantClass
Invariant2
makeInvmap :: Name -> Q Exp
makeInvmap :: Name -> Q Exp
makeInvmap = Options -> Name -> Q Exp
makeInvmapOptions Options
defaultOptions
makeInvmapOptions :: Options -> Name -> Q Exp
makeInvmapOptions :: Options -> Name -> Q Exp
makeInvmapOptions = InvariantClass -> Options -> Name -> Q Exp
makeInvmapClass InvariantClass
Invariant
makeInvmap2 :: Name -> Q Exp
makeInvmap2 :: Name -> Q Exp
makeInvmap2 = Options -> Name -> Q Exp
makeInvmap2Options Options
defaultOptions
makeInvmap2Options :: Options -> Name -> Q Exp
makeInvmap2Options :: Options -> Name -> Q Exp
makeInvmap2Options = InvariantClass -> Options -> Name -> Q Exp
makeInvmapClass InvariantClass
Invariant2
deriveInvariantClass :: InvariantClass -> Options -> Name -> Q [Dec]
deriveInvariantClass :: InvariantClass -> Options -> Name -> Q [Dec]
deriveInvariantClass InvariantClass
iClass Options
opts Name
name = do
DatatypeInfo
info <- Name -> Q DatatypeInfo
reifyDatatype Name
name
case DatatypeInfo
info of
DatatypeInfo { datatypeContext :: DatatypeInfo -> [Type]
datatypeContext = [Type]
ctxt
, datatypeName :: DatatypeInfo -> Name
datatypeName = Name
parentName
, datatypeInstTypes :: DatatypeInfo -> [Type]
datatypeInstTypes = [Type]
instTys
, datatypeVariant :: DatatypeInfo -> DatatypeVariant
datatypeVariant = DatatypeVariant
variant
, datatypeCons :: DatatypeInfo -> [ConstructorInfo]
datatypeCons = [ConstructorInfo]
cons
} -> do
([Type]
instanceCxt, Type
instanceType)
<- InvariantClass
-> Name -> [Type] -> [Type] -> DatatypeVariant -> Q ([Type], Type)
buildTypeInstance InvariantClass
iClass Name
parentName [Type]
ctxt [Type]
instTys DatatypeVariant
variant
(forall a. a -> [a] -> [a]
:[]) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
`fmap` forall (m :: * -> *).
Quote m =>
m [Type] -> m Type -> [m Dec] -> m Dec
instanceD (forall (m :: * -> *) a. Monad m => a -> m a
return [Type]
instanceCxt)
(forall (m :: * -> *) a. Monad m => a -> m a
return Type
instanceType)
(InvariantClass
-> Options -> Name -> [Type] -> [ConstructorInfo] -> [Q Dec]
invmapDecs InvariantClass
iClass Options
opts Name
parentName [Type]
instTys [ConstructorInfo]
cons)
invmapDecs :: InvariantClass -> Options -> Name -> [Type] -> [ConstructorInfo]
-> [Q Dec]
invmapDecs :: InvariantClass
-> Options -> Name -> [Type] -> [ConstructorInfo] -> [Q Dec]
invmapDecs InvariantClass
iClass Options
opts Name
parentName [Type]
instTys [ConstructorInfo]
cons =
[ forall (m :: * -> *). Quote m => Name -> [m Clause] -> m Dec
funD (InvariantClass -> Name
invmapName InvariantClass
iClass)
[ forall (m :: * -> *).
Quote m =>
[m Pat] -> m Body -> [m Dec] -> m Clause
clause []
(forall (m :: * -> *). Quote m => m Exp -> m Body
normalB forall a b. (a -> b) -> a -> b
$ InvariantClass
-> Options -> Name -> [Type] -> [ConstructorInfo] -> Q Exp
makeInvmapForCons InvariantClass
iClass Options
opts Name
parentName [Type]
instTys [ConstructorInfo]
cons)
[]
]
]
makeInvmapClass :: InvariantClass -> Options -> Name -> Q Exp
makeInvmapClass :: InvariantClass -> Options -> Name -> Q Exp
makeInvmapClass InvariantClass
iClass Options
opts Name
name = do
DatatypeInfo
info <- Name -> Q DatatypeInfo
reifyDatatype Name
name
case DatatypeInfo
info of
DatatypeInfo { datatypeContext :: DatatypeInfo -> [Type]
datatypeContext = [Type]
ctxt
, datatypeName :: DatatypeInfo -> Name
datatypeName = Name
parentName
, datatypeInstTypes :: DatatypeInfo -> [Type]
datatypeInstTypes = [Type]
instTys
, datatypeVariant :: DatatypeInfo -> DatatypeVariant
datatypeVariant = DatatypeVariant
variant
, datatypeCons :: DatatypeInfo -> [ConstructorInfo]
datatypeCons = [ConstructorInfo]
cons
} ->
InvariantClass
-> Name -> [Type] -> [Type] -> DatatypeVariant -> Q ([Type], Type)
buildTypeInstance InvariantClass
iClass Name
parentName [Type]
ctxt [Type]
instTys DatatypeVariant
variant
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> InvariantClass
-> Options -> Name -> [Type] -> [ConstructorInfo] -> Q Exp
makeInvmapForCons InvariantClass
iClass Options
opts Name
parentName [Type]
instTys [ConstructorInfo]
cons
makeInvmapForCons :: InvariantClass -> Options -> Name -> [Type] -> [ConstructorInfo]
-> Q Exp
makeInvmapForCons :: InvariantClass
-> Options -> Name -> [Type] -> [ConstructorInfo] -> Q Exp
makeInvmapForCons InvariantClass
iClass Options
opts Name
_parentName [Type]
instTys [ConstructorInfo]
cons = do
Name
value <- forall (m :: * -> *). Quote m => String -> m Name
newName String
"value"
[Name]
covMaps <- String -> Int -> Q [Name]
newNameList String
"covMap" Int
numNbs
[Name]
contraMaps <- String -> Int -> Q [Name]
newNameList String
"contraMap" Int
numNbs
let mapFuns :: [(Name, Name)]
mapFuns = forall a b. [a] -> [b] -> [(a, b)]
zip [Name]
covMaps [Name]
contraMaps
lastTyVars :: [Name]
lastTyVars = forall a b. (a -> b) -> [a] -> [b]
map Type -> Name
varTToName forall a b. (a -> b) -> a -> b
$ forall a. Int -> [a] -> [a]
drop (forall (t :: * -> *) a. Foldable t => t a -> Int
length [Type]
instTys forall a. Num a => a -> a -> a
- Int
numNbs) [Type]
instTys
tvMap :: Map Name (Name, Name)
tvMap = forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList forall a b. (a -> b) -> a -> b
$ forall a b. [a] -> [b] -> [(a, b)]
zip [Name]
lastTyVars [(Name, Name)]
mapFuns
argNames :: [Name]
argNames = forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat (forall a. [[a]] -> [[a]]
List.transpose [[Name]
covMaps, [Name]
contraMaps]) forall a. [a] -> [a] -> [a]
++ [Name
value]
forall (m :: * -> *). Quote m => [m Pat] -> m Exp -> m Exp
lamE (forall a b. (a -> b) -> [a] -> [b]
map forall (m :: * -> *). Quote m => Name -> m Pat
varP [Name]
argNames)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *). Quote m => [m Exp] -> m Exp
appsE
forall a b. (a -> b) -> a -> b
$ [ forall (m :: * -> *). Quote m => Name -> m Exp
varE forall a b. (a -> b) -> a -> b
$ InvariantClass -> Name
invmapConstName InvariantClass
iClass
, Name -> Map Name (Name, Name) -> Q Exp
makeFun Name
value Map Name (Name, Name)
tvMap
] forall a. [a] -> [a] -> [a]
++ forall a b. (a -> b) -> [a] -> [b]
map forall (m :: * -> *). Quote m => Name -> m Exp
varE [Name]
argNames
where
numNbs :: Int
numNbs :: Int
numNbs = forall a. Enum a => a -> Int
fromEnum InvariantClass
iClass
makeFun :: Name -> TyVarMap -> Q Exp
makeFun :: Name -> Map Name (Name, Name) -> Q Exp
makeFun Name
value Map Name (Name, Name)
tvMap = do
#if MIN_VERSION_template_haskell(2,9,0)
[Role]
roles <- Name -> Q [Role]
reifyRoles Name
_parentName
let rroles :: [Role]
rroles = [Role]
roles
#endif
case () of
()
_
#if MIN_VERSION_template_haskell(2,9,0)
| (forall (t :: * -> *) a. Foldable t => t a -> Int
length [Role]
rroles forall a. Ord a => a -> a -> Bool
>= Int
numNbs) Bool -> Bool -> Bool
&&
(forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (forall a. Eq a => a -> a -> Bool
== Role
PhantomR) (forall a. Int -> [a] -> [a]
drop (forall (t :: * -> *) a. Foldable t => t a -> Int
length [Role]
rroles forall a. Num a => a -> a -> a
- Int
numNbs) [Role]
rroles))
-> forall (m :: * -> *). Quote m => Name -> m Exp
varE Name
coerceValName forall (m :: * -> *). Quote m => m Exp -> m Exp -> m Exp
`appE` forall (m :: * -> *). Quote m => Name -> m Exp
varE Name
value
#endif
| forall (t :: * -> *) a. Foldable t => t a -> Bool
null [ConstructorInfo]
cons Bool -> Bool -> Bool
&& Options -> Bool
emptyCaseBehavior Options
opts Bool -> Bool -> Bool
&& Bool
ghc7'8OrLater
-> forall (m :: * -> *). Quote m => m Exp -> [m Match] -> m Exp
caseE (forall (m :: * -> *). Quote m => Name -> m Exp
varE Name
value) []
| forall (t :: * -> *) a. Foldable t => t a -> Bool
null [ConstructorInfo]
cons
-> forall (m :: * -> *). Quote m => m Exp -> m Exp -> m Exp
appE (forall (m :: * -> *). Quote m => Name -> m Exp
varE Name
seqValName) (forall (m :: * -> *). Quote m => Name -> m Exp
varE Name
value) forall (m :: * -> *). Quote m => m Exp -> m Exp -> m Exp
`appE`
forall (m :: * -> *). Quote m => m Exp -> m Exp -> m Exp
appE (forall (m :: * -> *). Quote m => Name -> m Exp
varE Name
errorValName)
(forall (m :: * -> *). Quote m => String -> m Exp
stringE forall a b. (a -> b) -> a -> b
$ String
"Void " forall a. [a] -> [a] -> [a]
++ Name -> String
nameBase (InvariantClass -> Name
invmapName InvariantClass
iClass))
| Bool
otherwise
-> forall (m :: * -> *). Quote m => m Exp -> [m Match] -> m Exp
caseE (forall (m :: * -> *). Quote m => Name -> m Exp
varE Name
value)
(forall a b. (a -> b) -> [a] -> [b]
map (InvariantClass
-> Map Name (Name, Name) -> ConstructorInfo -> Q Match
makeInvmapForCon InvariantClass
iClass Map Name (Name, Name)
tvMap) [ConstructorInfo]
cons)
ghc7'8OrLater :: Bool
#if __GLASGOW_HASKELL__ >= 708
ghc7'8OrLater :: Bool
ghc7'8OrLater = Bool
True
#else
ghc7'8OrLater = False
#endif
makeInvmapForCon :: InvariantClass -> TyVarMap -> ConstructorInfo -> Q Match
makeInvmapForCon :: InvariantClass
-> Map Name (Name, Name) -> ConstructorInfo -> Q Match
makeInvmapForCon InvariantClass
iClass Map Name (Name, Name)
tvMap
con :: ConstructorInfo
con@(ConstructorInfo { constructorName :: ConstructorInfo -> Name
constructorName = Name
conName
, constructorContext :: ConstructorInfo -> [Type]
constructorContext = [Type]
ctxt }) = do
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (Type -> [Name] -> Bool
`predMentionsName` forall k a. Map k a -> [k]
Map.keys Map Name (Name, Name)
tvMap) [Type]
ctxt
Bool -> Bool -> Bool
|| forall k a. Map k a -> Int
Map.size Map Name (Name, Name)
tvMap forall a. Ord a => a -> a -> Bool
< forall a. Enum a => a -> Int
fromEnum InvariantClass
iClass) forall a b. (a -> b) -> a -> b
$
forall a. Name -> Q a
existentialContextError Name
conName
[Exp -> Q Exp]
parts <- forall a.
InvariantClass
-> Map Name (Name, Name) -> FFoldType a -> ConstructorInfo -> Q [a]
foldDataConArgs InvariantClass
iClass Map Name (Name, Name)
tvMap FFoldType (Exp -> Q Exp)
ft_invmap ConstructorInfo
con
Name -> [Exp -> Q Exp] -> Q Match
match_for_con Name
conName [Exp -> Q Exp]
parts
where
ft_invmap :: FFoldType (Exp -> Q Exp)
ft_invmap :: FFoldType (Exp -> Q Exp)
ft_invmap = FT { ft_triv :: Exp -> Q Exp
ft_triv = forall (m :: * -> *) a. Monad m => a -> m a
return
, ft_var :: Name -> Exp -> Q Exp
ft_var = \Name
v Exp
x -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Name -> Exp
VarE (forall a b. (a, b) -> a
fst (Map Name (Name, Name)
tvMap forall k a. Ord k => Map k a -> k -> a
Map.! Name
v)) Exp -> Exp -> Exp
`AppE` Exp
x
, ft_co_var :: Name -> Exp -> Q Exp
ft_co_var = \Name
v Exp
x -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Name -> Exp
VarE (forall a b. (a, b) -> b
snd (Map Name (Name, Name)
tvMap forall k a. Ord k => Map k a -> k -> a
Map.! Name
v)) Exp -> Exp -> Exp
`AppE` Exp
x
, ft_fun :: (Exp -> Q Exp) -> (Exp -> Q Exp) -> Exp -> Q Exp
ft_fun = \Exp -> Q Exp
g Exp -> Q Exp
h Exp
x -> (Exp -> Q Exp) -> Q Exp
mkSimpleLam forall a b. (a -> b) -> a -> b
$ \Exp
b -> do
Exp
gg <- Exp -> Q Exp
g Exp
b
Exp -> Q Exp
h forall a b. (a -> b) -> a -> b
$ Exp
x Exp -> Exp -> Exp
`AppE` Exp
gg
, ft_tup :: TupleSort -> [Exp -> Q Exp] -> Exp -> Q Exp
ft_tup = forall a.
(Name -> [a] -> Q Match) -> TupleSort -> [a] -> Exp -> Q Exp
mkSimpleTupleCase Name -> [Exp -> Q Exp] -> Q Match
match_for_con
, ft_ty_app :: Bool -> [(Type, Exp -> Q Exp, Exp -> Q Exp)] -> Exp -> Q Exp
ft_ty_app = \Bool
contravariant [(Type, Exp -> Q Exp, Exp -> Q Exp)]
argGs Exp
x -> do
let inspect :: (Type, Exp -> Q Exp, Exp -> Q Exp) -> [Q Exp]
inspect :: (Type, Exp -> Q Exp, Exp -> Q Exp) -> [Q Exp]
inspect (Type
argTy, Exp -> Q Exp
g, Exp -> Q Exp
h)
| Just Name
argVar <- Type -> Maybe Name
varTToName_maybe Type
argTy
, Just (Name
covMap, Name
contraMap) <- forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Name
argVar Map Name (Name, Name)
tvMap
= forall a b. (a -> b) -> [a] -> [b]
map (forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. Name -> Exp
VarE) forall a b. (a -> b) -> a -> b
$
if Bool
contravariant
then [Name
contraMap, Name
covMap]
else [Name
covMap, Name
contraMap]
| Bool
otherwise
= [(Exp -> Q Exp) -> Q Exp
mkSimpleLam Exp -> Q Exp
g, (Exp -> Q Exp) -> Q Exp
mkSimpleLam Exp -> Q Exp
h]
forall (m :: * -> *). Quote m => [m Exp] -> m Exp
appsE forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *). Quote m => Name -> m Exp
varE (InvariantClass -> Name
invmapName (forall a. Enum a => Int -> a
toEnum (forall (t :: * -> *) a. Foldable t => t a -> Int
length [(Type, Exp -> Q Exp, Exp -> Q Exp)]
argGs)))
forall a. a -> [a] -> [a]
: forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (Type, Exp -> Q Exp, Exp -> Q Exp) -> [Q Exp]
inspect [(Type, Exp -> Q Exp, Exp -> Q Exp)]
argGs
forall a. [a] -> [a] -> [a]
++ [forall (m :: * -> *) a. Monad m => a -> m a
return Exp
x]
, ft_forall :: [TyVarBndrSpec] -> (Exp -> Q Exp) -> Exp -> Q Exp
ft_forall = \[TyVarBndrSpec]
_ Exp -> Q Exp
g Exp
x -> Exp -> Q Exp
g Exp
x
, ft_bad_app :: Exp -> Q Exp
ft_bad_app = \Exp
_ -> forall a. Name -> Q a
outOfPlaceTyVarError Name
conName
}
match_for_con :: Name -> [Exp -> Q Exp] -> Q Match
match_for_con :: Name -> [Exp -> Q Exp] -> Q Match
match_for_con = forall a. (Name -> [a] -> Q Exp) -> Name -> [Exp -> a] -> Q Match
mkSimpleConMatch forall a b. (a -> b) -> a -> b
$ \Name
conName' [Q Exp]
xs ->
forall (m :: * -> *). Quote m => [m Exp] -> m Exp
appsE (forall (m :: * -> *). Quote m => Name -> m Exp
conE Name
conName'forall a. a -> [a] -> [a]
:[Q Exp]
xs)
buildTypeInstance :: InvariantClass
-> Name
-> Cxt
-> [Type]
-> DatatypeVariant
-> Q (Cxt, Type)
buildTypeInstance :: InvariantClass
-> Name -> [Type] -> [Type] -> DatatypeVariant -> Q ([Type], Type)
buildTypeInstance InvariantClass
iClass Name
tyConName [Type]
dataCxt [Type]
varTysOrig DatatypeVariant
variant = do
[Type]
varTysExp <- forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM Type -> Q Type
resolveTypeSynonyms [Type]
varTysOrig
let remainingLength :: Int
remainingLength :: Int
remainingLength = forall (t :: * -> *) a. Foldable t => t a -> Int
length [Type]
varTysOrig forall a. Num a => a -> a -> a
- forall a. Enum a => a -> Int
fromEnum InvariantClass
iClass
droppedTysExp :: [Type]
droppedTysExp :: [Type]
droppedTysExp = forall a. Int -> [a] -> [a]
drop Int
remainingLength [Type]
varTysExp
droppedStarKindStati :: [StarKindStatus]
droppedStarKindStati :: [StarKindStatus]
droppedStarKindStati = forall a b. (a -> b) -> [a] -> [b]
map Type -> StarKindStatus
canRealizeKindStar [Type]
droppedTysExp
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
remainingLength forall a. Ord a => a -> a -> Bool
< Int
0 Bool -> Bool -> Bool
|| forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (forall a. Eq a => a -> a -> Bool
== StarKindStatus
NotKindStar) [StarKindStatus]
droppedStarKindStati) forall a b. (a -> b) -> a -> b
$
forall a. InvariantClass -> Name -> Q a
derivingKindError InvariantClass
iClass Name
tyConName
let droppedKindVarNames :: [Name]
droppedKindVarNames :: [Name]
droppedKindVarNames = [StarKindStatus] -> [Name]
catKindVarNames [StarKindStatus]
droppedStarKindStati
varTysExpSubst :: [Type]
varTysExpSubst :: [Type]
varTysExpSubst = forall a b. (a -> b) -> [a] -> [b]
map ([Name] -> Type -> Type
substNamesWithKindStar [Name]
droppedKindVarNames) [Type]
varTysExp
remainingTysExpSubst, droppedTysExpSubst :: [Type]
([Type]
remainingTysExpSubst, [Type]
droppedTysExpSubst) =
forall a. Int -> [a] -> ([a], [a])
splitAt Int
remainingLength [Type]
varTysExpSubst
droppedTyVarNames :: [Name]
droppedTyVarNames :: [Name]
droppedTyVarNames = forall a. TypeSubstitution a => a -> [Name]
freeVariables [Type]
droppedTysExpSubst
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Type -> Bool
hasKindStar [Type]
droppedTysExpSubst) forall a b. (a -> b) -> a -> b
$
forall a. InvariantClass -> Name -> Q a
derivingKindError InvariantClass
iClass Name
tyConName
let preds :: [Maybe Pred]
kvNames :: [[Name]]
kvNames' :: [Name]
([Maybe Type]
preds, [[Name]]
kvNames) = forall a b. [(a, b)] -> ([a], [b])
unzip forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map (InvariantClass -> Type -> (Maybe Type, [Name])
deriveConstraint InvariantClass
iClass) [Type]
remainingTysExpSubst
kvNames' :: [Name]
kvNames' = forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[Name]]
kvNames
remainingTysExpSubst' :: [Type]
remainingTysExpSubst' :: [Type]
remainingTysExpSubst' =
forall a b. (a -> b) -> [a] -> [b]
map ([Name] -> Type -> Type
substNamesWithKindStar [Name]
kvNames') [Type]
remainingTysExpSubst
remainingTysOrigSubst :: [Type]
remainingTysOrigSubst :: [Type]
remainingTysOrigSubst =
forall a b. (a -> b) -> [a] -> [b]
map ([Name] -> Type -> Type
substNamesWithKindStar (forall a. Eq a => [a] -> [a] -> [a]
List.union [Name]
droppedKindVarNames [Name]
kvNames'))
forall a b. (a -> b) -> a -> b
$ forall a. Int -> [a] -> [a]
take Int
remainingLength [Type]
varTysOrig
Bool
isDataFamily <-
case DatatypeVariant
variant of
DatatypeVariant
Datatype -> forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
DatatypeVariant
Newtype -> forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
DatatypeVariant
DataInstance -> forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
DatatypeVariant
NewtypeInstance -> forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
#if MIN_VERSION_th_abstraction(0,5,0)
DatatypeVariant
Datatype.TypeData -> forall a. Name -> Q a
typeDataError Name
tyConName
#endif
let remainingTysOrigSubst' :: [Type]
remainingTysOrigSubst' :: [Type]
remainingTysOrigSubst' =
if Bool
isDataFamily
then [Type]
remainingTysOrigSubst
else forall a b. (a -> b) -> [a] -> [b]
map Type -> Type
unSigT [Type]
remainingTysOrigSubst
instanceCxt :: Cxt
instanceCxt :: [Type]
instanceCxt = forall a. [Maybe a] -> [a]
catMaybes [Maybe Type]
preds
instanceType :: Type
instanceType :: Type
instanceType = Type -> Type -> Type
AppT (Name -> Type
ConT forall a b. (a -> b) -> a -> b
$ InvariantClass -> Name
invariantClassName InvariantClass
iClass)
forall a b. (a -> b) -> a -> b
$ Name -> [Type] -> Type
applyTyCon Name
tyConName [Type]
remainingTysOrigSubst'
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (Type -> [Name] -> Bool
`predMentionsName` [Name]
droppedTyVarNames) [Type]
dataCxt) forall a b. (a -> b) -> a -> b
$
forall a. Name -> Type -> Q a
datatypeContextError Name
tyConName Type
instanceType
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless ([Type] -> [Type] -> Bool
canEtaReduce [Type]
remainingTysExpSubst' [Type]
droppedTysExpSubst) forall a b. (a -> b) -> a -> b
$
forall a. Type -> Q a
etaReductionError Type
instanceType
forall (m :: * -> *) a. Monad m => a -> m a
return ([Type]
instanceCxt, Type
instanceType)
deriveConstraint :: InvariantClass -> Type -> (Maybe Pred, [Name])
deriveConstraint :: InvariantClass -> Type -> (Maybe Type, [Name])
deriveConstraint InvariantClass
iClass Type
t
| Bool -> Bool
not (Type -> Bool
isTyVar Type
t) = (forall a. Maybe a
Nothing, [])
| Bool
otherwise = case Int -> Type -> Maybe [Name]
hasKindVarChain Int
1 Type
t of
Just [Name]
ns | InvariantClass
iClass forall a. Ord a => a -> a -> Bool
>= InvariantClass
Invariant
-> (forall a. a -> Maybe a
Just (Name -> Name -> Type
applyClass Name
invariantTypeName Name
tName), [Name]
ns)
Maybe [Name]
_ -> case Int -> Type -> Maybe [Name]
hasKindVarChain Int
2 Type
t of
Just [Name]
ns | InvariantClass
iClass forall a. Eq a => a -> a -> Bool
== InvariantClass
Invariant2
-> (forall a. a -> Maybe a
Just (Name -> Name -> Type
applyClass Name
invariant2TypeName Name
tName), [Name]
ns)
Maybe [Name]
_ -> (forall a. Maybe a
Nothing, [])
where
tName :: Name
tName :: Name
tName = Type -> Name
varTToName Type
t
derivingKindError :: InvariantClass -> Name -> Q a
derivingKindError :: forall a. InvariantClass -> Name -> Q a
derivingKindError InvariantClass
iClass Name
tyConName = forall (m :: * -> *) a. MonadFail m => String -> m a
fail
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
"Cannot derive well-kinded instance of form ‘"
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
className
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> ShowS
showChar Char
' '
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bool -> ShowS -> ShowS
showParen Bool
True
( String -> ShowS
showString (Name -> String
nameBase Name
tyConName)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
" ..."
)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
"‘\n\tClass "
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
className
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
" expects an argument of kind "
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString (forall a. Ppr a => a -> String
pprint forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Type
createKindChain forall a b. (a -> b) -> a -> b
$ forall a. Enum a => a -> Int
fromEnum InvariantClass
iClass)
forall a b. (a -> b) -> a -> b
$ String
""
where
className :: String
className :: String
className = Name -> String
nameBase forall a b. (a -> b) -> a -> b
$ InvariantClass -> Name
invariantClassName InvariantClass
iClass
datatypeContextError :: Name -> Type -> Q a
datatypeContextError :: forall a. Name -> Type -> Q a
datatypeContextError Name
dataName Type
instanceType = forall (m :: * -> *) a. MonadFail m => String -> m a
fail
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
"Can't make a derived instance of ‘"
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString (forall a. Ppr a => a -> String
pprint Type
instanceType)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
"‘:\n\tData type ‘"
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString (Name -> String
nameBase Name
dataName)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
"‘ must not have a class context involving the last type argument(s)"
forall a b. (a -> b) -> a -> b
$ String
""
existentialContextError :: Name -> Q a
existentialContextError :: forall a. Name -> Q a
existentialContextError Name
conName = forall (m :: * -> *) a. MonadFail m => String -> m a
fail
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
"Constructor ‘"
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString (Name -> String
nameBase Name
conName)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
"‘ must be truly polymorphic in the last argument(s) of the data type"
forall a b. (a -> b) -> a -> b
$ String
""
outOfPlaceTyVarError :: Name -> Q a
outOfPlaceTyVarError :: forall a. Name -> Q a
outOfPlaceTyVarError Name
conName = forall (m :: * -> *) a. MonadFail m => String -> m a
fail
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
"Constructor ‘"
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString (Name -> String
nameBase Name
conName)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
"‘ must only use its last two type variable(s) within"
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
" the last two argument(s) of a data type"
forall a b. (a -> b) -> a -> b
$ String
""
etaReductionError :: Type -> Q a
etaReductionError :: forall a. Type -> Q a
etaReductionError Type
instanceType = forall (m :: * -> *) a. MonadFail m => String -> m a
fail forall a b. (a -> b) -> a -> b
$
String
"Cannot eta-reduce to an instance of form \n\tinstance (...) => "
forall a. [a] -> [a] -> [a]
++ forall a. Ppr a => a -> String
pprint Type
instanceType
#if MIN_VERSION_th_abstraction(0,5,0)
typeDataError :: Name -> Q a
typeDataError :: forall a. Name -> Q a
typeDataError Name
dataName = forall (m :: * -> *) a. MonadFail m => String -> m a
fail
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
"Cannot derive instance for ‘"
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString (Name -> String
nameBase Name
dataName)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
"‘, which is a ‘type data‘ declaration"
forall a b. (a -> b) -> a -> b
$ String
""
#endif
data FFoldType a
= FT { forall a. FFoldType a -> a
ft_triv :: a
, forall a. FFoldType a -> Name -> a
ft_var :: Name -> a
, forall a. FFoldType a -> Name -> a
ft_co_var :: Name -> a
, forall a. FFoldType a -> a -> a -> a
ft_fun :: a -> a -> a
, forall a. FFoldType a -> TupleSort -> [a] -> a
ft_tup :: TupleSort -> [a] -> a
, forall a. FFoldType a -> Bool -> [(Type, a, a)] -> a
ft_ty_app :: Bool -> [(Type, a, a)] -> a
, forall a. FFoldType a -> a
ft_bad_app :: a
, forall a. FFoldType a -> [TyVarBndrSpec] -> a -> a
ft_forall :: [TyVarBndrSpec] -> a -> a
}
functorLikeTraverse :: InvariantClass
-> TyVarMap
-> FFoldType a
-> Type
-> Q a
functorLikeTraverse :: forall a.
InvariantClass
-> Map Name (Name, Name) -> FFoldType a -> Type -> Q a
functorLikeTraverse InvariantClass
iClass Map Name (Name, Name)
tvMap (FT { ft_triv :: forall a. FFoldType a -> a
ft_triv = a
caseTrivial, ft_var :: forall a. FFoldType a -> Name -> a
ft_var = Name -> a
caseVar
, ft_co_var :: forall a. FFoldType a -> Name -> a
ft_co_var = Name -> a
caseCoVar, ft_fun :: forall a. FFoldType a -> a -> a -> a
ft_fun = a -> a -> a
caseFun
, ft_tup :: forall a. FFoldType a -> TupleSort -> [a] -> a
ft_tup = TupleSort -> [a] -> a
caseTuple, ft_ty_app :: forall a. FFoldType a -> Bool -> [(Type, a, a)] -> a
ft_ty_app = Bool -> [(Type, a, a)] -> a
caseTyApp
, ft_bad_app :: forall a. FFoldType a -> a
ft_bad_app = a
caseWrongArg, ft_forall :: forall a. FFoldType a -> [TyVarBndrSpec] -> a -> a
ft_forall = [TyVarBndrSpec] -> a -> a
caseForAll })
Type
ty
= do Type
ty' <- Type -> Q Type
resolveTypeSynonyms Type
ty
(a
res, Bool
_) <- Bool -> Type -> Q (a, Bool)
go Bool
False Type
ty'
forall (m :: * -> *) a. Monad m => a -> m a
return a
res
where
go :: Bool -> Type -> Q (a, Bool)
go Bool
co t :: Type
t@AppT{}
| (Type
ArrowT, [Type
funArg, Type
funRes]) <- Type -> (Type, [Type])
unapplyTy Type
t
= do (a
funArgR, Bool
funArgC) <- Bool -> Type -> Q (a, Bool)
go (Bool -> Bool
not Bool
co) Type
funArg
(a
funResR, Bool
funResC) <- Bool -> Type -> Q (a, Bool)
go Bool
co Type
funRes
if Bool
funArgC Bool -> Bool -> Bool
|| Bool
funResC
then forall (m :: * -> *) a. Monad m => a -> m a
return (a -> a -> a
caseFun a
funArgR a
funResR, Bool
True)
else Q (a, Bool)
trivial
go Bool
co t :: Type
t@AppT{} = do
let (Type
f, [Type]
args) = Type -> (Type, [Type])
unapplyTy Type
t
(a
_, Bool
fc) <- Bool -> Type -> Q (a, Bool)
go Bool
co Type
f
([a]
xrs, [Bool]
xcs) <- forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a b. [(a, b)] -> ([a], [b])
unzip forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (Bool -> Type -> Q (a, Bool)
go Bool
co) [Type]
args
([a]
contraXrs, [Bool]
_) <- forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a b. [(a, b)] -> ([a], [b])
unzip forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (Bool -> Type -> Q (a, Bool)
go (Bool -> Bool
not Bool
co)) [Type]
args
let numLastArgs, numFirstArgs :: Int
numLastArgs :: Int
numLastArgs = forall a. Ord a => a -> a -> a
min (forall a. Enum a => a -> Int
fromEnum InvariantClass
iClass) (forall (t :: * -> *) a. Foldable t => t a -> Int
length [Type]
args)
numFirstArgs :: Int
numFirstArgs = forall (t :: * -> *) a. Foldable t => t a -> Int
length [Type]
args forall a. Num a => a -> a -> a
- Int
numLastArgs
tuple :: TupleSort -> m (a, Bool)
tuple TupleSort
tupSort = forall (m :: * -> *) a. Monad m => a -> m a
return (TupleSort -> [a] -> a
caseTuple TupleSort
tupSort [a]
xrs, Bool
True)
wrongArg :: Q (a, Bool)
wrongArg = forall (m :: * -> *) a. Monad m => a -> m a
return (a
caseWrongArg, Bool
True)
case () of
()
_ | Bool -> Bool
not (forall (t :: * -> *). Foldable t => t Bool -> Bool
or [Bool]
xcs)
-> Q (a, Bool)
trivial
| TupleT Int
len <- Type
f
-> forall {m :: * -> *}. Monad m => TupleSort -> m (a, Bool)
tuple forall a b. (a -> b) -> a -> b
$ Int -> TupleSort
Boxed Int
len
#if MIN_VERSION_template_haskell(2,6,0)
| UnboxedTupleT Int
len <- Type
f
-> forall {m :: * -> *}. Monad m => TupleSort -> m (a, Bool)
tuple forall a b. (a -> b) -> a -> b
$ Int -> TupleSort
Unboxed Int
len
#endif
| Bool
fc Bool -> Bool -> Bool
|| forall (t :: * -> *). Foldable t => t Bool -> Bool
or (forall a. Int -> [a] -> [a]
take Int
numFirstArgs [Bool]
xcs)
-> Q (a, Bool)
wrongArg
| Bool
otherwise
-> do Bool
itf <- [Name] -> Type -> [Type] -> Q Bool
isInTypeFamilyApp [Name]
tyVarNames Type
f [Type]
args
if Bool
itf
then Q (a, Bool)
wrongArg
else forall (m :: * -> *) a. Monad m => a -> m a
return ( Bool -> [(Type, a, a)] -> a
caseTyApp Bool
co forall a b. (a -> b) -> a -> b
$ forall a. Int -> [a] -> [a]
drop Int
numFirstArgs
forall a b. (a -> b) -> a -> b
$ forall a b c. [a] -> [b] -> [c] -> [(a, b, c)]
zip3 [Type]
args [a]
xrs [a]
contraXrs
, Bool
True )
go Bool
co (SigT Type
t Type
k) = do
(a
_, Bool
kc) <- Bool -> Type -> Q (a, Bool)
go_kind Bool
co Type
k
if Bool
kc
then forall (m :: * -> *) a. Monad m => a -> m a
return (a
caseWrongArg, Bool
True)
else Bool -> Type -> Q (a, Bool)
go Bool
co Type
t
go Bool
co (VarT Name
v)
| forall k a. Ord k => k -> Map k a -> Bool
Map.member Name
v Map Name (Name, Name)
tvMap
= forall (m :: * -> *) a. Monad m => a -> m a
return (if Bool
co then Name -> a
caseCoVar Name
v else Name -> a
caseVar Name
v, Bool
True)
| Bool
otherwise
= Q (a, Bool)
trivial
go Bool
co (ForallT [TyVarBndrSpec]
tvbs [Type]
_ Type
t) = do
(a
tr, Bool
tc) <- Bool -> Type -> Q (a, Bool)
go Bool
co Type
t
let tvbNames :: [Name]
tvbNames = forall a b. (a -> b) -> [a] -> [b]
map forall flag. TyVarBndr_ flag -> Name
tvName [TyVarBndrSpec]
tvbs
if Bool -> Bool
not Bool
tc Bool -> Bool -> Bool
|| forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Name]
tvbNames) [Name]
tyVarNames
then Q (a, Bool)
trivial
else forall (m :: * -> *) a. Monad m => a -> m a
return ([TyVarBndrSpec] -> a -> a
caseForAll [TyVarBndrSpec]
tvbs a
tr, Bool
True)
go Bool
_ Type
_ = Q (a, Bool)
trivial
#if MIN_VERSION_template_haskell(2,9,0)
go_kind :: Bool -> Type -> Q (a, Bool)
go_kind = Bool -> Type -> Q (a, Bool)
go
#else
go_kind _ _ = trivial
#endif
trivial :: Q (a, Bool)
trivial = forall (m :: * -> *) a. Monad m => a -> m a
return (a
caseTrivial, Bool
False)
tyVarNames :: [Name]
tyVarNames :: [Name]
tyVarNames = forall k a. Map k a -> [k]
Map.keys Map Name (Name, Name)
tvMap
foldDataConArgs :: InvariantClass -> TyVarMap -> FFoldType a -> ConstructorInfo -> Q [a]
foldDataConArgs :: forall a.
InvariantClass
-> Map Name (Name, Name) -> FFoldType a -> ConstructorInfo -> Q [a]
foldDataConArgs InvariantClass
iClass Map Name (Name, Name)
tvMap FFoldType a
ft ConstructorInfo
con = do
[Type]
fieldTys <- forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM Type -> Q Type
resolveTypeSynonyms forall a b. (a -> b) -> a -> b
$ ConstructorInfo -> [Type]
constructorFields ConstructorInfo
con
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM Type -> Q a
foldArg [Type]
fieldTys
where
foldArg :: Type -> Q a
foldArg = forall a.
InvariantClass
-> Map Name (Name, Name) -> FFoldType a -> Type -> Q a
functorLikeTraverse InvariantClass
iClass Map Name (Name, Name)
tvMap FFoldType a
ft
mkSimpleLam :: (Exp -> Q Exp) -> Q Exp
mkSimpleLam :: (Exp -> Q Exp) -> Q Exp
mkSimpleLam Exp -> Q Exp
lam = do
Name
n <- forall (m :: * -> *). Quote m => String -> m Name
newName String
"n"
Exp
body <- Exp -> Q Exp
lam (Name -> Exp
VarE Name
n)
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ [Pat] -> Exp -> Exp
LamE [Name -> Pat
VarP Name
n] Exp
body
mkSimpleConMatch :: (Name -> [a] -> Q Exp)
-> Name
-> [Exp -> a]
-> Q Match
mkSimpleConMatch :: forall a. (Name -> [a] -> Q Exp) -> Name -> [Exp -> a] -> Q Match
mkSimpleConMatch Name -> [a] -> Q Exp
fold Name
conName [Exp -> a]
insides = do
[Name]
varsNeeded <- String -> Int -> Q [Name]
newNameList String
"_arg" forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) a. Foldable t => t a -> Int
length [Exp -> a]
insides
let pat :: Pat
pat = Name -> [Type] -> [Pat] -> Pat
ConP Name
conName
#if MIN_VERSION_template_haskell(2,18,0)
[]
#endif
(forall a b. (a -> b) -> [a] -> [b]
map Name -> Pat
VarP [Name]
varsNeeded)
Exp
rhs <- Name -> [a] -> Q Exp
fold Name
conName (forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (\Exp -> a
i Name
v -> Exp -> a
i forall a b. (a -> b) -> a -> b
$ Name -> Exp
VarE Name
v) [Exp -> a]
insides [Name]
varsNeeded)
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Pat -> Body -> [Dec] -> Match
Match Pat
pat (Exp -> Body
NormalB Exp
rhs) []
data TupleSort
= Boxed Int
#if MIN_VERSION_template_haskell(2,6,0)
| Unboxed Int
#endif
mkSimpleTupleCase :: (Name -> [a] -> Q Match)
-> TupleSort -> [a] -> Exp -> Q Exp
mkSimpleTupleCase :: forall a.
(Name -> [a] -> Q Match) -> TupleSort -> [a] -> Exp -> Q Exp
mkSimpleTupleCase Name -> [a] -> Q Match
matchForCon TupleSort
tupSort [a]
insides Exp
x = do
let tupDataName :: Name
tupDataName = case TupleSort
tupSort of
Boxed Int
len -> Int -> Name
tupleDataName Int
len
#if MIN_VERSION_template_haskell(2,6,0)
Unboxed Int
len -> Int -> Name
unboxedTupleDataName Int
len
#endif
Match
m <- Name -> [a] -> Q Match
matchForCon Name
tupDataName [a]
insides
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Exp -> [Match] -> Exp
CaseE Exp
x [Match
m]