Add make target %/fast.
[haskell/symantic.git] / symantic / Language / Symantic / Typing / Kind.hs
index 0ee74b17a3e20907a3585eca28159b98beb5de41..7f08c8c3f6abb308b029b3da791789a1225f0b7e 100644 (file)
+{-# LANGUAGE AllowAmbiguousTypes #-}
 {-# LANGUAGE GADTs #-}
 {-# LANGUAGE PolyKinds #-}
 {-# LANGUAGE UndecidableInstances #-}
 module Language.Symantic.Typing.Kind where
 
-import qualified Data.Kind as Kind
-import Data.Proxy
-import Data.Type.Equality
-import GHC.Exts (Constraint)
-import GHC.Prim (Any)
+import Data.Type.Equality (TestEquality(..), (:~:)(..))
+import qualified Data.Kind as K
 
--- * Type 'SKind'
+import Language.Symantic.Grammar
+
+-- * Type 'Kind'
 -- | Singleton for kind types.
-data SKind k where
-       SKiType       :: SKind Kind.Type
-       SKiConstraint :: SKind Constraint
-       SKiArrow      :: SKind ka -> SKind kb -> SKind (ka -> kb)
-infixr 5 `SKiArrow`
-
-instance Show (SKind k) where
-       show SKiType = "*"
-       show SKiConstraint  = "Constraint"
-       show (SKiArrow a b) = "(" ++ show a ++ " -> " ++ show b ++ ")"
-instance TestEquality SKind where
-       testEquality = eq_skind
-
-eq_skind :: SKind x -> SKind y -> Maybe (x:~:y)
-eq_skind SKiType SKiType = Just Refl
-eq_skind SKiConstraint SKiConstraint = Just Refl
-eq_skind (SKiArrow xa xb) (SKiArrow ya yb)
- | Just Refl <- eq_skind xa ya
- , Just Refl <- eq_skind xb yb
+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 => Sourced (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
-eq_skind _ _ = Nothing
+eqKind _ _ = Nothing
+
+-- * Type 'K'
+type K (t::kt) = kt
+
+-- * Class 'KindOf'
+-- | Return the 'Kind' of something.
+class KindOf (a::kt -> K.Type) where
+       kindOf :: a t -> Kind (SourceOf (a t)) kt
 
--- * Type 'IKind'
--- | Implicit 'SKind'.
+-- * Type 'Inj_Kind'
+-- | Implicit 'Kind'.
 --
 -- NOTE: GHC-8.0.1's bug <https://ghc.haskell.org/trac/ghc/ticket/12933 #12933>
--- makes it fail to properly build an implicit 'SKind',
+-- makes it fail to properly build an implicit 'Kind',
 -- this can however be worked around by having the class instances
--- work on a data type 'Ty' instead of 'Data.Kind.Type',
--- hence the introduction of 'Ty', 'Ty_of_Type', 'Type_of_Ty' and 'IKindP'.
-class (IKindP (Ty_of_Type k), Type_of_Ty (Ty_of_Type k) ~ k) => IKind k where
-       kind :: SKind k
-       kind = kindP (Proxy @(Ty_of_Type k))
-instance (IKindP (Ty_of_Type k), Type_of_Ty (Ty_of_Type k) ~ k) => IKind k
-
--- ** Type 'IKindP'
-class IKindP k where
-       kindP :: Proxy k -> SKind (Type_of_Ty k)
-instance IKindP Constraint where
-       kindP _ = SKiConstraint
-instance IKindP Ty where
-       kindP _ = SKiType
-instance (IKindP a, IKindP b) => IKindP (a -> b) where
-       kindP _ = kindP (Proxy @a) `SKiArrow` kindP (Proxy @b)
+-- work on a data type 'Ty' instead of 'Data.K.Type',
+-- hence the introduction of 'Ty', 'Ty_of_Type', 'Type_of_Ty' and 'Inj_KindP'.
+class (Inj_KindP (Ty_of_Type k), Type_of_Ty (Ty_of_Type k) ~ k) => Inj_Kind k where
+instance (Inj_KindP (Ty_of_Type k), Type_of_Ty (Ty_of_Type k) ~ k) => Inj_Kind k
+
+inj_Kind ::
+ forall k src.
+ Source src =>
+ Inj_Kind k =>
+ Kind src k
+inj_Kind = inj_KindP @(Ty_of_Type k) (noSource @src)
+
+-- ** Type 'Inj_KindP'
+class Inj_KindP k where
+       inj_KindP :: src -> Kind src (Type_of_Ty k)
+instance Inj_KindP K.Constraint where
+       inj_KindP = KiConstraint
+instance Inj_KindP Ty where
+       inj_KindP = KiType
+instance (Inj_KindP a, Inj_KindP b) => Inj_KindP (a -> b) where
+       inj_KindP src = KiFun src (inj_KindP @a src) (inj_KindP @b src)
 
 -- ** Type 'Ty'
--- | FIXME: to be removed when
+-- | FIXME: workaround to be removed when
 -- <https://ghc.haskell.org/trac/ghc/ticket/12933 #12933>
 -- will be fixed.
 data Ty
 
 -- ** Type family 'Ty_of_Type'
-type family   Ty_of_Type (typ::Kind.Type) :: Kind.Type
-type instance Ty_of_Type Kind.Type  = Ty
-type instance Ty_of_Type Constraint = Constraint
-type instance Ty_of_Type (a -> b)   = Ty_of_Type a -> Ty_of_Type b
+-- | NOTE: As of GHC-8.0.2, using a closed /type family/ does not work here,
+-- this notably disables the expansion of 'Ty_of_Type'@ Any@.
+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'
-type family   Type_of_Ty (typ::Kind.Type) :: Kind.Type
-type instance Type_of_Ty Ty         = Kind.Type
-type instance Type_of_Ty Constraint = Constraint
-type instance Type_of_Ty (a -> b)   = Type_of_Ty a -> Type_of_Ty b
+-- | NOTE: As of GHC-8.0.2, using a closed /type family/ does not work here,
+-- this notably disables the expansion of 'Type_of_Ty'@ Any@.
+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
 
--- * Type 'EKind'
+-- * Type 'KindK'
 -- | Existential for 'Kind'.
-data EKind = forall k. EKind (SKind k)
-instance Eq EKind where
-       EKind x == EKind y
-        | Just _ <- eq_skind x y = True
+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 EKind where
-       show (EKind x) = show x
-
--- * Type family 'Kind_Of'
-type family   Kind_Of (x::k) :: Kind.Type
-type instance Kind_Of (x::Constraint) = Constraint
-type instance Kind_Of (x::Kind.Type)  = Kind.Type
-type instance Kind_Of (x::a -> b)     = Kind_Of (Any::a) -> Kind_Of (Any::b)
-
-{-
-instance Show (x :~~: y) where
-       show _ = "HRefl"
-
-type family Eq_KindF (x::kx) (y::ky) :: Bool where
-       Eq_KindF (x::k) (y::k) = 'True
-       Eq_KindF x y = 'False
-
-type Eq_Kind x y = Eq_KindB (Eq_KindF x y) x y
-class Eq_KindB (b::Bool) (x::kx) (y::ky) where
-       eq_kindB :: Proxy b -> Proxy x -> Proxy y -> Maybe (x:~~:y)
-instance Eq_KindB 'False x y where
-       eq_kindB _b _x _y = Nothing
-instance Eq_KindB 'True (x::Kind.Type) (y::Kind.Type) where
-       eq_kindB _b _x _y = Just HRefl
-instance Eq_KindB 'True (x::Constraint) (y::Constraint) where
-       eq_kindB _b _x _y = Just HRefl
-instance
- ( Eq_Kind (Any::k0) (Any::k2)
- , Eq_Kind (Any::k1) (Any::k3)
- ) => Eq_KindB 'True (x::k0 -> k1) (y::k2 -> k3) where
-       eq_kindB _b _x _y
-        | Just HRefl <- eq_kind (Proxy @(Any::k0)) (Proxy @(Any::k2))
-        , Just HRefl <- eq_kind (Proxy @(Any::k1)) (Proxy @(Any::k3))
-        = Just HRefl
-       eq_kindB _b _x _y = Nothing
-
-eq_kind :: forall x y. Eq_Kind x y => Proxy x -> Proxy y -> Maybe (x:~~:y)
-eq_kind = eq_kindB (Proxy @(Eq_KindF x y))
--}
+instance Show (KindK src) where
+       show (KindK x) = show x
+
+-- * Type 'Con_Kind'
+data Con_Kind src
+ =   Con_Kind_Eq    (KindK src) (KindK src)
+ |   Con_Kind_Arrow (KindK src)
+ deriving (Eq, Show)
+
+when_EqKind
+ :: Inj_Error (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 $ inj_Error $ Con_Kind_Eq (KindK x) (KindK y)
+
+when_KiFun ::
+ Inj_Error (Con_Kind src) err =>
+ Inj_Source (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 `source` KindK x) (b `source` KindK x)
+        _ -> Left $ inj_Error $ Con_Kind_Arrow (KindK x)