{-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} module Gelatin.Shaders.TypeLevel ( -- * Type level combinators (:&)(..) -- * Generating symbol values on type lists , GetLits(..) -- * Generating function class , HasGenFunc(..) -- * Mapping types , TypeMap ) where import Data.Proxy (Proxy (..)) import GHC.TypeLits (KnownNat, KnownSymbol, natVal, symbolVal) -------------------------------------------------------------------------------- -- Type level combinators -------------------------------------------------------------------------------- -- | A heterogenious list. data a :& b = a :& b infixr 8 :& class GetLits a t where getSymbols :: Proxy a -> t instance GetLits '[] [t] where getSymbols _ = [] instance (GetLits a t, GetLits as [t]) => GetLits (a ': as) [t] where getSymbols _ = getSymbols (Proxy :: Proxy a) : getSymbols (Proxy :: Proxy as) instance KnownSymbol a => GetLits a String where getSymbols = symbolVal instance KnownNat a => GetLits a Integer where getSymbols = natVal -------------------------------------------------------------------------------- -- Generating a function from a type -------------------------------------------------------------------------------- class HasGenFunc a where type GenFunc a :: * genFunction :: Proxy a -> GenFunc a instance (HasGenFunc a, HasGenFunc b) => HasGenFunc (a :& b) where type GenFunc (a :& b) = GenFunc a :& GenFunc b genFunction _ = let a = (Proxy :: Proxy a) b = (Proxy :: Proxy b) in genFunction a :& genFunction b instance HasGenFunc '[] where type GenFunc '[] = () genFunction _ = () instance (HasGenFunc a, HasGenFunc as) => HasGenFunc (a ': as) where type GenFunc (a ': as) = GenFunc a :& GenFunc as genFunction _ = let a = (Proxy :: Proxy a) as = (Proxy :: Proxy as) in genFunction a :& genFunction as type family TypeMap (a :: * -> *) (xs :: [*]) :: [*] type instance TypeMap t '[] = '[] type instance TypeMap t (x ': xs) = t x ': TypeMap t xs