1 {-# LANGUAGE DataKinds #-} -- For ReprKind
2 {-# LANGUAGE PatternSynonyms #-} -- For (:!:)
3 {-# LANGUAGE TypeFamilyDependencies #-} -- For Permutation
4 {-# LANGUAGE UndecidableInstances #-} -- For Permutation
5 module Symantic.Lang where
7 import Data.Bool (Bool(..))
8 import Data.Char (Char)
9 import Data.Either (Either(..))
11 import Data.Kind (Type)
12 import Data.Maybe (Maybe(..), fromJust)
13 import Data.Proxy (Proxy(..))
14 import GHC.Generics (Generic)
15 import qualified Control.Category as Cat
16 import qualified Data.Function as Fun
17 import qualified Data.Tuple as Tuple
19 import Symantic.Derive
21 import Symantic.CurryN
24 type ReprKind = Type -> Type
26 -- * Class 'Abstractable'
27 class Abstractable repr where
28 -- | Application, aka. unabstract.
29 (.@) :: repr (a->b) -> repr a -> repr b; infixl 9 .@
30 -- | Lambda term abstraction, in HOAS (Higher-Order Abstract Syntax) style.
31 lam :: (repr a -> repr b) -> repr (a->b)
32 -- | Like 'lam' but whose argument is used only once,
33 -- hence safe to beta-reduce (inline) without duplicating work.
34 lam1 :: (repr a -> repr b) -> repr (a->b)
35 const :: repr (a -> b -> a)
36 flip :: repr ((a -> b -> c) -> b -> a -> c)
38 (.) :: repr ((b->c) -> (a->b) -> a -> c); infixr 9 .
39 ($) :: repr ((a->b) -> a -> b); infixr 0 $
40 var :: repr a -> repr a
41 (.@) = liftDerived2 (.@)
42 lam f = liftDerived (lam (derive Fun.. f Fun.. liftDerived))
43 lam1 f = liftDerived (lam1 (derive Fun.. f Fun.. liftDerived))
44 const = liftDerived const
45 flip = liftDerived flip
49 var = liftDerived1 var
51 FromDerived2 Abstractable repr =>
52 repr (a->b) -> repr a -> repr b
54 FromDerived Abstractable repr => Derivable repr =>
55 (repr a -> repr b) -> repr (a->b)
57 FromDerived Abstractable repr => Derivable repr =>
58 (repr a -> repr b) -> repr (a->b)
60 FromDerived Abstractable repr =>
63 FromDerived Abstractable repr =>
64 repr ((a -> b -> c) -> b -> a -> c)
66 FromDerived Abstractable repr =>
69 FromDerived Abstractable repr =>
70 repr ((b->c) -> (a->b) -> a -> c)
72 FromDerived Abstractable repr =>
73 repr ((a->b) -> a -> b)
75 FromDerived1 Abstractable repr =>
78 -- * Class 'Anythingable'
79 class Anythingable repr where
80 anything :: repr a -> repr a
83 -- * Class 'Bottomable'
84 class Bottomable repr where
87 -- * Class 'Constantable'
88 class Constantable c repr where
89 constant :: c -> repr c
90 constant = liftDerived Fun.. constant
92 FromDerived (Constantable c) repr =>
95 bool :: Constantable Bool repr => Bool -> repr Bool
97 char :: Constantable Char repr => Char -> repr Char
99 unit :: Constantable () repr => repr ()
100 unit = constant @() ()
102 -- * Class 'Eitherable'
103 class Eitherable repr where
104 left :: repr (l -> Either l r)
105 right :: repr (r -> Either l r)
106 left = liftDerived left
107 right = liftDerived right
109 FromDerived Eitherable repr =>
110 repr (l -> Either l r)
112 FromDerived Eitherable repr =>
113 repr (r -> Either l r)
115 -- * Class 'Equalable'
116 class Equalable repr where
117 equal :: Eq a => repr (a -> a -> Bool)
118 equal = liftDerived equal
120 FromDerived Equalable repr =>
121 Eq a => repr (a -> a -> Bool)
124 (==) :: (Abstractable repr, Equalable repr, Eq a) => repr (a -> a -> Bool)
125 (==) = lam (\x -> lam (\y -> equal .@ x .@ y))
127 -- * Class 'IfThenElseable'
128 class IfThenElseable repr where
129 ifThenElse :: repr Bool -> repr a -> repr a -> repr a
130 ifThenElse = liftDerived3 ifThenElse
131 default ifThenElse ::
132 FromDerived3 IfThenElseable repr =>
133 repr Bool -> repr a -> repr a -> repr a
135 -- * Class 'Listable'
136 class Listable repr where
137 cons :: repr (a -> [a] -> [a])
139 cons = liftDerived cons
140 nil = liftDerived nil
142 FromDerived Listable repr =>
143 repr (a -> [a] -> [a])
145 FromDerived Listable repr =>
148 -- * Class 'Maybeable'
149 class Maybeable repr where
150 nothing :: repr (Maybe a)
151 just :: repr (a -> Maybe a)
152 nothing = liftDerived nothing
153 just = liftDerived just
155 FromDerived Maybeable repr =>
158 FromDerived Maybeable repr =>
161 -- * Class 'IsoFunctor'
162 class IsoFunctor repr where
163 (<%>) :: Iso a b -> repr a -> repr b; infixl 4 <%>
164 (<%>) iso = liftDerived1 (iso <%>)
166 FromDerived1 IsoFunctor repr =>
167 Iso a b -> repr a -> repr b
170 data Iso a b = Iso { a2b :: a->b, b2a :: b->a }
171 instance Cat.Category Iso where
172 id = Iso Cat.id Cat.id
173 f . g = Iso (a2b f Cat.. a2b g) (b2a g Cat.. b2a f)
175 -- * Class 'ProductFunctor'
176 -- | Beware that this is an @infixr@,
177 -- not @infixl@ like to 'Control.Applicative.<*>';
178 -- this is to follow what is expected by 'ADT'.
179 class ProductFunctor repr where
180 (<.>) :: repr a -> repr b -> repr (a, b); infixr 4 <.>
181 (<.>) = liftDerived2 (<.>)
183 FromDerived2 ProductFunctor repr =>
184 repr a -> repr b -> repr (a, b)
185 (<.) :: repr a -> repr () -> repr a; infixr 4 <.
186 ra <. rb = Iso Tuple.fst (, ()) <%> (ra <.> rb)
187 default (<.) :: IsoFunctor repr => repr a -> repr () -> repr a
188 (.>) :: repr () -> repr a -> repr a; infixr 4 .>
189 ra .> rb = Iso Tuple.snd (() ,) <%> (ra <.> rb)
190 default (.>) :: IsoFunctor repr => repr () -> repr a -> repr a
192 -- * Class 'SumFunctor'
193 -- | Beware that this is an @infixr@,
194 -- not @infixl@ like to 'Control.Applicative.<|>';
195 -- this is to follow what is expected by 'ADT'.
196 class SumFunctor repr where
197 (<+>) :: repr a -> repr b -> repr (Either a b); infixr 3 <+>
198 (<+>) = liftDerived2 (<+>)
200 FromDerived2 SumFunctor repr =>
201 repr a -> repr b -> repr (Either a b)
203 -- * Class 'AlternativeFunctor'
204 -- | Beware that this is an @infixr@,
205 -- not @infixl@ like to 'Control.Applicative.<|>';
206 -- this is to follow what is expected by 'ADT'.
207 class AlternativeFunctor repr where
208 (<|>) :: repr a -> repr a -> repr a; infixr 3 <|>
209 (<|>) = liftDerived2 (<|>)
211 FromDerived2 AlternativeFunctor repr =>
212 repr a -> repr a -> repr a
214 -- * Class 'Dicurryable'
215 class Dicurryable repr where
219 (args-..->a) -> -- construction
220 (a->Tuples args) -> -- destruction
221 repr (Tuples args) ->
223 dicurry args constr destr = liftDerived1 (dicurry args constr destr)
225 FromDerived1 Dicurryable repr =>
230 repr (Tuples args) ->
239 Tuples args ~ EoT (ADT a) =>
240 (args ~ Args (args-..->a)) =>
242 repr (Tuples args) ->
244 construct f = dicurry (Proxy::Proxy args) f eotOfadt
252 repr (EoT (ADT adt)) ->
254 adt = (<%>) (Iso adtOfeot eotOfadt)
256 -- ** Class 'Emptyable'
257 class Emptyable repr where
259 empty = liftDerived empty
261 FromDerived Emptyable repr =>
264 -- ** Class 'Optionable'
265 class Optionable repr where
266 option :: repr a -> repr a
267 optional :: repr a -> repr (Maybe a)
268 option = liftDerived1 option
269 optional = liftDerived1 optional
271 FromDerived1 Optionable repr =>
274 FromDerived1 Optionable repr =>
275 repr a -> repr (Maybe a)
277 -- * Class 'Repeatable'
278 class Repeatable repr where
279 many0 :: repr a -> repr [a]
280 many1 :: repr a -> repr [a]
281 many0 = liftDerived1 many0
282 many1 = liftDerived1 many1
284 FromDerived1 Repeatable repr =>
287 FromDerived1 Repeatable repr =>
290 -- * Class 'Permutable'
291 class Permutable repr where
292 -- Use @TypeFamilyDependencies@ to help type-inference infer @(repr)@.
293 type Permutation (repr:: ReprKind) = (r :: ReprKind) | r -> repr
294 type Permutation repr = Permutation (Derived repr)
295 permutable :: Permutation repr a -> repr a
296 perm :: repr a -> Permutation repr a
297 noPerm :: Permutation repr ()
298 permWithDefault :: a -> repr a -> Permutation repr a
300 Eitherable repr => IsoFunctor repr => Permutable repr =>
301 repr a -> Permutation repr (Maybe a)
302 optionalPerm = permWithDefault Nothing Fun.. (<%>) (Iso Just fromJust)
306 ProductFunctor (Permutation repr) =>
308 Permutation repr b ->
309 Permutation repr (a, b)
310 x <&> y = perm x <.> y
318 ProductFunctor (Permutation repr) =>
320 Permutation repr b ->
321 Permutation repr (Maybe a, b)
322 x <?&> y = optionalPerm x <.> y
324 {-# INLINE (<?&>) #-}
331 ProductFunctor (Permutation repr) =>
333 Permutation repr b ->
334 Permutation repr ([a],b)
335 x <*&> y = permWithDefault [] (many1 x) <.> y
337 {-# INLINE (<*&>) #-}
344 ProductFunctor (Permutation repr) =>
346 Permutation repr b ->
347 Permutation repr ([a], b)
348 x <+&> y = perm (many1 x) <.> y
350 {-# INLINE (<+&>) #-}
352 -- * Class 'Routable'
353 class Routable repr where
354 (<!>) :: repr a -> repr b -> repr (a, b); infixr 4 <!>
355 (<!>) = liftDerived2 (<!>)
357 FromDerived2 Routable repr =>
358 repr a -> repr b -> repr (a, b)
360 -- | Like @(,)@ but @infixr@.
361 -- Mostly useful for clarity when using 'Routable'.
362 pattern (:!:) :: a -> b -> (a, b)
363 pattern a:!:b <- (a, b)
367 -- * Class 'Voidable'
368 -- | FIXME: this class should likely be removed
369 class Voidable repr where
370 void :: a -> repr a -> repr ()
371 void = liftDerived1 Fun.. void
373 FromDerived1 Voidable repr =>
374 a -> repr a -> repr ()
376 -- * Class 'Substractable'
377 class Substractable repr where
378 (<->) :: repr a -> repr b -> repr a; infixr 3 <->
379 (<->) = liftDerived2 (<->)
381 FromDerived2 Substractable repr =>
382 repr a -> repr b -> repr a