1 {-# LANGUAGE ConstraintKinds #-}
2 {-# LANGUAGE InstanceSigs #-}
3 {-# LANGUAGE QuantifiedConstraints #-}
4 {-# LANGUAGE RankNTypes #-}
5 {-# LANGUAGE UndecidableInstances #-}
6 {-# OPTIONS_GHC -Wno-partial-fields #-}
8 module Symantic.Compiler.Term where
10 import Control.Applicative (Applicative (..))
11 import Data.Function ((.))
12 import Data.Function qualified as Fun
13 import GHC.Types (Constraint, Type)
14 import Symantic.Semantics.Forall
15 import Symantic.Syntaxes.Classes (Syntaxes, Unabstractable (..))
16 import Type.Reflection (Typeable)
17 import Unsafe.Coerce (unsafeCoerce)
19 import Symantic.Typer.Type (Ty, monoTy)
21 type Semantic = Type -> Type
22 type Syntax = Semantic -> Constraint
24 -- * Class 'AbstractableTy'
25 class AbstractableTy meta sem where
26 -- | Lambda term abstraction, in HOAS (Higher-Order Abstract Syntax) style.
27 lamTy :: Ty meta '[] a -> (sem a -> sem b) -> sem (a -> b)
30 AbstractableTy () sem =>
34 fun = lamTy (monoTy @_ @())
36 -- * Class 'Constable'
37 class Constable sem where
38 constI :: sem (a -> a)
39 constK :: sem (a -> b -> a)
40 constS :: sem ((a -> b -> c) -> (a -> b) -> a -> c)
41 constB :: sem ((b -> c) -> (a -> b) -> a -> c)
42 constC :: sem ((a -> b -> c) -> b -> a -> c)
44 instance (forall sem. Syntaxes syns sem => Constable sem) => Constable (Forall syns) where
45 constI = Forall constI
46 constK = Forall constK
47 constS = Forall constS
48 constB = Forall constB
49 constC = Forall constC
51 ( forall sem. Syntaxes syns sem => AbstractableTy meta sem
52 -- , forall sem a. syn sem => AbstractableLam sem a
53 -- , forall sem. syn sem => AbstractableLam sem a
54 -- , forall sem. syn sem => Typeable sem -- user instance not accepted
55 -- , forall s1 s2. (syn s1, syn s2) => s1 ~ s2 -- crazy...
57 AbstractableTy meta (Forall syns)
59 lamTy aTy f = Forall (lamTy aTy (\a -> let Forall b = f (forallSem a) in b))
61 -- Safe here because (a :: sem a) and (b :: sem b) share the same 'sem'.
62 forallSem :: sem a -> Forall syns a
63 forallSem a = Forall (unsafeCoerce a)
66 data OpenTerm (syns :: [Syntax]) (vs :: [Type]) (a :: Type) where
67 -- E contains embedded closed (i.e. already abstracted) terms.
68 E :: Forall syns a -> OpenTerm syns vs a
69 -- V represents a reference to the innermost/top environment
71 V :: OpenTerm syns (a ': vs) a
72 -- N represents internalizing the innermost bound variable as a
73 -- function argument. In other words, we can represent an open
74 -- term referring to a certain variable as a function which
75 -- takes that variable as an argument.
76 N :: OpenTerm syns vs (a -> b) -> OpenTerm syns (a ': vs) b
77 -- For efficiency, there is also a special variant of N for the
78 -- case where the term does not refer to the topmost variable at all.
79 W :: OpenTerm syns vs b -> OpenTerm syns (a ': vs) b
81 ( forall sem. Syntaxes syns sem => AbstractableTy meta sem
82 , Syntaxes syns (Forall syns)
84 AbstractableTy meta (OpenTerm syns '[])
86 lamTy aTy f = E (lamTy aTy (runOpenTerm . f . E))
88 ( forall sem. Syntaxes syns sem => Constable sem
89 , Syntaxes syns (Forall syns)
91 Constable (OpenTerm syns vs)
100 newtype R a = R {unR :: a}
101 instance AbstractableTy meta R where
102 lamTy _aTy f = R (unR . f . R)
103 instance Unabstractable R where
105 instance Constable R where
112 runOpenTerm :: OpenTerm syns '[] a -> Forall syns a
113 runOpenTerm t = case t of E t' -> t'
115 eval :: Syntaxes syns R => OpenTerm syns '[] a -> a
117 | Forall sem <- runOpenTerm t =
121 ( forall sem. Syntaxes syns sem => Constable sem
122 , forall sem. Syntaxes syns sem => Unabstractable sem
123 , Syntaxes syns (Forall syns)
125 Unabstractable (OpenTerm syns vs)
131 ( forall sem. Syntaxes syns sem => Constable sem
132 , forall sem. Syntaxes syns sem => Unabstractable sem
133 , Syntaxes syns (Forall syns)
135 OpenTerm syns as (a -> b) ->
136 OpenTerm syns as a ->
138 W e1 `appOpenTerm` W e2 = W (e1 `appOpenTerm` e2)
139 W e `appOpenTerm` E d = W (e `appOpenTerm` E d)
140 E d `appOpenTerm` W e = W (E d `appOpenTerm` e)
141 W e `appOpenTerm` V = N e
142 V `appOpenTerm` W e = N (E (constC .@ constI) `appOpenTerm` e)
143 W e1 `appOpenTerm` N e2 = N (E constB `appOpenTerm` e1 `appOpenTerm` e2)
144 N e1 `appOpenTerm` W e2 = N (E constC `appOpenTerm` e1 `appOpenTerm` e2)
145 N e1 `appOpenTerm` N e2 = N (E constS `appOpenTerm` e1 `appOpenTerm` e2)
146 N e `appOpenTerm` V = N (E constS `appOpenTerm` e `appOpenTerm` E constI)
147 V `appOpenTerm` N e = N (E (constS .@ constI) `appOpenTerm` e)
148 E d `appOpenTerm` N e = N (E (constB .@ d) `appOpenTerm` e)
149 E d `appOpenTerm` V = N (E d)
150 V `appOpenTerm` E d = N (E (constC .@ constI .@ d))
151 N e `appOpenTerm` E d = N (E (constC .@ constC .@ d) `appOpenTerm` e)
152 E d1 `appOpenTerm` E d2 = E (d1 .@ d2)