1 {-# LANGUAGE DataKinds #-}
2 {-# LANGUAGE FlexibleContexts #-}
3 {-# LANGUAGE PolyKinds #-}
5 {-# LANGUAGE Rank2Types #-}
6 {-# LANGUAGE ScopedTypeVariables #-}
7 {-# LANGUAGE TypeFamilies #-}
8 {-# LANGUAGE TypeOperators #-}
9 module Language.Symantic.Typing.Type where
11 import Data.Maybe (isJust)
13 import Data.Type.Equality
14 import GHC.Prim (Constraint)
16 import Language.Symantic.Typing.Kind
17 import Language.Symantic.Typing.Constant
23 -- * @cs@: /type constants/.
24 -- * @ki@: 'Kind' (/type of the type/).
25 -- * @h@: Haskell type projected onto.
27 -- * 'TyConst': /type constant/
28 -- * '(:$)': /type application/
29 -- * '(:~)': /type constraint constructor/
31 -- NOTE: when used, @h@ is a 'Proxy',
32 -- because @GADTs@ constructors cannot alter kinds.
33 -- Neither is it possible to assert that @(@'UnProxy'@ f :: * -> *)@,
34 -- and therefore @(@'UnProxy'@ f (@'UnProxy'@ x))@ cannot kind check;
35 -- however a type application of @f@ is needed in 'App' and 'Con',
36 -- so this is worked around with the introduction of the 'App' type family,
37 -- which handles the type application when @(@'UnProxy'@ f :: * -> *)@
38 -- is true from elsewhere, or stay abstract otherwise.
39 -- However, since type synonym family cannot be used within the pattern
40 -- of another type family, the kind of an abstract
41 -- @(@'App'@ f x)@ cannot be derived from @f@,
42 -- so this is worked around with the introduction of the @ki@ parameter.
43 data Type (cs::[*]) (ki::Kind) (h:: *) where
46 -> Type cs (Kind_of_Proxy c) c
48 :: Type cs (ki_x ':> ki) f
50 -> Type cs ki (App f x)
53 => Type cs (ki_x ':> 'KiCon) q
55 -> Type cs 'KiCon (App q x)
65 -- ** Type family 'UnProxy'
66 -- | Useful to have 'App' and 'Con' type families working on all @a@.
67 type family UnProxy px :: k where
70 -- ** Type family 'App'
71 -- | Lift the Haskell /type application/ within a 'Proxy'.
72 type family App (f:: *) (a:: *) :: *
73 type instance App (Proxy (f:: ki_a -> ki_fa)) a = Proxy (f (UnProxy a))
75 -- ** Type family 'Con'
76 -- | Lift the Haskell /type constraint/ within a 'Proxy'.
77 type family Con (q:: *) (a:: *) :: Constraint
78 type instance Con (Proxy (q:: ki_a -> Constraint)) a = q (UnProxy a)
81 -- | Convenient wrapper when @t@ is statically known.
82 type Type_of cs t = Type cs (Kind_of t) (Proxy t)
84 kind_of :: Type cs ki h -> SKind ki
87 TyConst c -> kind_of_const c
88 f :$ _x -> case kind_of f of _ `SKiArrow` ki -> ki
89 q :~ _x -> case kind_of q of _ `SKiArrow` ki -> ki
92 :: Type cs ki_x x -> Type cs ki_y y
94 eq_type (TyConst x) (TyConst y)
95 | Just Refl <- testEquality x y
97 eq_type (xf :$ xx) (yf :$ yx)
98 | Just Refl <- eq_type xf yf
99 , Just Refl <- eq_type xx yx
101 eq_type (xq :~ xx) (yq :~ yx)
102 | Just Refl <- eq_type xq yq
103 , Just Refl <- eq_type xx yx
105 eq_type _ _ = Nothing
107 instance TestEquality (Type cs ki) where
108 testEquality = eq_type
111 -- | Existential for 'Type'.
112 data EType cs = forall ki h. EType (Type cs ki h)
114 instance Eq (EType cs) where
115 EType x == EType y = isJust $ eq_type x y
116 instance Show_Const cs => Show (EType cs) where
117 show (EType ty) = show_type ty
119 show_type :: Show_Const cs => Type cs ki_h h -> String
120 show_type (TyConst c) = show c
121 show_type ((:$) f@(:$){} a@(:$){}) = "(" ++ show_type f ++ ") (" ++ show_type a ++ ")"
122 show_type ((:$) f@(:$){} a) = "(" ++ show_type f ++ ") " ++ show_type a
123 show_type ((:$) f a@(:$){}) = show_type f ++ " (" ++ show_type a ++ ")"
124 show_type ((:$) f a) = show_type f ++ " " ++ show_type a
125 show_type ((:~) q a) = show_type q ++ " " ++ show_type a
126 -- show_type (TyVar v) = "t" ++ show (integral_from_peano v::Integer)
129 data Args (cs::[*]) (args::[*]) where
131 ArgS :: Type cs ki arg
133 -> Args cs (arg ': args)
136 -- | Build the left spine of a 'Type'.
139 -> (forall c as. Const cs c
140 -> Args cs as -> ret) -> ret
141 spine_of_type (TyConst c) k = k c ArgZ
142 spine_of_type (f :$ a) k = spine_of_type f $ \c as -> k c (a `ArgS` as)
143 spine_of_type (q :~ a) k = spine_of_type q $ \c as -> k c (a `ArgS` as)
147 -- | The 'Bool' 'Type'
148 tyBool :: Inj_Const cs Bool => Type_of cs Bool
149 tyBool = TyConst inj_const
152 tyEq :: Inj_Const cs Eq => Type_of cs Eq
153 tyEq = TyConst inj_const
155 -- | The 'Int' 'Type'
156 tyInt :: Inj_Const cs Int => Type_of cs Int
157 tyInt = TyConst inj_const
159 -- | The 'IO'@ a@ 'Type'
160 tyIO :: Inj_Const cs IO => Type_of cs IO
161 tyIO = TyConst inj_const
163 -- | The 'Traversable'@ a@ 'Type'
164 tyTraversable :: Inj_Const cs Traversable => Type_of cs Traversable
165 tyTraversable = TyConst inj_const
167 -- | The 'Monad'@ a@ 'Type'
168 tyMonad :: Inj_Const cs Monad => Type_of cs Monad
169 tyMonad = TyConst inj_const
171 -- | The 'Int' 'Type'
172 tyFun :: Inj_Const cs (->) => Type_of cs (->)
173 tyFun = TyConst inj_const
175 -- | The function 'Type' @(\->) a b@
176 -- with an infix notation more readable.
177 (~>) :: forall cs a b. Inj_Const cs (->)
178 => Type cs 'KiTerm (Proxy a)
179 -> Type cs 'KiTerm (Proxy b)
180 -> Type_of cs (a -> b)
181 (~>) a b = TyConst (inj_const::Const cs (Proxy (->))) :$ a :$ b