]> Git — Sourcephile - haskell/symantic.git/blob - Language/Symantic/Typing/Family.hs
Add Gram_Term.
[haskell/symantic.git] / Language / Symantic / Typing / Family.hs
1 {-# LANGUAGE ConstraintKinds #-}
2 {-# LANGUAGE PolyKinds #-}
3 module Language.Symantic.Typing.Family where
4
5 import Control.Applicative ((<|>))
6 import Data.Proxy
7 import Data.Text (Text)
8
9 import Language.Symantic.Typing.Type
10
11 -- * Type family 'Fam'
12 -- | Apply the /type family/ selected by @fam@
13 -- to a list of types (within a 'Proxy').
14 type family Fam fam (hs::[*]) :: *
15
16 -- * Type 'Name_Fam'
17 type Name_Fam = Text
18
19 -- * Type 'Proj_Fam'
20 -- | Convenient type synonym wrapping 'Proj_FamR'
21 -- to initiate its recursion.
22 type Proj_Fam cs = Proj_FamR cs cs
23
24 -- | Project the 'Constraint' indexed by the given 'Type'
25 -- onto its proof, captured by 'Con' when it holds.
26 proj_fam
27 :: forall fam cs hs. Proj_Fam cs fam
28 => fam -> Types cs hs -> Maybe (Type cs (Fam fam hs))
29 proj_fam = proj_famR (Proxy @cs)
30
31 -- ** Class 'Proj_FamR'
32 -- | Intermediate type class to construct an instance of 'Proj_Fam'
33 -- from many instances of 'Proj_FamC', one for each item of @cs@.
34 --
35 -- * @cs@: starting list of /type constants/.
36 -- * @rs@: remaining list of /type constants/.
37 class Proj_FamR (cs::[*]) (rs::[*]) fam where
38 proj_famR
39 :: Proxy rs -> fam -> Types cs hs
40 -> Maybe (Type cs (Fam fam hs))
41 proj_famR _rs _fam _ty = Nothing
42
43 -- | Test whether @c@ handles the work of 'Proj_Fam' or not,
44 -- or recurse on @rs@, preserving the starting list of /type constants/.
45 instance
46 ( Proj_FamC cs fam c
47 , Proj_FamR cs rs fam
48 ) => Proj_FamR cs (Proxy c ': rs) fam where
49 proj_famR _rs fam typ =
50 proj_famC (Proxy @c) fam typ <|>
51 proj_famR (Proxy @rs) fam typ
52 -- | End the recursion.
53 instance Proj_FamR cs '[] fam
54
55 -- ** Class 'Proj_FamC'
56 -- | Handle the work of 'Proj_Fam' for a given /type family/ @fam@ and /type constant/ @c@,
57 -- that is: maybe it handles the given /type family/,
58 -- and if so, maybe the /type family/ has an instance for the given 'Type'.
59 class Proj_FamC cs fam (c::kc) where
60 proj_famC
61 :: Proxy c -> fam -> Types cs hs
62 -> Maybe (Type cs (Fam fam hs))
63 proj_famC _c _fam _ty = Nothing