{-# LANGUAGE TemplateHaskell #-}
module Language.Syntactic.Functional.Tuple.TH
( deriveSyntacticForTuples
) where
import Language.Haskell.TH
import Data.NestTuple
import Data.NestTuple.TH
import Language.Syntactic ((:<:), Syntactic (..))
import Language.Syntactic.TH
deriveSyntacticForTuples
:: (Type -> Cxt)
-> (Type -> Type)
-> Cxt
-> Int
-> DecsQ
deriveSyntacticForTuples internalPred mkDomain extraConstraint n = return $
map deriveSyntacticForTuple [3..n]
where
deriveSyntacticForTuple w = instD
( concat
[ map (classPred ''Syntactic ConT . return) varsT
, concatMap internalPred $ map (AppT (ConT ''Internal)) varsT
, [classPred ''(:<:) ConT [ConT (mkName "Tuple"), VarT (mkName "sym")]]
, [eqPred domainA (mkDomain (VarT (mkName "sym")))]
, [eqPred domainA (AppT (ConT ''Domain) b)
| b <- tail varsT
]
, extraConstraint
]
)
(AppT (ConT ''Syntactic) tupT)
[ tySynInst ''Domain [tupT] domainA
, tySynInst ''Internal [tupT] tupTI
, FunD 'desugar
[ Clause
[]
(NormalB (foldl AppE (VarE '(.)) $ map VarE [mkName "desugar", 'nest]))
[]
]
, FunD 'sugar
[ Clause
[]
(NormalB (foldl AppE (VarE '(.)) $ map VarE ['unnest, mkName "sugar"]))
[]
]
]
where
varsT = map VarT $ take w varSupply
tupT = foldl AppT (TupleT w) varsT
tupTI = foldNest id mkPairT $ toNest $ map (AppT (ConT ''Internal)) varsT
domainA = AppT (ConT ''Domain) (VarT (mkName "a"))