1 {-# LANGUAGE DataKinds #-} -- For ReprKind
2 {-# LANGUAGE PatternSynonyms #-} -- For (:!:)
3 {-# LANGUAGE TypeFamilyDependencies #-} -- For Permutation
4 {-# LANGUAGE UndecidableInstances #-} -- For Permutation
5 -- | Combinators 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 optional :: repr a -> repr (Maybe a)
316 optional = liftDerived1 optional
318 FromDerived1 Optionable repr =>
319 repr a -> repr (Maybe a)
321 -- * Class 'Repeatable'
322 class Repeatable repr where
323 many0 :: repr a -> repr [a]
324 many1 :: repr a -> repr [a]
325 many0 = liftDerived1 many0
326 many1 = liftDerived1 many1
328 FromDerived1 Repeatable repr =>
331 FromDerived1 Repeatable repr =>
334 -- | Alias to 'many0'.
335 many :: Repeatable repr => repr a -> repr [a]
338 -- | Alias to 'many1'.
339 some :: Repeatable repr => repr a -> repr [a]
342 -- * Class 'Permutable'
343 class Permutable repr where
344 -- Use @TypeFamilyDependencies@ to help type-inference infer @(repr)@.
345 type Permutation (repr:: ReprKind) = (r :: ReprKind) | r -> repr
346 type Permutation repr = Permutation (Derived repr)
347 permutable :: Permutation repr a -> repr a
348 perm :: repr a -> Permutation repr a
349 noPerm :: Permutation repr ()
350 permWithDefault :: a -> repr a -> Permutation repr a
352 Eitherable repr => IsoFunctor repr => Permutable repr =>
353 repr a -> Permutation repr (Maybe a)
354 optionalPerm = permWithDefault Nothing Fun.. (<%>) (Iso Just fromJust)
358 ProductFunctor (Permutation repr) =>
360 Permutation repr b ->
361 Permutation repr (a, b)
362 x <&> y = perm x <.> y
370 ProductFunctor (Permutation repr) =>
372 Permutation repr b ->
373 Permutation repr (Maybe a, b)
374 x <?&> y = optionalPerm x <.> y
376 {-# INLINE (<?&>) #-}
383 ProductFunctor (Permutation repr) =>
385 Permutation repr b ->
386 Permutation repr ([a],b)
387 x <*&> y = permWithDefault [] (many1 x) <.> y
389 {-# INLINE (<*&>) #-}
396 ProductFunctor (Permutation repr) =>
398 Permutation repr b ->
399 Permutation repr ([a], b)
400 x <+&> y = perm (many1 x) <.> y
402 {-# INLINE (<+&>) #-}
404 -- * Class 'Routable'
405 class Routable repr where
406 (<!>) :: repr a -> repr b -> repr (a, b); infixr 4 <!>
407 (<!>) = liftDerived2 (<!>)
409 FromDerived2 Routable repr =>
410 repr a -> repr b -> repr (a, b)
412 -- | Like @(,)@ but @infixr@.
413 -- Mostly useful for clarity when using 'Routable'.
414 pattern (:!:) :: a -> b -> (a, b)
415 pattern a:!:b <- (a, b)
419 -- * Class 'Voidable'
420 class Voidable repr where
421 -- | Useful to supply @(a)@ to a @(repr)@ consuming @(a)@,
422 -- for example in the format of a printing interpreter.
423 void :: a -> repr a -> repr ()
424 void = liftDerived1 Fun.. void
426 FromDerived1 Voidable repr =>
427 a -> repr a -> repr ()
429 -- * Class 'Substractable'
430 class Substractable repr where
431 (<->) :: repr a -> repr b -> repr a; infixr 3 <->
432 (<->) = liftDerived2 (<->)
434 FromDerived2 Substractable repr =>
435 repr a -> repr b -> repr a