]> Git — Sourcephile - haskell/symantic.git/blob - symantic/Language/Symantic/Typing/Type.hs
Add Lib.{Bounded,Enum,Ratio,Rational,Real,Semigroup}.
[haskell/symantic.git] / symantic / Language / Symantic / Typing / Type.hs
1 {-# LANGUAGE ConstraintKinds #-}
2 {-# LANGUAGE GADTs #-}
3 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
4 {-# LANGUAGE TypeInType #-}
5 {-# LANGUAGE UndecidableInstances #-}
6 {-# LANGUAGE ViewPatterns #-}
7 {-# OPTIONS_GHC -fno-warn-orphans #-}
8 module Language.Symantic.Typing.Type where
9
10 import Control.Applicative (Applicative(..))
11 import qualified Data.Char as Char
12 import Data.Monoid ((<>))
13 import Data.Proxy
14 import Data.Maybe (fromMaybe, isJust)
15 import Data.Text (Text)
16 import qualified Data.Text as Text
17 import Data.Type.Equality
18 import qualified Data.Kind as K
19
20 import Language.Symantic.Typing.Kind
21 import Language.Symantic.Typing.Constant
22 import Language.Symantic.Parsing
23
24 -- * Type 'Type'
25
26 -- | /Type of terms/.
27 --
28 -- * @cs@: /type constants/, fixed at compile time.
29 -- * @h@: indexed Haskell type.
30 --
31 -- * 'TyConst': /type constant/, selected amongst @cs@.
32 -- * @(:$)@: /type application/.
33 --
34 -- See also: https://ghc.haskell.org/trac/ghc/wiki/Typeable
35 -- Which currently concludes:
36 -- "Why kind equalities, then? Given the fact that Richard's branch
37 -- doesn't solve this problem, what is it good for?
38 -- It still works wonders in the mono-kinded case,
39 -- such as for decomposing ->.
40 -- It's just that poly-kinded constructors are still a pain."
41 data Type (cs::[K.Type]) (h::k) where
42 TyConst :: TyConst cs c -> Type cs c
43 (:$) :: Type cs f -> Type cs x -> Type cs (f x)
44 -- TODO: TyVar :: SKind k -> Type cs (v::k)
45 infixl 9 :$
46
47 -- | 'Type' constructor to be used
48 -- with @TypeApplications@
49 -- and @NoMonomorphismRestriction@.
50 ty :: forall c cs. Inj_TyConst cs c => Type cs c
51 ty = TyConst inj_TyConst
52 -- NOTE: The forall brings @c@ first in the type variables,
53 -- which is convenient to use @TypeApplications@.
54
55 instance TestEquality (Type cs) where
56 testEquality = eq_Type
57 instance Eq (Type cs h) where
58 _x == _y = True
59 instance Show_TyConst cs => Show (Type cs h) where
60 show = show_Type
61 -- deriving instance Show_TyConst cs => Show (Type cs h)
62
63 kind_of :: Type cs (h::k) -> SKind k
64 kind_of t =
65 case t of
66 TyConst c -> kind_of_TyConst c
67 f :$ _x ->
68 case kind_of f of
69 _kx `SKiArrow` kf -> kf
70
71 eq_Type
72 :: Type cs (x::k) -> Type cs (y::k) -> Maybe (x:~:y)
73 eq_Type (TyConst x) (TyConst y)
74 | Just Refl <- testEquality x y
75 = Just Refl
76 eq_Type (xf :$ xx) (yf :$ yx)
77 | Just Refl <- eq_skind (kind_of xf) (kind_of yf)
78 , Just Refl <- eq_Type xf yf
79 , Just Refl <- eq_Type xx yx
80 = Just Refl
81 eq_Type _ _ = Nothing
82
83 eq_Kind_Type
84 :: Type cs (x::kx) -> Type cs (y::ky) -> Maybe (kx:~:ky)
85 eq_Kind_Type (TyConst x) (TyConst y)
86 | Just Refl <- eq_Kind_TyConst x y
87 = Just Refl
88 eq_Kind_Type (xf :$ xx) (yf :$ yx)
89 | Just Refl <- eq_Kind_Type xf yf
90 , Just Refl <- eq_Kind_Type xx yx
91 = Just Refl
92 eq_Kind_Type _x _y = Nothing
93
94 show_Type :: Show_TyConst cs => Type cs h -> String
95 show_Type (TyConst c) = show c
96 show_Type (f@(:$){} :$ a@(:$){}) = "(" <> show_Type f <> ") (" <> show_Type a <> ")"
97 show_Type (f@(:$){} :$ a) = "(" <> show_Type f <> ") " <> show_Type a
98 show_Type (f :$ a@(:$){}) = show_Type f <> " (" <> show_Type a <> ")"
99 show_Type (f :$ a) = show_Type f <> " " <> show_Type a
100 -- show_Type (TyVar v) = "t" <> show (integral_from_peano v::Integer)
101
102 -- | Cons a @new_c@ to @cs@.
103 lift_Type :: Type cs c -> Type (new_c ': cs) c
104 lift_Type (TyConst c) = TyConst (TyConstS c)
105 lift_Type (f :$ a) = lift_Type f :$ lift_Type a
106
107 -- * Type 'EType'
108 -- | Existential for 'Type'.
109 data EType cs = forall h. EType (Type cs h)
110
111 instance Eq (EType cs) where
112 EType x == EType y
113 | Just Refl <- eq_Kind_Type x y
114 = isJust $ eq_Type x y
115 _x == _y = False
116 instance Show_TyConst cs => Show (EType cs) where
117 show (EType t) = show t
118
119 -- * Type 'KType'
120 -- | Existential for 'Type' of a known 'Kind'.
121 data KType cs k = forall (h::k). KType (Type cs h)
122
123 instance Eq (KType cs ki) where
124 KType x == KType y = isJust $ eq_Type x y
125 instance Show_TyConst cs => Show (KType cs ki) where
126 show (KType t) = show_Type t
127
128 -- * Type 'Token_Type'
129 type Token_Type = Type '[] ()
130
131 -- * Type 'TyName'
132 newtype TyName = TyName Text
133 deriving (Eq, Ord, Show)
134
135 data instance TokenT meta ts (Proxy Token_Type)
136 = Token_Type TyName [EToken meta ts]
137 deriving instance Eq_Token meta ts => Eq (TokenT meta ts (Proxy Token_Type))
138 deriving instance Show_Token meta ts => Show (TokenT meta ts (Proxy Token_Type))
139
140 instance
141 ( Read_TyNameR TyName cs rs
142 , Inj_TyConst cs Token_Type
143 ) => Read_TyNameR TyName cs (Proxy Token_Type ': rs) where
144 read_TyNameR _rs (TyName "Type") k = k (ty @Token_Type)
145 read_TyNameR _rs raw k = read_TyNameR (Proxy @rs) raw k
146 instance Show_TyConst cs => Show_TyConst (Proxy Token_Type ': cs) where
147 show_TyConst TyConstZ{} = "Type"
148 show_TyConst (TyConstS c) = show_TyConst c
149
150 -- * Class 'Compile_Type'
151 -- | Try to build a 'Type' from name data.
152 class Compile_Type ts cs where
153 compile_Type
154 :: ( MonoLift (Error_Type meta ts) err
155 , MonoLift (Con_Kind meta ts) err )
156 => EToken meta ts
157 -> (forall k h. Type cs (h::k) -> Either err ret)
158 -> Either err ret
159
160 compile_EType
161 :: Read_TyName TyName cs
162 => EToken meta '[Proxy Token_Type]
163 -> Either (Error_Type meta '[Proxy Token_Type]) (EType cs)
164 compile_EType tok = compile_Type tok (Right . EType)
165
166 -- ** Type 'Con_Kind'
167 data Con_Kind meta ts
168 = Con_Kind_Eq (At meta ts EKind) (At meta ts EKind)
169 | Con_Kind_Arrow (At meta ts EKind)
170 deriving instance (Eq_TokenR meta ts ts) => Eq (Con_Kind meta ts)
171 deriving instance (Show_TokenR meta ts ts) => Show (Con_Kind meta ts)
172
173 check_Kind
174 :: MonoLift (Con_Kind meta ts) err
175 => At meta ts (SKind x)
176 -> At meta ts (SKind y)
177 -> ((x :~: y) -> Either err ret) -> Either err ret
178 check_Kind x y k =
179 case unAt x `eq_skind` unAt y of
180 Just Refl -> k Refl
181 Nothing -> Left $ olift $
182 Con_Kind_Eq (EKind <$> x) (EKind <$> y)
183
184 check_Kind_arrow
185 :: MonoLift (Con_Kind meta ts) err
186 => At meta ts (SKind x)
187 -> (forall a b. (x :~: (a -> b)) -> SKind a -> SKind b -> Either err ret)
188 -> Either err ret
189 check_Kind_arrow x k =
190 case unAt x of
191 a `SKiArrow` b -> k Refl a b
192 _ -> Left $ olift $
193 Con_Kind_Arrow (EKind <$> x)
194
195 -- ** Type 'Error_Type'
196 data Error_Type meta ts
197 = Error_Type_Token_invalid (EToken meta ts)
198 | Error_Type_Constant_unknown (At meta ts TyName)
199 | Error_Type_Con_Kind (Con_Kind meta ts)
200 deriving instance (Eq_TokenR meta ts ts) => Eq (Error_Type meta ts)
201 deriving instance (Show_TokenR meta ts ts) => Show (Error_Type meta ts)
202
203 -- * Class 'Read_TyName'
204 type Read_TyName raw cs = Read_TyNameR raw cs cs
205
206 read_TyName
207 :: forall raw cs ret.
208 Read_TyNameR raw cs cs
209 => raw -> (forall k c. Type cs (c::k) -> Maybe ret)
210 -> Maybe ret
211 read_TyName = read_TyNameR (Proxy @cs)
212
213 -- ** Class 'Read_TyNameR'
214 class Read_TyNameR raw cs rs where
215 read_TyNameR
216 :: Proxy rs -> raw -> (forall k c. Type cs (c::k) -> Maybe ret)
217 -> Maybe ret
218
219 instance Read_TyNameR raw cs '[] where
220 read_TyNameR _cs _c _k = Nothing
221
222 -- TODO: move each of these to a dedicated module.
223 instance
224 ( Read_TyNameR TyName cs rs
225 , Inj_TyConst cs Fractional
226 ) => Read_TyNameR TyName cs (Proxy Fractional ': rs) where
227 read_TyNameR _cs (TyName "Fractional") k = k (ty @Fractional)
228 read_TyNameR _rs raw k = read_TyNameR (Proxy @rs) raw k
229 instance
230 ( Read_TyNameR TyName cs rs
231 , Inj_TyConst cs []
232 , Inj_TyConst cs Char
233 ) => Read_TyNameR TyName cs (Proxy String ': rs) where
234 read_TyNameR _cs (TyName "String") k = k (ty @[] :$ ty @Char)
235 read_TyNameR _rs raw k = read_TyNameR (Proxy @rs) raw k
236
237 instance
238 ( Read_TyName TyName cs
239 , Proj_Token ts Token_Type
240 ) => Compile_Type ts cs where
241 compile_Type
242 :: forall meta err ret.
243 ( MonoLift (Error_Type meta ts) err
244 , MonoLift (Con_Kind meta ts) err
245 ) => EToken meta ts
246 -> (forall k h. Type cs (h::k) -> Either err ret)
247 -> Either err ret
248 compile_Type tok@(proj_etoken -> Just (Token_Type cst args)) kk =
249 fromMaybe (Left $ olift $ Error_Type_Constant_unknown $ At (Just tok) cst) $
250 read_TyName cst $ \typ -> Just $
251 go args typ kk
252 where
253 go :: [EToken meta ts]
254 -> Type cs h
255 -> (forall k' h'. Type cs (h'::k') -> Either err ret)
256 -> Either err ret
257 go [] typ k = k typ
258 go (tok_x:tok_xs) ty_f k =
259 compile_Type tok_x $ \(ty_x::Type cs (h'::k')) ->
260 check_Kind_arrow
261 (At (Just tok) $ kind_of ty_f) $ \Refl ki_f_a _ki_f_b ->
262 check_Kind
263 (At (Just tok) ki_f_a)
264 (At (Just tok_x) $ kind_of ty_x) $ \Refl ->
265 go tok_xs (ty_f :$ ty_x) k
266 compile_Type tok _k = Left $ olift $ Error_Type_Token_invalid tok
267
268 -- * Type 'Types'
269 data Types cs (hs::[K.Type]) where
270 TypesZ :: Types cs '[]
271 TypesS :: Type cs h
272 -> Types cs hs
273 -> Types cs (Proxy h ': hs)
274 infixr 5 `TypesS`
275
276 eTypes :: Types cs hs -> [EType cs]
277 eTypes TypesZ = []
278 eTypes (TypesS t ts) = EType t : eTypes ts
279
280 -- | Build the left spine of a 'Type'.
281 spine_of_Type
282 :: Type cs h
283 -> (forall kc (c::kc) hs. TyConst cs c -> Types cs hs -> ret) -> ret
284 spine_of_Type (TyConst c) k = k c TypesZ
285 spine_of_Type (f :$ a) k = spine_of_Type f $ \c as -> k c (a `TypesS` as)
286
287 -- * Type 'UnProxy'
288 type family UnProxy (x::K.Type) :: k where
289 UnProxy (Proxy x) = x
290
291 -- * Class 'MonoLift'
292 class MonoLift a b where
293 olift :: a -> b
294 instance MonoLift
295 (Error_Type meta ts)
296 (Error_Type meta ts) where
297 olift = id
298 instance
299 MonoLift (Con_Kind meta ts) (Error_Type meta ts) where
300 olift = olift . Error_Type_Con_Kind
301
302 -- * Class 'Gram_Type'
303 type TokType meta = EToken meta '[Proxy Token_Type]
304 class
305 ( Alt g
306 , Alter g
307 , App g
308 , Try g
309 , Gram_CF g
310 , Gram_Rule g
311 , Gram_Terminal g
312 , Gram_Lexer g
313 , Gram_Op g
314 , Gram_Meta meta g
315 ) => Gram_Type meta g where
316 typeG :: CF g (TokType meta)
317 typeG = rule "type" $ type_fun
318 type_fun :: CF g (TokType meta)
319 type_fun = rule "type_fun" $
320 infixrG type_list (metaG $ op <$ symbol "->")
321 where op meta a b = inj_EToken meta $ Token_Type (TyName "(->)") [a, b]
322 type_list :: CF g (TokType meta)
323 type_list = rule "type_list" $
324 metaG $ inside f
325 (symbol "[") (option [] (pure <$> typeG)) (symbol "]")
326 (const <$> type_tuple2)
327 where f a meta = inj_EToken meta $ Token_Type (TyName "[]") a
328 type_tuple2 :: CF g (TokType meta)
329 type_tuple2 = rule "type_tuple2" $
330 try (parens (infixrG typeG (metaG $ op <$ symbol ","))) <+> type_app
331 where op meta a b = inj_EToken meta $ Token_Type (TyName "(,)") [a, b]
332 type_app :: CF g (TokType meta)
333 type_app = rule "type_app" $
334 f <$> some type_atom
335 where
336 f :: [TokType meta] -> TokType meta
337 f (EToken (TokenZ meta (Token_Type a as)):as') =
338 EToken $ TokenZ meta $ Token_Type a $ as <> as'
339 f _ = error "Oops, the impossible happened"
340 type_atom :: CF g (TokType meta)
341 type_atom = rule "type_atom" $
342 try (parens typeG) <+>
343 type_name <+>
344 type_symbol
345 type_name :: CF g (TokType meta)
346 type_name = rule "type_name" $
347 metaG $ lexeme $
348 (\c cs meta -> EToken $ TokenZ meta $ Token_Type (TyName $ Text.pack $ c:cs) [])
349 <$> unicat (Unicat Char.UppercaseLetter)
350 <*> many (choice $ unicat <$> [Unicat_Letter, Unicat_Number])
351 type_symbol :: CF g (TokType meta)
352 type_symbol = rule "type_symbol" $
353 metaG $ (f <$>) $
354 parens $ many $ cf_of_Terminal $ choice okG `but` choice koG
355 where
356 f s meta = inj_EToken meta $ (`Token_Type` []) $
357 TyName $ Text.concat ["(", Text.pack s, ")"]
358 okG = unicat <$>
359 [ Unicat_Symbol
360 , Unicat_Punctuation
361 , Unicat_Mark
362 ]
363 koG = char <$> ['(', ')', '`']
364
365 deriving instance Gram_Type meta g => Gram_Type meta (CF g)
366 instance Gram_Type meta EBNF
367 instance Gram_Type meta RuleDef
368
369 -- | List of the rules of 'Gram_Type'.
370 gram_type :: Gram_Type meta g => [CF g (TokType meta)]
371 gram_type =
372 [ typeG
373 , type_fun
374 , type_list
375 , type_tuple2
376 , type_app
377 , type_atom
378 , type_name
379 , type_symbol
380 ]