{-# Language CPP, PolyKinds, TypeFamilies, KindSignatures, TemplateHaskell, GADTs #-} {-| Module : Main Description : Test cases for the th-abstraction package Copyright : Eric Mertens 2017 License : ISC Maintainer : emertens@gmail.com This module checks that the 'reifyDatatype' logic works consistently across a wide range of datatypes. These tests are validated across the versions of GHC supported by this package. -} module Main (main) where import Language.Haskell.TH import Language.Haskell.TH.Datatype import Harness type Gadt1Int = Gadt1 Int data Gadt1 (a :: *) where Gadtc1 :: Int -> Gadt1Int Gadtc2 :: (a,a) -> Gadt1 a data Adt1 (a :: *) (b :: *) = Adtc1 (a,b) | Bool `Adtc2` Int data Gadtrec1 a where Gadtrecc1, Gadtrecc2 :: { gadtrec1a :: a, gadtrec1b :: b } -> Gadtrec1 (a,b) data Equal :: * -> * -> * -> * where Equalc :: (Read a, Show a) => [a] -> Maybe a -> Equal a a a data Showable :: * where Showable :: Show a => a -> Showable data R = R1 { field1, field2 :: Int } data Gadt2 :: * -> * -> * where Gadt2c1 :: Gadt2 a [a] Gadt2c2 :: Gadt2 [a] a Gadt2c3 :: Gadt2 [a] [a] data family DF (a :: *) data instance DF (Maybe a) = DFMaybe Int [a] #if MIN_VERSION_template_haskell(2,9,0) data family DF1 (a :: k) #elif MIN_VERSION_template_haskell(2,8,0) data family DF1 a #else data family DF1 (a :: *) #endif data instance DF1 b = DF1 b data VoidStoS (f :: * -> *) return [] -- segment type declarations above from refiy below -- | Test entry point. Tests will pass or fail at compile time. main :: IO () main = do adt1Test gadt1Test gadt2Test gadtrec1Test equalTest showableTest recordTest dataFamilyTest ghc78bugTest voidstosTest adt1Test :: IO () adt1Test = $(do info <- reifyDatatype ''Adt1 let [a,b] = map (VarT . mkName) ["a","b"] validate info DatatypeInfo { datatypeName = ''Adt1 , datatypeContext = [] , datatypeVars = [a, b] , datatypeVariant = Datatype , datatypeCons = [ ConstructorInfo { constructorName = 'Adtc1 , constructorContext = [] , constructorVars = [] , constructorFields = [AppT (AppT (TupleT 2) a) b] , constructorVariant = NormalConstructor } , ConstructorInfo { constructorName = 'Adtc2 , constructorContext = [] , constructorVars = [] , constructorFields = [ConT ''Bool, ConT ''Int] , constructorVariant = NormalConstructor } ] } ) gadt1Test :: IO () gadt1Test = $(do info <- reifyDatatype ''Gadt1 let a = VarT (mkName "a") validate info DatatypeInfo { datatypeName = ''Gadt1 , datatypeContext = [] , datatypeVars = [a] , datatypeVariant = Datatype , datatypeCons = [ ConstructorInfo { constructorName = 'Gadtc1 , constructorVars = [] , constructorContext = [equalPred a (ConT ''Int)] , constructorFields = [ConT ''Int] , constructorVariant = NormalConstructor } , ConstructorInfo { constructorName = 'Gadtc2 , constructorVars = [] , constructorContext = [] , constructorFields = [AppT (AppT (TupleT 2) a) a] , constructorVariant = NormalConstructor } ] } ) gadtrec1Test :: IO () gadtrec1Test = $(do info <- reifyDatatype ''Gadtrec1 let a = VarT (mkName "a") let [v1,v2] = map mkName ["v1","v2"] let con = ConstructorInfo { constructorName = 'Gadtrecc1 , constructorVars = [PlainTV v1, PlainTV v2] , constructorContext = [equalPred a (AppT (AppT (TupleT 2) (VarT v1)) (VarT v2))] , constructorFields = [VarT v1, VarT v2] , constructorVariant = RecordConstructor ['gadtrec1a, 'gadtrec1b] } validate info DatatypeInfo { datatypeName = ''Gadtrec1 , datatypeContext = [] , datatypeVars = [a] , datatypeVariant = Datatype , datatypeCons = [ con, con { constructorName = 'Gadtrecc2 } ] } ) equalTest :: IO () equalTest = $(do info <- reifyDatatype ''Equal let [a,b,c] = map (VarT . mkName) ["a","b","c"] validate info DatatypeInfo { datatypeName = ''Equal , datatypeContext = [] , datatypeVars = [a, b, c] , datatypeVariant = Datatype , datatypeCons = [ ConstructorInfo { constructorName = 'Equalc , constructorVars = [] , constructorContext = [equalPred a c, equalPred b c, classPred ''Read [c], classPred ''Show [c] ] , constructorFields = [ListT `AppT` c, ConT ''Maybe `AppT` c] , constructorVariant = NormalConstructor } ] } ) showableTest :: IO () showableTest = $(do info <- reifyDatatype ''Showable let a = mkName "a" validate info DatatypeInfo { datatypeName = ''Showable , datatypeContext = [] , datatypeVars = [] , datatypeVariant = Datatype , datatypeCons = [ ConstructorInfo { constructorName = 'Showable , constructorVars = [PlainTV a] , constructorContext = [classPred ''Show [VarT a]] , constructorFields = [VarT a] , constructorVariant = NormalConstructor } ] } ) recordTest :: IO () recordTest = $(do info <- reifyDatatype ''R validate info DatatypeInfo { datatypeName = ''R , datatypeContext = [] , datatypeVars = [] , datatypeVariant = Datatype , datatypeCons = [ ConstructorInfo { constructorName = 'R1 , constructorVars = [] , constructorContext = [] , constructorFields = [ConT ''Int, ConT ''Int] , constructorVariant = RecordConstructor ['field1, 'field2] } ] } ) gadt2Test :: IO () gadt2Test = $(do info <- reifyDatatype ''Gadt2 let [a,b] = map (VarT . mkName) ["a","b"] x = mkName "x" con = ConstructorInfo { constructorName = undefined , constructorVars = [] , constructorContext = [] , constructorFields = [] , constructorVariant = NormalConstructor } validate info DatatypeInfo { datatypeName = ''Gadt2 , datatypeContext = [] , datatypeVars = [a, b] , datatypeVariant = Datatype , datatypeCons = [ con { constructorName = 'Gadt2c1 , constructorContext = [equalPred b (AppT ListT a)] } , con { constructorName = 'Gadt2c2 , constructorContext = [equalPred a (AppT ListT b)] } , con { constructorName = 'Gadt2c3 , constructorVars = [PlainTV x] , constructorContext = [equalPred a (AppT ListT (VarT x)) ,equalPred b (AppT ListT (VarT x))] } ] } ) dataFamilyTest :: IO () dataFamilyTest = $(do info <- reifyDatatype 'DFMaybe let a = mkName "a" validate info DatatypeInfo { datatypeName = ''DF , datatypeContext = [] , datatypeVars = [AppT (ConT ''Maybe) (VarT a)] , datatypeVariant = DataInstance , datatypeCons = [ ConstructorInfo { constructorName = 'DFMaybe , constructorVars = [] , constructorContext = [] , constructorFields = [ConT ''Int, ListT `AppT` VarT a] , constructorVariant = NormalConstructor } ] } ) ghc78bugTest :: IO () ghc78bugTest = $(do info <- reifyDatatype 'DF1 let c = mkName "c" validate info DatatypeInfo { datatypeName = ''DF1 , datatypeContext = [] , datatypeVars = [VarT c] , datatypeVariant = DataInstance , datatypeCons = [ ConstructorInfo { constructorName = 'DF1 , constructorVars = [] , constructorContext = [] , constructorFields = [VarT c] , constructorVariant = NormalConstructor } ] } ) voidstosTest :: IO () voidstosTest = $(do info <- reifyDatatype ''VoidStoS let g = mkName "g" validate info DatatypeInfo { datatypeName = ''VoidStoS , datatypeContext = [] , datatypeVars = [VarT g] , datatypeVariant = Datatype , datatypeCons = [] } )