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)
128 (==) :: (Abstractable repr, Equalable repr, Eq a) => repr (a -> a -> Bool)
129 (==) = lam (\x -> lam (\y -> equal .@ x .@ y))
131 -- * Class 'IfThenElseable'
132 class IfThenElseable repr where
133 ifThenElse :: repr Bool -> repr a -> repr a -> repr a
134 ifThenElse = liftDerived3 ifThenElse
135 default ifThenElse ::
136 FromDerived3 IfThenElseable repr =>
137 repr Bool -> repr a -> repr a -> repr a
139 -- * Class 'Listable'
140 class Listable repr where
141 cons :: repr (a -> [a] -> [a])
143 cons = liftDerived cons
144 nil = liftDerived nil
146 FromDerived Listable repr =>
147 repr (a -> [a] -> [a])
149 FromDerived Listable repr =>
152 -- * Class 'Maybeable'
153 class Maybeable repr where
154 nothing :: repr (Maybe a)
155 just :: repr (a -> Maybe a)
156 nothing = liftDerived nothing
157 just = liftDerived just
159 FromDerived Maybeable repr =>
162 FromDerived Maybeable repr =>
165 -- * Class 'IsoFunctor'
166 class IsoFunctor repr where
167 (<%>) :: Iso a b -> repr a -> repr b; infixl 4 <%>
168 (<%>) iso = liftDerived1 (iso <%>)
170 FromDerived1 IsoFunctor repr =>
171 Iso a b -> repr a -> repr b
174 data Iso a b = Iso { a2b :: a->b, b2a :: b->a }
175 instance Cat.Category Iso where
176 id = Iso Cat.id Cat.id
177 f . g = Iso (a2b f Cat.. a2b g) (b2a g Cat.. b2a f)
179 -- * Class 'ProductFunctor'
180 -- | Beware that this is an @infixr@,
181 -- not @infixl@ like to 'Control.Applicative.<*>';
182 -- this is to follow what is expected by 'ADT'.
183 class ProductFunctor repr where
184 (<.>) :: repr a -> repr b -> repr (a, b); infixr 4 <.>
185 (<.>) = liftDerived2 (<.>)
187 FromDerived2 ProductFunctor repr =>
188 repr a -> repr b -> repr (a, b)
189 (<.) :: repr a -> repr () -> repr a; infixr 4 <.
190 ra <. rb = Iso Tuple.fst (, ()) <%> (ra <.> rb)
191 default (<.) :: IsoFunctor repr => repr a -> repr () -> repr a
192 (.>) :: repr () -> repr a -> repr a; infixr 4 .>
193 ra .> rb = Iso Tuple.snd (() ,) <%> (ra <.> rb)
194 default (.>) :: IsoFunctor repr => repr () -> repr a -> repr a
196 -- * Class 'SumFunctor'
197 -- | Beware that this is an @infixr@,
198 -- not @infixl@ like to 'Control.Applicative.<|>';
199 -- this is to follow what is expected by 'ADT'.
200 class SumFunctor repr where
201 (<+>) :: repr a -> repr b -> repr (Either a b); infixr 3 <+>
202 (<+>) = liftDerived2 (<+>)
204 FromDerived2 SumFunctor repr =>
205 repr a -> repr b -> repr (Either a b)
207 -- * Class 'AlternativeFunctor'
208 -- | Beware that this is an @infixr@,
209 -- not @infixl@ like to 'Control.Applicative.<|>';
210 -- this is to follow what is expected by 'ADT'.
211 class AlternativeFunctor repr where
212 (<|>) :: repr a -> repr a -> repr a; infixr 3 <|>
213 (<|>) = liftDerived2 (<|>)
215 FromDerived2 AlternativeFunctor repr =>
216 repr a -> repr a -> repr a
218 -- * Class 'Dicurryable'
219 class Dicurryable repr where
223 (args-..->a) -> -- construction
224 (a->Tuples args) -> -- destruction
225 repr (Tuples args) ->
227 dicurry args constr destr = liftDerived1 (dicurry args constr destr)
229 FromDerived1 Dicurryable repr =>
234 repr (Tuples args) ->
243 Tuples args ~ EoT (ADT a) =>
244 (args ~ Args (args-..->a)) =>
246 repr (Tuples args) ->
248 construct f = dicurry (Proxy::Proxy args) f eotOfadt
256 repr (EoT (ADT adt)) ->
258 adt = (<%>) (Iso adtOfeot eotOfadt)
260 -- * Class 'Monoidable'
270 -- ** Class 'Emptyable'
271 class Emptyable repr where
273 empty = liftDerived empty
275 FromDerived Emptyable repr =>
278 -- ** Class 'Semigroupable'
279 class Semigroupable repr where
280 concat :: Semigroup a => repr (a -> a -> a)
281 concat = liftDerived concat
283 FromDerived Semigroupable repr =>
287 infixr 6 `concat`, <>
289 Abstractable repr => Semigroupable repr => Semigroup a =>
290 repr a -> repr a -> repr a
291 (<>) x y = concat .@ x .@ y
293 -- ** Class 'Optionable'
294 class Optionable repr where
295 option :: repr a -> repr a
296 optional :: repr a -> repr (Maybe a)
297 option = liftDerived1 option
298 optional = liftDerived1 optional
300 FromDerived1 Optionable repr =>
303 FromDerived1 Optionable repr =>
304 repr a -> repr (Maybe a)
306 -- * Class 'Repeatable'
307 class Repeatable repr where
308 many0 :: repr a -> repr [a]
309 many1 :: repr a -> repr [a]
310 many0 = liftDerived1 many0
311 many1 = liftDerived1 many1
313 FromDerived1 Repeatable repr =>
316 FromDerived1 Repeatable repr =>
319 -- * Class 'Permutable'
320 class Permutable repr where
321 -- Use @TypeFamilyDependencies@ to help type-inference infer @(repr)@.
322 type Permutation (repr:: ReprKind) = (r :: ReprKind) | r -> repr
323 type Permutation repr = Permutation (Derived repr)
324 permutable :: Permutation repr a -> repr a
325 perm :: repr a -> Permutation repr a
326 noPerm :: Permutation repr ()
327 permWithDefault :: a -> repr a -> Permutation repr a
329 Eitherable repr => IsoFunctor repr => Permutable repr =>
330 repr a -> Permutation repr (Maybe a)
331 optionalPerm = permWithDefault Nothing Fun.. (<%>) (Iso Just fromJust)
335 ProductFunctor (Permutation repr) =>
337 Permutation repr b ->
338 Permutation repr (a, b)
339 x <&> y = perm x <.> y
347 ProductFunctor (Permutation repr) =>
349 Permutation repr b ->
350 Permutation repr (Maybe a, b)
351 x <?&> y = optionalPerm x <.> y
353 {-# INLINE (<?&>) #-}
360 ProductFunctor (Permutation repr) =>
362 Permutation repr b ->
363 Permutation repr ([a],b)
364 x <*&> y = permWithDefault [] (many1 x) <.> y
366 {-# INLINE (<*&>) #-}
373 ProductFunctor (Permutation repr) =>
375 Permutation repr b ->
376 Permutation repr ([a], b)
377 x <+&> y = perm (many1 x) <.> y
379 {-# INLINE (<+&>) #-}
381 -- * Class 'Routable'
382 class Routable repr where
383 (<!>) :: repr a -> repr b -> repr (a, b); infixr 4 <!>
384 (<!>) = liftDerived2 (<!>)
386 FromDerived2 Routable repr =>
387 repr a -> repr b -> repr (a, b)
389 -- | Like @(,)@ but @infixr@.
390 -- Mostly useful for clarity when using 'Routable'.
391 pattern (:!:) :: a -> b -> (a, b)
392 pattern a:!:b <- (a, b)
396 -- * Class 'Voidable'
397 -- | FIXME: this class should likely be removed
398 class Voidable repr where
399 void :: a -> repr a -> repr ()
400 void = liftDerived1 Fun.. void
402 FromDerived1 Voidable repr =>
403 a -> repr a -> repr ()
405 -- * Class 'Substractable'
406 class Substractable repr where
407 (<->) :: repr a -> repr b -> repr a; infixr 3 <->
408 (<->) = liftDerived2 (<->)
410 FromDerived2 Substractable repr =>
411 repr a -> repr b -> repr a