{-# LANGUAGE DataKinds, GADTs, PolyKinds, TypeFamilies, ExplicitForAll,
             TemplateHaskell, UndecidableInstances, ScopedTypeVariables,
             TypeInType #-}

module KindEqualities2 where

import Data.Kind
import GHC.Exts ( Any )

data Kind = Star | Arr Kind Kind

data Ty :: Kind -> * where
  TInt :: Ty Star
  TBool :: Ty Star
  TMaybe :: Ty (Arr Star Star)
  TApp :: Ty (Arr k1 k2) -> Ty k1 -> Ty k2


data TyRep (k :: Kind) (t :: Ty k) where
  TyInt :: TyRep Star TInt
  TyBool :: TyRep Star TBool
  TyMaybe :: TyRep (Arr Star Star) TMaybe
  TyApp :: TyRep (Arr k1 k2) a -> TyRep k1 b -> TyRep k2 (TApp a b)

type family IK (k :: Kind)
type instance IK Star = *
type instance IK (Arr k1 k2) = IK k1 -> IK k2

$(return [])  -- necessary because the following instances depend on the
              -- previous ones.

type family I (t :: Ty k) :: IK k
type instance I TInt = Int
type instance I TBool = Bool
type instance I TMaybe = Maybe
type instance I (TApp a b) = (I a) (I b)

zero :: forall (a :: Ty 'Star). TyRep Star a -> I a
zero TyInt = 0
zero TyBool = False
zero (TyApp TyMaybe TyInt) = Nothing

main = print $ zero (TyApp TyMaybe TyInt)
