{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE UndecidableInstances #-}
module Language.Symantic.Typing.Kind where
import Data.Type.Equality (TestEquality(..), (:~:)(..))
import qualified Data.Kind as K
import Language.Symantic.Grammar
data Kind src k where
KiType :: src -> Kind src K.Type
KiConstraint :: src -> Kind src K.Constraint
KiFun :: src -> Kind src ka -> Kind src kb -> Kind src (ka -> kb)
infixr 5 `KiFun`
type instance SourceOf (Kind src k) = src
instance Source src => Sourceable (Kind src k) where
sourceOf (KiType src) = src
sourceOf (KiConstraint src) = src
sourceOf (KiFun src _a _b) = src
setSource (KiType _loc) src = KiType src
setSource (KiConstraint _loc) src = KiConstraint src
setSource (KiFun _loc a b) src = KiFun src a b
instance Show (Kind src k) where
show KiType{} = "*"
show KiConstraint{} = "Constraint"
show (KiFun _src a b) = "(" ++ show a ++ " -> " ++ show b ++ ")"
instance TestEquality (Kind src) where
testEquality = eqKind
eqKind :: Kind xs x -> Kind ys y -> Maybe (x:~:y)
eqKind KiType{} KiType{} = Just Refl
eqKind KiConstraint{} KiConstraint{} = Just Refl
eqKind (KiFun _xs xa xb) (KiFun _ys ya yb)
| Just Refl <- eqKind xa ya
, Just Refl <- eqKind xb yb
= Just Refl
eqKind _ _ = Nothing
type K (t::kt) = kt
class KindOf (a::kt -> K.Type) where
kindOf :: a t -> Kind (SourceOf (a t)) kt
class (KindInjP (Ty_of_Type k), Type_of_Ty (Ty_of_Type k) ~ k) => KindInj k where
instance (KindInjP (Ty_of_Type k), Type_of_Ty (Ty_of_Type k) ~ k) => KindInj k
kindInj ::
forall k src.
Source src =>
KindInj k =>
Kind src k
kindInj = kindInjP @(Ty_of_Type k) (noSource @src)
class KindInjP k where
kindInjP :: src -> Kind src (Type_of_Ty k)
instance KindInjP K.Constraint where
kindInjP = KiConstraint
instance KindInjP Ty where
kindInjP = KiType
instance (KindInjP a, KindInjP b) => KindInjP (a -> b) where
kindInjP src = KiFun src (kindInjP @a src) (kindInjP @b src)
data Ty
type family Ty_of_Type (t::K.Type) :: K.Type
type instance Ty_of_Type K.Type = Ty
type instance Ty_of_Type K.Constraint = K.Constraint
type instance Ty_of_Type (a -> b) = Ty_of_Type a -> Ty_of_Type b
type family Type_of_Ty (t::K.Type) :: K.Type
type instance Type_of_Ty Ty = K.Type
type instance Type_of_Ty K.Constraint = K.Constraint
type instance Type_of_Ty (a -> b) = Type_of_Ty a -> Type_of_Ty b
data KindK src = forall k. KindK (Kind src k)
instance Eq (KindK src) where
KindK x == KindK y
| Just _ <- eqKind x y = True
_x == _y = False
instance Show (KindK src) where
show (KindK x) = show x
data Con_Kind src
= Con_Kind_Eq (KindK src) (KindK src)
| Con_Kind_Arrow (KindK src)
deriving (Eq, Show)
when_EqKind
:: ErrorInj (Con_Kind src) err
=> Kind src x
-> Kind src y
-> ((x :~: y) -> Either err ret) -> Either err ret
when_EqKind x y k =
case x `eqKind` y of
Just Refl -> k Refl
Nothing -> Left $ errorInj $ Con_Kind_Eq (KindK x) (KindK y)
when_KiFun ::
ErrorInj (Con_Kind src) err =>
SourceInj (KindK src) src =>
Kind src x ->
(forall a b. (x :~: (a -> b)) ->
Kind src a ->
Kind src b ->
Either err ret) ->
Either err ret
when_KiFun x k =
case x of
KiFun _src a b -> k Refl (a `withSource` KindK x) (b `withSource` KindK x)
_ -> Left $ errorInj $ Con_Kind_Arrow (KindK x)