module Language.Symantic.Typing.Type
( module Language.Symantic.Typing.Type
, Proxy(..)
, (:~:)(..)
, (:~~:)(..)
, K.Constraint
) where
import Control.Applicative (Alternative(..))
import Data.Maybe (isJust)
import Data.Proxy
import Data.Semigroup ((<>))
import Data.Set (Set)
import Data.Type.Equality
import Data.Typeable
import qualified Data.Kind as K
import qualified Data.Set as Set
import Language.Symantic.Grammar
import Language.Symantic.Typing.List
import Language.Symantic.Typing.Kind
import Language.Symantic.Typing.Variable
import Language.Symantic.Typing.Module
data Type (src::K.Type) (vs::[K.Type]) (t::kt) where
TyConst :: src -> Len vs
-> Const src c
-> Type src vs c
TyApp :: src -> Type src vs f
-> Type src vs a
-> Type src vs (f a)
TyVar :: src -> NameVar
-> Var src vs v
-> Type src vs v
TyFam :: src -> Len vs
-> Const src fam
-> Types src vs hs
-> Type src vs (Fam fam hs)
instance Source src => Eq (Type src vs t) where
x == y = isJust $ eqType x y
instance SourceInj (TypeVT src) src => TestEquality (Type src vs) where
testEquality = eqType
type instance SourceOf (Type src vs t) = src
instance Source src => Sourced (Type src vs t) where
sourceOf (TyConst src _l _c) = src
sourceOf (TyApp src _f _a) = src
sourceOf (TyVar src _n _v) = src
sourceOf (TyFam src _l _f _as) = src
setSource (TyConst _src l c) src = TyConst src l c
setSource (TyApp _src f a) src = TyApp src f a
setSource (TyVar _src n v) src = TyVar src n v
setSource (TyFam _src l f as) src = TyFam src l f as
instance SourceInj (TypeVT src) src => KindOf (Type src vs) where
kindOf t = kindOfType t `withSource` TypeVT t
instance ConstsOf (Type src vs t) where
constsOf (TyConst _src _len c) = Set.singleton $ ConstC c
constsOf TyVar{} = Set.empty
constsOf (TyApp _src f a) = constsOf f `Set.union` constsOf a
constsOf (TyFam _src _len fam as) = constsOf fam `Set.union` constsOf as
type instance VarsOf (Type src vs t) = vs
instance LenVars (Type src vs t) where
lenVars (TyConst _src len _c) = len
lenVars (TyApp _src f _a) = lenVars f
lenVars (TyVar _src _n v) = lenVars v
lenVars (TyFam _src l _f _as) = l
instance UsedVarsOf (Type src vs t) where
usedVarsOf vs TyConst{} k = k vs
usedVarsOf vs (TyFam _src _len _fam as) k = usedVarsOf vs as k
usedVarsOf vs (TyApp _src f a) k =
usedVarsOf vs f $ \vs' ->
usedVarsOf vs' a k
usedVarsOf vs (TyVar _src _n v) k =
case insertUsedVars v vs of
Nothing -> k vs
Just vs' -> k vs'
instance VarOccursIn (Type src vs t) where
varOccursIn v (TyVar _src _n v') | Just{} <- v `eqVarKi` v' = False
varOccursIn _v TyVar{} = False
varOccursIn _v TyConst{} = False
varOccursIn v (TyApp _src f a) = varOccursIn v f || varOccursIn v a
varOccursIn v (TyFam _src _len _fam as) = varOccursIn v as
instance AllocVars (Type src) where
allocVarsL len (TyConst src l c) = TyConst src (addLen len l) c
allocVarsL len (TyApp src f a) = TyApp src (allocVarsL len f) (allocVarsL len a)
allocVarsL len (TyVar src n v) = TyVar src n $ allocVarsL len v
allocVarsL len (TyFam src l f as) = TyFam src (addLen len l) f $ allocVarsL len `mapTys` as
allocVarsR len (TyConst src l c) = TyConst src (addLen l len) c
allocVarsR len (TyApp src f a) = TyApp src (allocVarsR len f) (allocVarsR len a)
allocVarsR len (TyVar src n v) = TyVar src n $ allocVarsR len v
allocVarsR len (TyFam src l f as) = TyFam src (addLen l len) f $ allocVarsR len `mapTys` as
tyConst ::
forall kc (c::kc) src vs.
Source src =>
LenInj vs =>
Constable c =>
KindInjP (Ty_of_Type kc) =>
Type_of_Ty (Ty_of_Type kc) ~ kc =>
Type src vs c
tyConst = TyConst noSource lenInj constInj
tyConstLen ::
forall kc (c::kc) src vs.
Source src =>
Constable c =>
KindInjP (Ty_of_Type kc) =>
Type_of_Ty (Ty_of_Type kc) ~ kc =>
Len vs ->
Type src vs c
tyConstLen len = TyConst noSource len constInj
tyApp ::
Source src =>
Type src vs f ->
Type src vs a ->
Type src vs (f a)
tyApp = TyApp noSource
infixl 9 `tyApp`
tyVar ::
Source src =>
NameVar ->
Var src vs v ->
Type src vs v
tyVar = TyVar noSource
tyFam ::
forall kc (c::kc) as vs src.
Source src =>
LenInj vs =>
Constable c =>
KindInjP (Ty_of_Type kc) =>
Type_of_Ty (Ty_of_Type kc) ~ kc =>
Types src vs as ->
Type src vs (Fam c as)
tyFam = TyFam noSource lenInj (constInj @c)
tyQual ::
Source src =>
Type src vs q ->
Type src vs t ->
(Qual q ->
Type src vs t ->
Type src vs (q #> t)) ->
Type src vs (q #> t)
tyQual q t f =
case proveConstraint q of
Just Dict -> f Dict t
Nothing -> q #> t
infix 1 `tyQual`
data TypeK src vs kt = forall (t::kt). TypeK (Type src vs t)
type instance SourceOf (TypeK src vs ki) = src
type instance VarsOf (TypeK src vs ki) = vs
instance Source src => Eq (TypeK src vs ki) where
TypeK x == TypeK y = isJust $ eqType x y
data TypeT src vs = forall t. TypeT (Type src vs t)
type instance SourceOf (TypeT src vs) = src
type instance VarsOf (TypeT src vs) = vs
instance Source src => Eq (TypeT src vs) where
TypeT x == TypeT y = isJust $ eqTypeKi x y
data TypeVT src = forall vs t. TypeVT (Type src vs t)
type instance SourceOf (TypeVT src) = src
instance Source src => Eq (TypeVT src) where
TypeVT x == TypeVT y =
let (x', y') = appendVars x y in
isJust $ eqTypeKi x' y'
data Const src (c::kc) where
Const :: Constable c => Kind src kc -> Const src (c::kc)
type instance SourceOf (Const src c) = src
instance ConstsOf (Const src c) where
constsOf = Set.singleton . ConstC
instance SourceInj (ConstC src) src => KindOf (Const src) where
kindOf c@(Const kc) = kc `withSource` ConstC c
kindOfConst :: Const src (t::kt) -> Kind src kt
kindOfConst (Const kc) = kc
class
( Typeable c
, FixityOf c
, NameTyOf c
, ClassInstancesFor c
, TypeInstancesFor c
) => Constable c
instance
( Typeable c
, FixityOf c
, NameTyOf c
, ClassInstancesFor c
, TypeInstancesFor c
) => Constable c
class ConstsOf a where
constsOf :: a -> Set (ConstC (SourceOf a))
data ConstC src
= forall c. ConstC (Const src c)
instance Eq (ConstC src) where
ConstC x == ConstC y = isJust $ x `eqConstKi` y
instance Ord (ConstC src) where
ConstC x `compare` ConstC y = x `ordConst` y
(~>) ::
Source src =>
Constable (->) =>
Type src vs a ->
Type src vs b ->
Type src vs (a -> b)
(~>) a b = (tyConstLen @(K (->)) @(->) (lenVars a) `tyApp` a) `tyApp` b
infixr 0 ~>
instance FixityOf (->) where
fixityOf _c = Just $ Fixity2 $ infixR 0
type family FunArg (fun::K.Type) :: K.Type where
FunArg (q #> f) = FunArg f
FunArg (a -> b) = a
type family FunRes (fun::K.Type) :: K.Type where
FunRes (q #> f) = FunRes f
FunRes (a -> b) = b
unTyFun ::
forall t src tys.
SourceInj (TypeVT src) src =>
Constable (->) =>
Type src tys t ->
Maybe ( Type src tys (FunArg t)
, Type src tys (FunRes t) )
unTyFun ty_ini = go ty_ini
where
go ::
Type src tys x ->
Maybe ( Type src tys (FunArg x)
, Type src tys (FunRes x) )
go (TyApp _ (TyApp _ (TyConst _ _ f) a) b)
| Just HRefl <- proj_ConstKi @(K (->)) @(->) f
= Just ((a `withSource` TypeVT ty_ini), (b `withSource` TypeVT ty_ini))
go (TyApp _ (TyApp _ (TyConst _ _ f) _a) b)
| Just HRefl <- proj_ConstKi @(K (#>)) @(#>) f
= go b
go TyApp{} = Nothing
go TyConst{} = Nothing
go TyVar{} = Nothing
go TyFam{} = Nothing
newtype (#>) (q::K.Constraint) (a::K.Type) = Qual (q => a)
instance NameTyOf (#>) where
nameTyOf _c = [] `Mod` "=>"
instance FixityOf (#>) where
fixityOf _c = Just $ Fixity2 $ infixR 0
instance ClassInstancesFor (#>)
instance TypeInstancesFor (#>)
(#>) ::
Source src =>
Type src vs q ->
Type src vs t ->
Type src vs (q #> t)
(#>) q t = (tyConstLen @(K (#>)) @(#>) (lenVars q) `tyApp` q) `tyApp` t
infixr 0 #>
class (x, y) => x # y
instance (x, y) => x # y
instance NameTyOf (#) where
nameTyOf _c = [] `Mod` ","
instance FixityOf (#) where
fixityOf _c = Just $ Fixity2 $ infixB SideL 0
instance ClassInstancesFor (#) where
proveConstraintFor _c (TyApp _ (TyApp _ c q0) q1)
| Just HRefl <- proj_ConstKiTy @(K (#)) @(#) c
, Just Dict <- proveConstraint q0
, Just Dict <- proveConstraint q1
= Just Dict
proveConstraintFor _c _q = Nothing
instance TypeInstancesFor (#)
(#) ::
Source src =>
Type src vs qx ->
Type src vs qy ->
Type src vs (qx # qy)
(#) a b = (tyConstLen @(K (#)) @(#) (lenVars a) `tyApp` a) `tyApp` b
infixr 2 #
instance NameTyOf (()::K.Constraint) where
nameTyOf _c = [] `Mod` "()"
instance ClassInstancesFor (()::K.Constraint) where
proveConstraintFor _c q
| Just HRefl <- proj_ConstKiTy @K.Constraint @(()::K.Constraint) q
= Just Dict
proveConstraintFor _c _q = Nothing
instance TypeInstancesFor (()::K.Constraint)
noConstraint :: Source src => LenInj vs => Type src vs (()::K.Constraint)
noConstraint = tyConstLen @K.Constraint @(()::K.Constraint) lenInj
noConstraintLen :: Source src => Len vs -> Type src vs (()::K.Constraint)
noConstraintLen = tyConstLen @K.Constraint @(()::K.Constraint)
class (x ~ y) => x #~ y
instance (x ~ y) => x #~ y
instance NameTyOf (#~) where
nameTyOf _c = [] `Mod` "~"
isNameTyOp _c = True
instance FixityOf (#~) where
fixityOf _ = Just $ Fixity2 $ infixB SideL 0
instance
( KindInj k
, Typeable k
) => ClassInstancesFor ((#~)::k -> k -> K.Constraint) where
proveConstraintFor _c (TyApp _ (TyApp _ c a) b)
| Just HRefl <- proj_ConstKiTy @(k -> k -> K.Constraint) @(#~) c
, Just Refl <- eqType a b
= Just Dict
proveConstraintFor _c _q = Nothing
instance TypeInstancesFor (#~)
(#~) ::
forall k a b src vs.
Source src =>
Typeable k =>
KindInj k =>
Type src vs (a :: k) ->
Type src vs (b :: k) ->
Type src vs (a #~ b)
(#~) a b = (tyConstLen @(K (#~)) @(#~) (lenVars a) `tyApp` a) `tyApp` b
infixr 2 #~
eqType ::
Source src =>
Type src tys (x::k) ->
Type src tys (y::k) ->
Maybe (x:~:y)
eqType x y | Just HRefl <- eqTypeKi x y = Just Refl
eqType _x _y = Nothing
eqTypeKi ::
Source src =>
Type src tys (x::kx) ->
Type src tys (y::ky) ->
Maybe (x:~~:y)
eqTypeKi (TyConst _sx _lx x) (TyConst _sy _ly y) = eqConstKi x y
eqTypeKi (TyVar _sx _nx x) (TyVar _sy _ny y) = eqVarKi x y
eqTypeKi (TyApp _sx fx ax) (TyApp _sy fy ay)
| Just HRefl <- eqTypeKi fx fy
, Just HRefl <- eqTypeKi ax ay
= Just HRefl
eqTypeKi (TyFam _ _lx fx ax) (TyFam _ _ly fy ay)
| Just HRefl <- eqConstKi fx fy
, Just HRefl <- eqTypes ax ay
= Just HRefl
eqTypeKi x@TyFam{} y = eqTypeKi (expandFam x) y
eqTypeKi x y@TyFam{} = eqTypeKi x (expandFam y)
eqTypeKi _x _y = Nothing
eqTypes ::
Source src =>
Types src tys x ->
Types src tys y ->
Maybe (x:~~:y)
eqTypes TypesZ TypesZ = Just HRefl
eqTypes (x `TypesS` sx) (y `TypesS` sy)
| Just HRefl <- eqTypeKi x y
, Just HRefl <- eqTypes sx sy
= Just HRefl
eqTypes _x _y = Nothing
ordType ::
Source src =>
Type src tys (x::kx) ->
Type src tys (y::ky) ->
Ordering
ordType (TyFam _ _lx fx ax) (TyFam _ _ly fy ay) = ordConst fx fy <> ordTypes ax ay
ordType x@TyFam{} y = ordType (expandFam x) y
ordType x y@TyFam{} = ordType x (expandFam y)
ordType (TyConst _sx _lx x) (TyConst _sy _ly y) = ordConst x y
ordType TyConst{} _y = LT
ordType _x TyConst{} = GT
ordType (TyVar _sx _kx x) (TyVar _sy _ky y) = ordVarKi x y
ordType TyVar{} _y = LT
ordType _x TyVar{} = GT
ordType (TyApp _sx fx xx) (TyApp _sy fy xy) = ordType fx fy <> ordType xx xy
ordTypes ::
Source src =>
Types src tys x ->
Types src tys y ->
Ordering
ordTypes TypesZ TypesZ = EQ
ordTypes TypesZ TypesS{} = LT
ordTypes TypesS{} TypesZ = GT
ordTypes (x `TypesS` sx) (y `TypesS` sy) = ordType x y <> ordTypes sx sy
data Qual q where
Dict :: q => Qual q
class ClassInstancesFor c where
proveConstraintFor
:: Source src
=> proxy c
-> Type src vs q
-> Maybe (Qual q)
proveConstraintFor _c _q = Nothing
proveConstraint :: Source src => Type src vs q -> Maybe (Qual q)
proveConstraint q = foldr proj Nothing $ constsOf q
where proj (ConstC c@Const{}) = (<|> proveConstraintFor c q)
constInj ::
forall c src.
Source src =>
Constable c =>
KindInjP (Ty_of_Type (K c)) =>
Type_of_Ty (Ty_of_Type (K c)) ~ K c =>
Const src c
constInj = Const $ kindInjP @(Ty_of_Type (K c)) noSource
constKiInj ::
forall kc c src.
Source src =>
Constable c =>
Kind src kc ->
Const src (c::kc)
constKiInj = Const
proj_Const ::
forall c u src.
Typeable c =>
Const src u ->
Maybe (c :~: u)
proj_Const Const{} = eqT
proj_ConstTy ::
forall c u src vs.
Typeable c =>
Type src vs u ->
Maybe (c :~: u)
proj_ConstTy (TyConst _src _len Const{}) = eqT
proj_ConstTy _ = Nothing
proj_ConstKi ::
forall kc (c::kc) u src.
Typeable c =>
(kc ~ Type_of_Ty (Ty_of_Type kc)) =>
KindInjP (Ty_of_Type kc) =>
Const src u ->
Maybe (c :~~: u)
proj_ConstKi (Const ku) = do
Refl <- eqKind ku $ kindInjP @(Ty_of_Type kc) ()
Refl :: u:~:c <- eqT
Just HRefl
proj_ConstKiTy ::
forall kc (c::kc) u src vs.
Typeable c =>
(kc ~ Type_of_Ty (Ty_of_Type kc)) =>
KindInjP (Ty_of_Type kc) =>
Type src vs u ->
Maybe (c :~~: u)
proj_ConstKiTy (TyConst _src _len c) = proj_ConstKi c
proj_ConstKiTy _ = Nothing
eqConst ::
Const src_x (x::k) ->
Const src_y (y::k) ->
Maybe (x:~:y)
eqConst (Const _kx) (Const _ky) = eqT
instance Eq (Const src c) where
x == y = isJust $ eqConstKi x y
instance Ord (Const src c) where
compare = ordConst
eqConstKi ::
forall src_x src_y kx ky x y.
Const src_x (x::kx) ->
Const src_y (y::ky) ->
Maybe (x:~~:y)
eqConstKi (Const kx) (Const ky)
| Just Refl <- eqKind kx ky
, Just (Refl::x:~:y) <- eqT
= Just HRefl
eqConstKi _x _y = Nothing
ordConst ::
forall src_x src_y kx ky x y.
Const src_x (x::kx) ->
Const src_y (y::ky) ->
Ordering
ordConst x@Const{} y@Const{} =
typeRep x `compare` typeRep y
normalizeQualsTy ::
Source src =>
Type src tys (t::kt) ->
TypeK src tys kt
normalizeQualsTy = go
where
go ::
Source src =>
Type src tys (a::ka) ->
TypeK src tys ka
go (TyApp s1 (TyApp s0 f q0) q1)
| Just HRefl <- proj_ConstKiTy @(K (#)) @(#) f
, TypeK q0' <- go q0
, TypeK q1' <- go q1 =
case (proveConstraint q0', proveConstraint q1') of
(Just{}, Just{}) -> TypeK $ tyConstLen @K.Constraint @(()::K.Constraint) $ lenVars q0
(Just{}, Nothing) -> TypeK q1'
(Nothing, Just{}) -> TypeK q0'
(Nothing, Nothing) ->
case q0' `ordType` q1' of
LT -> TypeK $ TyApp s1 (TyApp s0 f q0') q1'
EQ -> TypeK $ q0'
GT -> TypeK $ TyApp s0 (TyApp s1 f q1') q0'
go (TyApp s1 (TyApp s0 f0@(TyConst sf0 lf0 _) q0) (TyApp s2 (TyApp s3 f1 q1) t))
| Just HRefl <- proj_ConstKiTy @(K (#>)) @(#>) f0
, Just HRefl <- proj_ConstKiTy @(K (#>)) @(#>) f1
, TypeK q0' <- go q0
, TypeK q1' <- go q1 =
case (proveConstraint q0', proveConstraint q1') of
(Just{}, Just{}) -> TypeK t
(Just{}, Nothing) -> TypeK $ TyApp s2 (TyApp s3 f1 q1) t
(Nothing, Just{}) -> TypeK $ TyApp s1 (TyApp s0 f0 q0) t
(Nothing, Nothing) ->
case q0' `ordType` q1' of
LT ->
let q0q1 = TyApp s2 (TyApp s0 (TyConst sf0 lf0 $ constInj @(#)) q0') q1' in
TypeK $ TyApp s2 (TyApp s3 f1 q0q1) t
EQ -> TypeK $ TyApp s2 (TyApp s3 f1 q1') t
GT ->
let q1q0 = TyApp s0 (TyApp s2 (TyConst sf0 lf0 $ constInj @(#)) q1') q0' in
TypeK $ TyApp s2 (TyApp s3 f1 q1q0) t
go (TyApp _sa (TyApp _sq (TyConst _sc _lc c) q) t)
| Just HRefl <- proj_ConstKi @(K (#>)) @(#>) c =
case proveConstraint q of
Just{} -> go t
Nothing
| TypeK q' <- go q
, TypeK t' <- go t
-> TypeK $ q' #> t'
go q
| Just Refl <- KiConstraint () `eqKind` kindOfType q
= case proveConstraint q of
Just{} -> TypeK $ tyConstLen @K.Constraint @(()::K.Constraint) $ lenVars q
Nothing -> TypeK q
go (TyApp src f a)
| TypeK f' <- go f
, TypeK a' <- go a
= TypeK $ TyApp src f' a'
go t@TyFam{} = go (expandFam t)
go t@TyConst{} = TypeK t
go t@TyVar{} = TypeK t
type family Fam (fam::k) (hs::[K.Type]) :: k
class TypeInstancesFor (c::kc) where
expandFamFor
:: Source src
=> proxy c
-> Len vs
-> Const src fam
-> Types src vs ts
-> Maybe (Type src vs (Fam fam ts))
expandFamFor _c _len _fam _as = Nothing
class ExpandFam a where
expandFam :: Source (SourceOf a) => a -> a
instance ExpandFam (Type src vs t) where
expandFam t@TyConst{} = t
expandFam t@TyVar{} = t
expandFam (TyApp src f a) = TyApp src (expandFam f) (expandFam a)
expandFam t@(TyFam _src len fam as) =
case foldr proj Nothing $ constsOf fam `Set.union` constsOf as of
Nothing -> t
Just t' -> expandFam t'
where proj (ConstC c@Const{}) = (<|> expandFamFor c len fam as)
kindOfType :: Type src vs (t::kt) -> Kind src kt
kindOfType (TyConst _src _l c) = kindOfConst c
kindOfType (TyApp _src f _a) =
case kindOfType f of
KiFun _src_kf _kx kf -> kf
kindOfType (TyVar _src _n v) = kindOfVar v
kindOfType (TyFam _src _len fam _as) = kindOfConst fam
normalizeVarsTy ::
Type src vs (t::kt) ->
(forall vs'. Type src vs' (t::kt) -> ret) -> ret
normalizeVarsTy ty k =
usedVarsOf UsedVarsZ ty $ \vs ->
k $ goTy vs ty
where
goTy ::
UsedVars src vs vs' ->
Type src vs t ->
Type src vs' t
goTy vs (TyConst src _len c) = TyConst src (lenVars vs) c
goTy vs (TyApp src f a) = TyApp src (goTy vs f) (goTy vs a)
goTy vs (TyVar src n v) =
case v `lookupUsedVars` vs of
Nothing -> error "[BUG] normalizeVarsTy: impossible lookup fail"
Just v' -> TyVar src n v'
goTy vs (TyFam src _len fam as) = TyFam src (lenVars vs) fam $ goTys vs as
goTys ::
UsedVars src vs vs' ->
Types src vs ts ->
Types src vs' ts
goTys _vs TypesZ = TypesZ
goTys vs (TypesS t ts) =
goTy vs t `TypesS`
goTys vs ts
data Types src vs (ts::[K.Type]) where
TypesZ :: Types src vs '[]
TypesS :: Type src vs t
-> Types src vs ts
-> Types src vs (Proxy t ': ts)
infixr 5 `TypesS`
type instance SourceOf (Types src vs ts) = src
instance ConstsOf (Types src vs ts) where
constsOf TypesZ = Set.empty
constsOf (TypesS t ts) = constsOf t `Set.union` constsOf ts
type instance VarsOf (Types src vs ts) = vs
instance UsedVarsOf (Types src vs ts) where
usedVarsOf vs TypesZ k = k vs
usedVarsOf vs (TypesS t ts) k =
usedVarsOf vs t $ \vs' ->
usedVarsOf vs' ts k
instance VarOccursIn (Types src vs ts) where
varOccursIn _v TypesZ = False
varOccursIn v (TypesS t ts) = varOccursIn v t || varOccursIn v ts
mapTys ::
(forall kt (t::kt). Type src vs t -> Type src vs' t) ->
Types src vs ts ->
Types src vs' ts
mapTys _f TypesZ = TypesZ
mapTys f (TypesS t ts) = f t `TypesS` mapTys f ts
foldlTys ::
(forall k (t::k). Type src vs t -> acc -> acc) ->
Types src vs ts -> acc -> acc
foldlTys _f TypesZ acc = acc
foldlTys f (TypesS t ts) acc = foldlTys f ts (f t acc)
class TypeOf a where
typeOf :: a t -> Type (SourceOf (a t)) (VarsOf (a t)) t