1 {-# LANGUAGE DataKinds #-} -- For ReprKind
2 {-# LANGUAGE PatternSynonyms #-} -- For (:!:)
3 {-# LANGUAGE TypeFamilyDependencies #-} -- For Permutation
4 {-# LANGUAGE UndecidableInstances #-} -- For Permutation
5 -- | Comibnators in this module conflict with usual ones from the @Prelude@
6 -- hence they are meant to be imported either explicitely or qualified.
7 module Symantic.Classes where
9 import Data.Bool (Bool(..))
10 import Data.Char (Char)
11 import Data.Either (Either(..))
14 import Data.Kind (Type)
15 import Data.Maybe (Maybe(..), fromJust)
16 import Data.Proxy (Proxy(..))
17 import Data.Semigroup (Semigroup)
18 import Data.String (String)
19 import GHC.Generics (Generic)
20 import Numeric.Natural (Natural)
21 import qualified Control.Category as Cat
22 import qualified Data.Function as Fun
23 import qualified Data.Tuple as Tuple
25 import Symantic.Derive
27 import Symantic.CurryN
30 -- | The kind of @repr@(esentations) throughout this library.
31 type ReprKind = Type -> Type
33 -- * Class 'Abstractable'
34 class Abstractable repr where
35 -- | Lambda term abstraction, in HOAS (Higher-Order Abstract Syntax) style.
36 lam :: (repr a -> repr b) -> repr (a->b)
37 -- | Like 'lam' but whose argument must be used only once,
38 -- hence safe to beta-reduce (inline) without duplicating work.
39 lam1 :: (repr a -> repr b) -> repr (a->b)
40 var :: repr a -> repr a
41 -- | Application, aka. unabstract.
42 (.@) :: repr (a->b) -> repr a -> repr b; infixl 9 .@
43 lam f = liftDerived (lam (derive Fun.. f Fun.. liftDerived))
44 lam1 f = liftDerived (lam1 (derive Fun.. f Fun.. liftDerived))
45 var = liftDerived1 var
46 (.@) = liftDerived2 (.@)
48 FromDerived Abstractable repr => Derivable repr =>
49 (repr a -> repr b) -> repr (a->b)
51 FromDerived Abstractable repr => Derivable repr =>
52 (repr a -> repr b) -> repr (a->b)
54 FromDerived1 Abstractable repr =>
57 FromDerived2 Abstractable repr =>
58 repr (a->b) -> repr a -> repr b
60 -- ** Class 'Functionable'
61 class Functionable repr where
62 const :: repr (a -> b -> a)
63 flip :: repr ((a -> b -> c) -> b -> a -> c)
65 (.) :: repr ((b->c) -> (a->b) -> a -> c); infixr 9 .
66 ($) :: repr ((a->b) -> a -> b); infixr 0 $
67 const = liftDerived const
68 flip = liftDerived flip
73 FromDerived Functionable repr =>
76 FromDerived Functionable repr =>
77 repr ((a -> b -> c) -> b -> a -> c)
79 FromDerived Functionable repr =>
82 FromDerived Functionable repr =>
83 repr ((b->c) -> (a->b) -> a -> c)
85 FromDerived Functionable repr =>
86 repr ((a->b) -> a -> b)
88 -- * Class 'Anythingable'
89 class Anythingable repr where
90 anything :: repr a -> repr a
93 -- * Class 'Bottomable'
94 class Bottomable repr where
97 -- * Class 'Constantable'
98 class Constantable c repr where
99 constant :: c -> repr c
100 constant = liftDerived Fun.. constant
102 FromDerived (Constantable c) repr =>
105 -- * Class 'Eitherable'
106 class Eitherable repr where
107 left :: repr (l -> Either l r)
108 right :: repr (r -> Either l r)
109 left = liftDerived left
110 right = liftDerived right
112 FromDerived Eitherable repr =>
113 repr (l -> Either l r)
115 FromDerived Eitherable repr =>
116 repr (r -> Either l r)
118 -- * Class 'Equalable'
119 class Equalable repr where
120 equal :: Eq a => repr (a -> a -> Bool)
121 equal = liftDerived equal
123 FromDerived Equalable repr =>
124 Eq a => repr (a -> a -> Bool)
128 Abstractable repr => Equalable repr => Eq a =>
129 repr a -> repr a -> repr Bool
130 (==) x y = equal .@ x .@ y
132 -- * Class 'IfThenElseable'
133 class IfThenElseable repr where
134 ifThenElse :: repr Bool -> repr a -> repr a -> repr a
135 ifThenElse = liftDerived3 ifThenElse
136 default ifThenElse ::
137 FromDerived3 IfThenElseable repr =>
138 repr Bool -> repr a -> repr a -> repr a
140 -- * Class 'Inferable'
141 class Inferable a repr where
143 default infer :: FromDerived (Inferable a) repr => repr a
144 infer = liftDerived infer
146 unit :: Inferable () repr => repr ()
148 bool :: Inferable Bool repr => repr Bool
150 char :: Inferable Char repr => repr Char
152 int :: Inferable Int repr => repr Int
154 natural :: Inferable Natural repr => repr Natural
156 string :: Inferable String repr => repr String
159 -- * Class 'Listable'
160 class Listable repr where
161 cons :: repr (a -> [a] -> [a])
163 cons = liftDerived cons
164 nil = liftDerived nil
166 FromDerived Listable repr =>
167 repr (a -> [a] -> [a])
169 FromDerived Listable repr =>
172 -- * Class 'Maybeable'
173 class Maybeable repr where
174 nothing :: repr (Maybe a)
175 just :: repr (a -> Maybe a)
176 nothing = liftDerived nothing
177 just = liftDerived just
179 FromDerived Maybeable repr =>
182 FromDerived Maybeable repr =>
185 -- * Class 'IsoFunctor'
186 class IsoFunctor repr where
187 (<%>) :: Iso a b -> repr a -> repr b; infixl 4 <%>
188 (<%>) iso = liftDerived1 (iso <%>)
190 FromDerived1 IsoFunctor repr =>
191 Iso a b -> repr a -> repr b
194 data Iso a b = Iso { a2b :: a->b, b2a :: b->a }
195 instance Cat.Category Iso where
196 id = Iso Cat.id Cat.id
197 f . g = Iso (a2b f Cat.. a2b g) (b2a g Cat.. b2a f)
199 -- * Class 'ProductFunctor'
200 -- | Beware that this is an @infixr@,
201 -- not @infixl@ like 'Control.Applicative.<*>';
202 -- this is to follow what is expected by 'ADT'.
203 class ProductFunctor repr where
204 (<.>) :: repr a -> repr b -> repr (a, b); infixr 4 <.>
205 (<.>) = liftDerived2 (<.>)
207 FromDerived2 ProductFunctor repr =>
208 repr a -> repr b -> repr (a, b)
209 (<.) :: repr a -> repr () -> repr a; infixr 4 <.
210 ra <. rb = Iso Tuple.fst (, ()) <%> (ra <.> rb)
211 default (<.) :: IsoFunctor repr => repr a -> repr () -> repr a
212 (.>) :: repr () -> repr a -> repr a; infixr 4 .>
213 ra .> rb = Iso Tuple.snd (() ,) <%> (ra <.> rb)
214 default (.>) :: IsoFunctor repr => repr () -> repr a -> repr a
216 -- * Class 'SumFunctor'
217 -- | Beware that this is an @infixr@,
218 -- not @infixl@ like 'Control.Applicative.<|>';
219 -- this is to follow what is expected by 'ADT'.
220 class SumFunctor repr where
221 (<+>) :: repr a -> repr b -> repr (Either a b); infixr 3 <+>
222 (<+>) = liftDerived2 (<+>)
224 FromDerived2 SumFunctor repr =>
225 repr a -> repr b -> repr (Either a b)
227 -- * Class 'AlternativeFunctor'
228 -- | Beware that this is an @infixr@,
229 -- not @infixl@ like 'Control.Applicative.<|>';
230 -- this is to follow what is expected by 'ADT'.
231 class AlternativeFunctor repr where
232 (<|>) :: repr a -> repr a -> repr a; infixr 3 <|>
233 (<|>) = liftDerived2 (<|>)
235 FromDerived2 AlternativeFunctor repr =>
236 repr a -> repr a -> repr a
238 -- * Class 'Dicurryable'
239 class Dicurryable repr where
243 (args-..->a) -> -- construction
244 (a->Tuples args) -> -- destruction
245 repr (Tuples args) ->
247 dicurry args constr destr = liftDerived1 (dicurry args constr destr)
249 FromDerived1 Dicurryable repr =>
254 repr (Tuples args) ->
263 Tuples args ~ EoT (ADT a) =>
264 (args ~ Args (args-..->a)) =>
266 repr (Tuples args) ->
268 construct f = dicurry (Proxy::Proxy args) f eotOfadt
276 repr (EoT (ADT adt)) ->
278 adt = (<%>) (Iso adtOfeot eotOfadt)
280 -- * Class 'Monoidable'
290 -- ** Class 'Emptyable'
291 class Emptyable repr where
293 empty = liftDerived empty
295 FromDerived Emptyable repr =>
298 -- ** Class 'Semigroupable'
299 class Semigroupable repr where
300 concat :: Semigroup a => repr (a -> a -> a)
301 concat = liftDerived concat
303 FromDerived Semigroupable repr =>
307 infixr 6 `concat`, <>
309 Abstractable repr => Semigroupable repr => Semigroup a =>
310 repr a -> repr a -> repr a
311 (<>) x y = concat .@ x .@ y
313 -- ** Class 'Optionable'
314 class Optionable repr where
315 option :: repr a -> repr a
316 optional :: repr a -> repr (Maybe a)
317 option = liftDerived1 option
318 optional = liftDerived1 optional
320 FromDerived1 Optionable repr =>
323 FromDerived1 Optionable repr =>
324 repr a -> repr (Maybe a)
326 -- * Class 'Repeatable'
327 class Repeatable repr where
328 many0 :: repr a -> repr [a]
329 many1 :: repr a -> repr [a]
330 many0 = liftDerived1 many0
331 many1 = liftDerived1 many1
333 FromDerived1 Repeatable repr =>
336 FromDerived1 Repeatable repr =>
339 -- | Alias to 'many0'.
340 many :: Repeatable repr => repr a -> repr [a]
343 -- | Alias to 'many1'.
344 some :: Repeatable repr => repr a -> repr [a]
347 -- * Class 'Permutable'
348 class Permutable repr where
349 -- Use @TypeFamilyDependencies@ to help type-inference infer @(repr)@.
350 type Permutation (repr:: ReprKind) = (r :: ReprKind) | r -> repr
351 type Permutation repr = Permutation (Derived repr)
352 permutable :: Permutation repr a -> repr a
353 perm :: repr a -> Permutation repr a
354 noPerm :: Permutation repr ()
355 permWithDefault :: a -> repr a -> Permutation repr a
357 Eitherable repr => IsoFunctor repr => Permutable repr =>
358 repr a -> Permutation repr (Maybe a)
359 optionalPerm = permWithDefault Nothing Fun.. (<%>) (Iso Just fromJust)
363 ProductFunctor (Permutation repr) =>
365 Permutation repr b ->
366 Permutation repr (a, b)
367 x <&> y = perm x <.> y
375 ProductFunctor (Permutation repr) =>
377 Permutation repr b ->
378 Permutation repr (Maybe a, b)
379 x <?&> y = optionalPerm x <.> y
381 {-# INLINE (<?&>) #-}
388 ProductFunctor (Permutation repr) =>
390 Permutation repr b ->
391 Permutation repr ([a],b)
392 x <*&> y = permWithDefault [] (many1 x) <.> y
394 {-# INLINE (<*&>) #-}
401 ProductFunctor (Permutation repr) =>
403 Permutation repr b ->
404 Permutation repr ([a], b)
405 x <+&> y = perm (many1 x) <.> y
407 {-# INLINE (<+&>) #-}
409 -- * Class 'Routable'
410 class Routable repr where
411 (<!>) :: repr a -> repr b -> repr (a, b); infixr 4 <!>
412 (<!>) = liftDerived2 (<!>)
414 FromDerived2 Routable repr =>
415 repr a -> repr b -> repr (a, b)
417 -- | Like @(,)@ but @infixr@.
418 -- Mostly useful for clarity when using 'Routable'.
419 pattern (:!:) :: a -> b -> (a, b)
420 pattern a:!:b <- (a, b)
424 -- * Class 'Voidable'
425 class Voidable repr where
426 -- | Useful to supply @(a)@ to a @(repr)@ consuming @(a)@,
427 -- for example in the format of a printing interpreter.
428 void :: a -> repr a -> repr ()
429 void = liftDerived1 Fun.. void
431 FromDerived1 Voidable repr =>
432 a -> repr a -> repr ()
434 -- * Class 'Substractable'
435 class Substractable repr where
436 (<->) :: repr a -> repr b -> repr a; infixr 3 <->
437 (<->) = liftDerived2 (<->)
439 FromDerived2 Substractable repr =>
440 repr a -> repr b -> repr a