1 {-# LANGUAGE DataKinds #-} -- For ReprKind
2 {-# LANGUAGE PatternSynonyms #-} -- For (:!:)
3 {-# LANGUAGE TypeFamilyDependencies #-} -- For Permutation
4 {-# LANGUAGE UndecidableInstances #-} -- For Permutation
5 module Symantic.Class 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 Data.Semigroup (Semigroup)
15 import GHC.Generics (Generic)
16 import qualified Control.Category as Cat
17 import qualified Data.Function as Fun
18 import qualified Data.Tuple as Tuple
20 import Symantic.Derive
22 import Symantic.CurryN
25 type ReprKind = Type -> Type
27 -- * Class 'Abstractable'
28 class Abstractable repr where
29 -- | Lambda term abstraction, in HOAS (Higher-Order Abstract Syntax) style.
30 lam :: (repr a -> repr b) -> repr (a->b)
31 -- | Like 'lam' but whose argument is used only once,
32 -- hence safe to beta-reduce (inline) without duplicating work.
33 lam1 :: (repr a -> repr b) -> repr (a->b)
34 var :: repr a -> repr a
35 -- | Application, aka. unabstract.
36 (.@) :: repr (a->b) -> repr a -> repr b; infixl 9 .@
37 lam f = liftDerived (lam (derive Fun.. f Fun.. liftDerived))
38 lam1 f = liftDerived (lam1 (derive Fun.. f Fun.. liftDerived))
39 var = liftDerived1 var
40 (.@) = liftDerived2 (.@)
42 FromDerived Abstractable repr => Derivable repr =>
43 (repr a -> repr b) -> repr (a->b)
45 FromDerived Abstractable repr => Derivable repr =>
46 (repr a -> repr b) -> repr (a->b)
48 FromDerived1 Abstractable repr =>
51 FromDerived2 Abstractable repr =>
52 repr (a->b) -> repr a -> repr b
54 -- ** Class 'Functionable'
55 class Functionable repr where
56 const :: repr (a -> b -> a)
57 flip :: repr ((a -> b -> c) -> b -> a -> c)
59 (.) :: repr ((b->c) -> (a->b) -> a -> c); infixr 9 .
60 ($) :: repr ((a->b) -> a -> b); infixr 0 $
61 const = liftDerived const
62 flip = liftDerived flip
67 FromDerived Functionable repr =>
70 FromDerived Functionable repr =>
71 repr ((a -> b -> c) -> b -> a -> c)
73 FromDerived Functionable repr =>
76 FromDerived Functionable repr =>
77 repr ((b->c) -> (a->b) -> a -> c)
79 FromDerived Functionable repr =>
80 repr ((a->b) -> a -> b)
82 -- * Class 'Anythingable'
83 class Anythingable repr where
84 anything :: repr a -> repr a
87 -- * Class 'Bottomable'
88 class Bottomable repr where
91 -- * Class 'Constantable'
92 class Constantable c repr where
93 constant :: c -> repr c
94 constant = liftDerived Fun.. constant
96 FromDerived (Constantable c) repr =>
99 bool :: Constantable Bool repr => Bool -> repr Bool
100 bool = constant @Bool
101 char :: Constantable Char repr => Char -> repr Char
102 char = constant @Char
103 unit :: Constantable () repr => repr ()
104 unit = constant @() ()
106 -- * Class 'Eitherable'
107 class Eitherable repr where
108 left :: repr (l -> Either l r)
109 right :: repr (r -> Either l r)
110 left = liftDerived left
111 right = liftDerived right
113 FromDerived Eitherable repr =>
114 repr (l -> Either l r)
116 FromDerived Eitherable repr =>
117 repr (r -> Either l r)
119 -- * Class 'Equalable'
120 class Equalable repr where
121 equal :: Eq a => repr (a -> a -> Bool)
122 equal = liftDerived equal
124 FromDerived Equalable repr =>
125 Eq a => repr (a -> a -> Bool)
129 Abstractable repr => Equalable repr => Eq a =>
130 repr a -> repr a -> repr Bool
131 (==) x y = equal .@ x .@ y
133 -- * Class 'IfThenElseable'
134 class IfThenElseable repr where
135 ifThenElse :: repr Bool -> repr a -> repr a -> repr a
136 ifThenElse = liftDerived3 ifThenElse
137 default ifThenElse ::
138 FromDerived3 IfThenElseable repr =>
139 repr Bool -> repr a -> repr a -> repr a
141 -- * Class 'Listable'
142 class Listable repr where
143 cons :: repr (a -> [a] -> [a])
145 cons = liftDerived cons
146 nil = liftDerived nil
148 FromDerived Listable repr =>
149 repr (a -> [a] -> [a])
151 FromDerived Listable repr =>
154 -- * Class 'Maybeable'
155 class Maybeable repr where
156 nothing :: repr (Maybe a)
157 just :: repr (a -> Maybe a)
158 nothing = liftDerived nothing
159 just = liftDerived just
161 FromDerived Maybeable repr =>
164 FromDerived Maybeable repr =>
167 -- * Class 'IsoFunctor'
168 class IsoFunctor repr where
169 (<%>) :: Iso a b -> repr a -> repr b; infixl 4 <%>
170 (<%>) iso = liftDerived1 (iso <%>)
172 FromDerived1 IsoFunctor repr =>
173 Iso a b -> repr a -> repr b
176 data Iso a b = Iso { a2b :: a->b, b2a :: b->a }
177 instance Cat.Category Iso where
178 id = Iso Cat.id Cat.id
179 f . g = Iso (a2b f Cat.. a2b g) (b2a g Cat.. b2a f)
181 -- * Class 'ProductFunctor'
182 -- | Beware that this is an @infixr@,
183 -- not @infixl@ like to 'Control.Applicative.<*>';
184 -- this is to follow what is expected by 'ADT'.
185 class ProductFunctor repr where
186 (<.>) :: repr a -> repr b -> repr (a, b); infixr 4 <.>
187 (<.>) = liftDerived2 (<.>)
189 FromDerived2 ProductFunctor repr =>
190 repr a -> repr b -> repr (a, b)
191 (<.) :: repr a -> repr () -> repr a; infixr 4 <.
192 ra <. rb = Iso Tuple.fst (, ()) <%> (ra <.> rb)
193 default (<.) :: IsoFunctor repr => repr a -> repr () -> repr a
194 (.>) :: repr () -> repr a -> repr a; infixr 4 .>
195 ra .> rb = Iso Tuple.snd (() ,) <%> (ra <.> rb)
196 default (.>) :: IsoFunctor repr => repr () -> repr a -> repr a
198 -- * Class 'SumFunctor'
199 -- | Beware that this is an @infixr@,
200 -- not @infixl@ like to 'Control.Applicative.<|>';
201 -- this is to follow what is expected by 'ADT'.
202 class SumFunctor repr where
203 (<+>) :: repr a -> repr b -> repr (Either a b); infixr 3 <+>
204 (<+>) = liftDerived2 (<+>)
206 FromDerived2 SumFunctor repr =>
207 repr a -> repr b -> repr (Either a b)
209 -- * Class 'AlternativeFunctor'
210 -- | Beware that this is an @infixr@,
211 -- not @infixl@ like to 'Control.Applicative.<|>';
212 -- this is to follow what is expected by 'ADT'.
213 class AlternativeFunctor repr where
214 (<|>) :: repr a -> repr a -> repr a; infixr 3 <|>
215 (<|>) = liftDerived2 (<|>)
217 FromDerived2 AlternativeFunctor repr =>
218 repr a -> repr a -> repr a
220 -- * Class 'Dicurryable'
221 class Dicurryable repr where
225 (args-..->a) -> -- construction
226 (a->Tuples args) -> -- destruction
227 repr (Tuples args) ->
229 dicurry args constr destr = liftDerived1 (dicurry args constr destr)
231 FromDerived1 Dicurryable repr =>
236 repr (Tuples args) ->
245 Tuples args ~ EoT (ADT a) =>
246 (args ~ Args (args-..->a)) =>
248 repr (Tuples args) ->
250 construct f = dicurry (Proxy::Proxy args) f eotOfadt
258 repr (EoT (ADT adt)) ->
260 adt = (<%>) (Iso adtOfeot eotOfadt)
262 -- * Class 'Monoidable'
272 -- ** Class 'Emptyable'
273 class Emptyable repr where
275 empty = liftDerived empty
277 FromDerived Emptyable repr =>
280 -- ** Class 'Semigroupable'
281 class Semigroupable repr where
282 concat :: Semigroup a => repr (a -> a -> a)
283 concat = liftDerived concat
285 FromDerived Semigroupable repr =>
289 infixr 6 `concat`, <>
291 Abstractable repr => Semigroupable repr => Semigroup a =>
292 repr a -> repr a -> repr a
293 (<>) x y = concat .@ x .@ y
295 -- ** Class 'Optionable'
296 class Optionable repr where
297 option :: repr a -> repr a
298 optional :: repr a -> repr (Maybe a)
299 option = liftDerived1 option
300 optional = liftDerived1 optional
302 FromDerived1 Optionable repr =>
305 FromDerived1 Optionable repr =>
306 repr a -> repr (Maybe a)
308 -- * Class 'Repeatable'
309 class Repeatable repr where
310 many0 :: repr a -> repr [a]
311 many1 :: repr a -> repr [a]
312 many0 = liftDerived1 many0
313 many1 = liftDerived1 many1
315 FromDerived1 Repeatable repr =>
318 FromDerived1 Repeatable repr =>
321 -- * Class 'Permutable'
322 class Permutable repr where
323 -- Use @TypeFamilyDependencies@ to help type-inference infer @(repr)@.
324 type Permutation (repr:: ReprKind) = (r :: ReprKind) | r -> repr
325 type Permutation repr = Permutation (Derived repr)
326 permutable :: Permutation repr a -> repr a
327 perm :: repr a -> Permutation repr a
328 noPerm :: Permutation repr ()
329 permWithDefault :: a -> repr a -> Permutation repr a
331 Eitherable repr => IsoFunctor repr => Permutable repr =>
332 repr a -> Permutation repr (Maybe a)
333 optionalPerm = permWithDefault Nothing Fun.. (<%>) (Iso Just fromJust)
337 ProductFunctor (Permutation repr) =>
339 Permutation repr b ->
340 Permutation repr (a, b)
341 x <&> y = perm x <.> y
349 ProductFunctor (Permutation repr) =>
351 Permutation repr b ->
352 Permutation repr (Maybe a, b)
353 x <?&> y = optionalPerm x <.> y
355 {-# INLINE (<?&>) #-}
362 ProductFunctor (Permutation repr) =>
364 Permutation repr b ->
365 Permutation repr ([a],b)
366 x <*&> y = permWithDefault [] (many1 x) <.> y
368 {-# INLINE (<*&>) #-}
375 ProductFunctor (Permutation repr) =>
377 Permutation repr b ->
378 Permutation repr ([a], b)
379 x <+&> y = perm (many1 x) <.> y
381 {-# INLINE (<+&>) #-}
383 -- * Class 'Routable'
384 class Routable repr where
385 (<!>) :: repr a -> repr b -> repr (a, b); infixr 4 <!>
386 (<!>) = liftDerived2 (<!>)
388 FromDerived2 Routable repr =>
389 repr a -> repr b -> repr (a, b)
391 -- | Like @(,)@ but @infixr@.
392 -- Mostly useful for clarity when using 'Routable'.
393 pattern (:!:) :: a -> b -> (a, b)
394 pattern a:!:b <- (a, b)
398 -- * Class 'Voidable'
399 -- | FIXME: this class should likely be removed
400 class Voidable repr where
401 void :: a -> repr a -> repr ()
402 void = liftDerived1 Fun.. void
404 FromDerived1 Voidable repr =>
405 a -> repr a -> repr ()
407 -- * Class 'Substractable'
408 class Substractable repr where
409 (<->) :: repr a -> repr b -> repr a; infixr 3 <->
410 (<->) = liftDerived2 (<->)
412 FromDerived2 Substractable repr =>
413 repr a -> repr b -> repr a