1 -- For type class synonyms
2 {-# LANGUAGE ConstraintKinds #-}
4 {-# LANGUAGE DataKinds #-}
5 -- For adding LiftDerived* constraints
6 {-# LANGUAGE DefaultSignatures #-}
7 {-# LANGUAGE PolyKinds #-}
9 module Symantic.Syntaxes.Derive where
11 import Data.Function ((.))
12 import Data.Kind (Type)
16 -- | The kind of @sem@(antics) throughout this library.
17 type Semantic = Type -> Type
19 -- * Type family 'Derived'
21 -- | The next 'Semantic' that @(sem)@ derives to.
22 type family Derived (sem :: Semantic) :: Semantic
24 -- * Class 'Derivable'
26 -- | Derive from a semantic @(sem)@
27 -- another semantic determined by the 'Derived' open type family.
28 -- This is mostly useful when running a semantic stack,
29 -- but also when going back from an initial encoding to a final one.
31 -- Note that 'derive' and 'liftDerived' are not necessarily reciprocical functions.
32 class Derivable sem where
33 derive :: sem a -> Derived sem a
35 -- * Class 'LiftDerived'
37 -- | Lift the 'Derived' interpreter of an interpreter, to that interpreter.
38 -- This is mostly useful to give default values to class methods
39 -- in order to skip their definition for interpreters
40 -- where 'liftDerived' can already apply the right semantic.
42 -- Note that 'derive' and 'liftDerived' are not necessarily reciprocical functions.
43 class LiftDerived sem where
44 liftDerived :: Derived sem a -> sem a
46 -- * Class 'LiftDerived1'
48 -- | Convenient wrapper of 'derive' and 'liftDerived' for functions with a single argument.
49 class LiftDerived1 sem where
51 (Derived sem a -> Derived sem b) ->
54 liftDerived1 f = liftDerived . f . derive
55 default liftDerived1 ::
58 (Derived sem a -> Derived sem b) ->
62 -- * Class 'LiftDerived2'
64 -- | Convenient wrapper of 'derive' and 'liftDerived' for functions with two arguments.
65 -- Note that the default instance relies upon 'LiftDerived', not 'LiftDerived1'.
66 class LiftDerived2 sem where
68 (Derived sem a -> Derived sem b -> Derived sem c) ->
72 liftDerived2 f a b = liftDerived (f (derive a) (derive b))
73 default liftDerived2 ::
76 (Derived sem a -> Derived sem b -> Derived sem c) ->
81 -- * Class 'LiftDerived3'
83 -- | Convenient wrapper of 'derive' and 'liftDerived' for functions with three arguments.
84 -- Note that the default instance relies upon 'LiftDerived', not 'LiftDerived2'.
85 class LiftDerived3 sem where
87 (Derived sem a -> Derived sem b -> Derived sem c -> Derived sem d) ->
92 liftDerived3 f a b c = liftDerived (f (derive a) (derive b) (derive c))
93 default liftDerived3 ::
96 (Derived sem a -> Derived sem b -> Derived sem c -> Derived sem d) ->
102 -- * Class 'LiftDerived4'
104 -- | Convenient wrapper of 'derive' and 'liftDerived' for functions with three arguments.
105 -- Note that the default instance relies upon 'LiftDerived', not 'LiftDerived3'.
106 class LiftDerived4 sem where
108 (Derived sem a -> Derived sem b -> Derived sem c -> Derived sem d -> Derived sem e) ->
114 liftDerived4 f a b c d = liftDerived (f (derive a) (derive b) (derive c) (derive d))
115 default liftDerived4 ::
118 (Derived sem a -> Derived sem b -> Derived sem c -> Derived sem d -> Derived sem e) ->
125 -- * Type synonyms @FromDerived*@
127 -- | Convenient type synonym for using 'liftDerived' on 'Syntax' @(syn)@.
128 type FromDerived syn sem = (LiftDerived sem, syn (Derived sem))
130 type FromDerived1 syn sem = (LiftDerived1 sem, syn (Derived sem))
131 type FromDerived2 syn sem = (LiftDerived2 sem, syn (Derived sem))
132 type FromDerived3 syn sem = (LiftDerived3 sem, syn (Derived sem))
133 type FromDerived4 syn sem = (LiftDerived4 sem, syn (Derived sem))