packages feed

witness-0.5: src/Data/Witness/Kind.hs

module Data.Witness.Kind where

import Data.Constraint
import Data.Kind
import Data.Witness.Constraint
import Data.Witness.Representative
import GHC.TypeLits
import Prelude

type family KindWitness k :: k -> Type

type InKind (a :: k) = Is (KindWitness k) a

inKind ::
       forall k (a :: k). InKind a
    => KindWitness k a
inKind = representative

-- NoWitness
data NoWitness (t :: k) =
    MkNoWitness

instance Representative NoWitness where
    getRepWitness MkNoWitness = Dict

instance Is NoWitness a where
    representative = MkNoWitness

-- Type
type instance KindWitness Type = NoWitness

-- Constraint
type instance KindWitness Constraint = NoWitness

-- Nat
type instance KindWitness Nat = NoWitness

-- kp -> kq
data FunctionKindWitness (wp :: kp -> Type) (wq :: kq -> Type) (t :: kp -> kq) where
    MkFunctionKindWitness
        :: forall kp kq (wp :: kp -> Type) (wq :: kq -> Type) (t :: kp -> kq).
           (forall (p :: kp). Is wp p => Is wq (t p))
        => FunctionKindWitness wp wq t

applyFunctionKindWitness ::
       forall kp kq (wp :: kp -> Type) (wq :: kq -> Type) (t :: kp -> kq) (p :: kp) (proxy :: kp -> Type). Is wp p
    => FunctionKindWitness wp wq t
    -> proxy p
    -> Dict (Is wq (t p))
applyFunctionKindWitness MkFunctionKindWitness _ = Dict

type instance KindWitness (kp -> kq) =
     FunctionKindWitness (KindWitness kp) (KindWitness kq)

instance forall kp kq (wp :: kp -> Type) (wq :: kq -> Type). Representative (FunctionKindWitness wp wq) {- Representative wq => -}
                                                                                                                                   where
    getRepWitness MkFunctionKindWitness = Dict

instance (forall p. Is wp p => Is wq (f p)) =>
             Is (FunctionKindWitness (wp :: kp -> Type) (wq :: kq -> Type)) (f :: kp -> kq) where
    representative = MkFunctionKindWitness

-- (kp,kq)
data PairWitness (wp :: kp -> Type) (wq :: kq -> Type) (t :: (kp, kq)) where
    MkPairWitness :: (Is wp p, Is wq q) => PairWitness wp wq '( p, q)

instance (Representative wp, Representative wq) => Representative (PairWitness wp wq) where
    getRepWitness MkPairWitness = Dict

instance (Is wp p, Is wq q) => Is (PairWitness wp wq) '( p, q) where
    representative = MkPairWitness

type instance KindWitness (kp, kq) =
     PairWitness (KindWitness kp) (KindWitness kq)

data AnyInKind (wit :: k -> Type) =
    forall (t :: k). InKind t => MkAnyInKind (wit t)

instance AllWitnessConstraint Show w => Show (AnyInKind w) where
    show (MkAnyInKind wa) = showAllWitness wa