type-functions-0.2.0.0: src/Data/TypeFun.hs
-- | Emulation of type-level functions.
module Data.TypeFun (
-- * Type-level functions in general
TypeFun (type Domain),
App,
-- * Construction of type-level functions
Id (Id),
Const (Const),
(:->) ((:->)),
FunMap,
-- * Utilities
WrappedApp (WrapApp),
unwrapApp,
Universal
) where
import Data.Kind as Kind
{-NOTE:
At the value level, type-level function representations contain other /representations/ but
nothing else.
-}
-- * Type-level functions in general
{-|
Type-level functions are represented by types. @TypeFun@ is the class of all type-level
function representations.
-}
class (Kind (Domain fun)) => TypeFun fun where
{-|
The domain of the type-level function as a subkind representation. Subkind handling is
provided by the /kinds/ package.
-}
type Domain fun
{-|
Application of type-level functions. @App@ takes a function representation and an argument
and returns the corresponding result.
-}
type family App fun arg
-- * Construction of type-level functions
infixr 1 :->
{-|
A type @Id /d/@ represents the type-level identity function whose domain is represented
by @/d/@.
-}
data Id dom = Id dom
instance (Kind dom) => TypeFun (Id dom) where
type Domain (Id dom) = dom
type instance App (Id dom) arg = arg
{-|
A type @Const /d/ /v/@ represents the constant type-level function whose domain is
represented by @/d/@, and whose result is @/v/@.
-}
data Const dom val = Const dom
instance (Kind dom) => TypeFun (Const dom val) where
type Domain (Const dom val) = dom
type instance App (Const dom val) arg = val
{-|
A type @/f/ :-> /f'/@ represents the type-level function @\\arg -> ('App' /f/ arg -> 'App'
/f'/ arg)@.
-}
data fun :-> fun' = fun :-> fun'
instance (TypeFun fun, TypeFun fun', Domain fun ~ Domain fun') => TypeFun (fun :-> fun') where
type Domain (fun :-> fun') = Domain fun
type instance App (fun :-> fun') arg = App fun arg -> App fun' arg
{-|
If @/t/@ is a type of kind @* -> *@, and @/f/@ is the representation of a
type-level function, @FunMap /t/ /f/@ represents the function @\\arg -> /t/ (App /f/ arg)@.
-}
data FunMap (trans :: * -> *) fun = FunMap fun
instance (TypeFun fun) => TypeFun (FunMap trans fun) where
type Domain (FunMap trans fun) = Domain fun
type instance App (FunMap trans fun) arg = trans (App fun arg)
-- * Utilities
-- |A data type that is isomorphic to the type synonym family 'App'.
newtype WrappedApp fun arg = WrapApp (App fun arg)
-- |The inverse of 'WrapApp'.
unwrapApp :: WrappedApp fun arg -> App fun arg
unwrapApp (WrapApp val) = val
-- |Turns a type-level function into the intersection of all its results.
type Universal fun = forall arg. (Inhabitant (Domain fun) arg) => WrappedApp fun arg