-- test reification of data declarations

{-# LANGUAGE TypeFamilies, TypeApplications, PolyKinds #-}
module TH_reifyDecl1 where

import Data.Kind as K
import System.IO
import Language.Haskell.TH
import Text.PrettyPrint.HughesPJ

infixl 3 `m1`

-- simple
data T = A | B

-- parametric
data R a = C a | D

-- recursive
data List a = Nil | Cons a (List a)

-- infix operator
data Tree a = Leaf | Tree a :+: Tree a

-- type declaration
type IntList = [Int]

-- newtype declaration
newtype Length = Length Int

-- simple class
class C1 a where
  m1 :: a -> Int

-- class with instances
class C2 a where
  m2 :: a -> Int
instance C2 Int where
  m2 x = x

-- associated types
class C3 a where
  type AT1 a
  data AT2 a

instance C3 Int where
  type AT1 Int = Bool
  data AT2 Int = AT2Int

-- type family
type family TF1 a

-- type family, with instances
type family TF2 a
type instance TF2 Bool = Bool

-- data family
data family DF1 a

-- data family, with instances
data family DF2 a
data instance DF2 Bool = DBool

data family DF3 (a :: k)
data instance DF3 @K.Type a = DF3Bool
data instance DF3 @(K.Type -> K.Type) b = DF3Char

$(return [])

test :: ()
test = $(let
      display :: Name -> Q ()
      display q = do { i <- reify q; runIO $ hPutStrLn stderr (pprint i) }
    in do { display ''T
          ; display ''R
          ; display ''List
          ; display ''Tree
          ; display ''IntList
          ; display ''Length
          ; display 'Leaf
          ; display 'm1
          ; display ''C1
          ; display ''C2
          ; display ''C3
          ; display ''AT1
          ; display ''AT2
          ; display ''TF1
          ; display ''TF2
          ; display ''DF1
          ; display ''DF2
          ; display ''DF3
          ; [| () |] })
