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 Data.Function as Fun
17 import Symantic.Derive
19 import Symantic.CurryN
22 type ReprKind = Type -> Type
24 -- * Class 'Abstractable'
25 class Abstractable repr where
26 -- | Application, aka. unabstract.
27 (.@) :: repr (a->b) -> repr a -> repr b; infixl 9 .@
28 -- | Lambda term abstraction, in HOAS (Higher-Order Abstract Syntax) style.
29 lam :: (repr a -> repr b) -> repr (a->b)
30 -- | Like 'lam' but whose argument is used only once,
31 -- hence safe to beta-reduce (inline) without duplicating work.
32 lam1 :: (repr a -> repr b) -> repr (a->b)
33 const :: repr (a -> b -> a)
34 flip :: repr ((a -> b -> c) -> b -> a -> c)
36 (.) :: repr ((b->c) -> (a->b) -> a -> c); infixr 9 .
37 ($) :: repr ((a->b) -> a -> b); infixr 0 $
38 var :: repr a -> repr a
39 (.@) = liftDerived2 (.@)
40 lam f = liftDerived (lam (derive Fun.. f Fun.. liftDerived))
41 lam1 f = liftDerived (lam1 (derive Fun.. f Fun.. liftDerived))
42 const = liftDerived const
43 flip = liftDerived flip
47 var = liftDerived1 var
49 FromDerived2 Abstractable repr =>
50 repr (a->b) -> repr a -> repr b
52 FromDerived Abstractable repr => Derivable repr =>
53 (repr a -> repr b) -> repr (a->b)
55 FromDerived Abstractable repr => Derivable repr =>
56 (repr a -> repr b) -> repr (a->b)
58 FromDerived Abstractable repr =>
61 FromDerived Abstractable repr =>
62 repr ((a -> b -> c) -> b -> a -> c)
64 FromDerived Abstractable repr =>
67 FromDerived Abstractable repr =>
68 repr ((b->c) -> (a->b) -> a -> c)
70 FromDerived Abstractable repr =>
71 repr ((a->b) -> a -> b)
73 FromDerived1 Abstractable repr =>
76 -- * Class 'Anythingable'
77 class Anythingable repr where
78 anything :: repr a -> repr a
81 -- * Class 'Bottomable'
82 class Bottomable repr where
85 -- * Class 'Constantable'
86 class Constantable c repr where
87 constant :: c -> repr c
88 constant = liftDerived Fun.. constant
90 FromDerived (Constantable c) repr =>
93 bool :: Constantable Bool repr => Bool -> repr Bool
95 char :: Constantable Char repr => Char -> repr Char
97 unit :: Constantable () repr => repr ()
98 unit = constant @() ()
100 -- * Class 'Eitherable'
101 class Eitherable repr where
102 left :: repr (l -> Either l r)
103 right :: repr (r -> Either l r)
104 left = liftDerived left
105 right = liftDerived right
107 FromDerived Eitherable repr =>
108 repr (l -> Either l r)
110 FromDerived Eitherable repr =>
111 repr (r -> Either l r)
113 -- * Class 'Equalable'
114 class Equalable repr where
115 equal :: Eq a => repr (a -> a -> Bool)
116 equal = liftDerived equal
118 FromDerived Equalable repr =>
119 Eq a => repr (a -> a -> Bool)
122 (==) :: (Abstractable repr, Equalable repr, Eq a) => repr (a -> a -> Bool)
123 (==) = lam (\x -> lam (\y -> equal .@ x .@ y))
125 -- * Class 'IfThenElseable'
126 class IfThenElseable repr where
127 ifThenElse :: repr Bool -> repr a -> repr a -> repr a
128 ifThenElse = liftDerived3 ifThenElse
129 default ifThenElse ::
130 FromDerived3 IfThenElseable repr =>
131 repr Bool -> repr a -> repr a -> repr a
133 -- * Class 'Listable'
134 class Listable repr where
135 cons :: repr (a -> [a] -> [a])
137 cons = liftDerived cons
138 nil = liftDerived nil
140 FromDerived Listable repr =>
141 repr (a -> [a] -> [a])
143 FromDerived Listable repr =>
146 -- * Class 'Maybeable'
147 class Maybeable repr where
148 nothing :: repr (Maybe a)
149 just :: repr (a -> Maybe a)
150 nothing = liftDerived nothing
151 just = liftDerived just
153 FromDerived Maybeable repr =>
156 FromDerived Maybeable repr =>
159 -- * Class 'IsoFunctor'
160 class IsoFunctor repr where
161 (<%>) :: Iso a b -> repr a -> repr b
162 (<%>) iso = liftDerived1 (iso <%>)
164 FromDerived1 IsoFunctor repr =>
165 Iso a b -> repr a -> repr b
168 data Iso a b = Iso { a2b :: a->b, b2a :: b->a }
170 -- * Class 'ProductFunctor'
171 class ProductFunctor repr where
172 (<.>) :: repr a -> repr b -> repr (a, b)
173 (<.>) = liftDerived2 (<.>)
175 FromDerived2 ProductFunctor repr =>
176 repr a -> repr b -> repr (a, b)
178 -- * Class 'SumFunctor'
179 class SumFunctor repr where
180 (<+>) :: repr a -> repr b -> repr (Either a b)
181 (<+>) = liftDerived2 (<+>)
183 FromDerived2 SumFunctor repr =>
184 repr a -> repr b -> repr (Either a b)
186 -- * Class 'AlternativeFunctor'
187 class AlternativeFunctor repr where
188 (<|>) :: repr a -> repr a -> repr a
189 (<|>) = liftDerived2 (<|>)
191 FromDerived2 AlternativeFunctor repr =>
192 repr a -> repr a -> repr a
194 -- * Class 'Dicurryable'
195 class Dicurryable repr where
199 (args-..->a) -> -- construction
200 (a->Tuples args) -> -- destruction
201 repr (Tuples args) ->
203 dicurry args constr destr = liftDerived1 (dicurry args constr destr)
205 FromDerived1 Dicurryable repr =>
210 repr (Tuples args) ->
219 Tuples args ~ EoT (ADT a) =>
220 (args ~ Args (args-..->a)) =>
222 repr (Tuples args) ->
224 construct f = dicurry (Proxy::Proxy args) f eotOfadt
232 repr (EoT (ADT adt)) ->
234 adt = (<%>) (Iso adtOfeot eotOfadt)
236 -- ** Class 'Emptyable'
237 class Emptyable repr where
239 empty = liftDerived empty
241 FromDerived Emptyable repr =>
244 -- ** Class 'Optionable'
245 class Optionable repr where
246 option :: repr a -> repr a
247 optional :: repr a -> repr (Maybe a)
248 option = liftDerived1 option
249 optional = liftDerived1 optional
251 FromDerived1 Optionable repr =>
254 FromDerived1 Optionable repr =>
255 repr a -> repr (Maybe a)
257 -- * Class 'Repeatable'
258 class Repeatable repr where
259 many0 :: repr a -> repr [a]
260 many1 :: repr a -> repr [a]
261 many0 = liftDerived1 many0
262 many1 = liftDerived1 many1
264 FromDerived1 Repeatable repr =>
267 FromDerived1 Repeatable repr =>
270 -- * Class 'Permutable'
271 class Permutable repr where
272 -- Use @TypeFamilyDependencies@ to help type-inference infer @(repr)@.
273 type Permutation (repr:: ReprKind) = (r :: ReprKind) | r -> repr
274 type Permutation repr = Permutation (Derived repr)
275 permutable :: Permutation repr a -> repr a
276 perm :: repr a -> Permutation repr a
277 noPerm :: Permutation repr ()
278 permWithDefault :: a -> repr a -> Permutation repr a
280 Eitherable repr => IsoFunctor repr => Permutable repr =>
281 repr a -> Permutation repr (Maybe a)
282 optionalPerm = permWithDefault Nothing Fun.. (<%>) (Iso Just fromJust)
286 ProductFunctor (Permutation repr) =>
288 Permutation repr b ->
289 Permutation repr (a, b)
290 x <&> y = perm x <.> y
296 ProductFunctor (Permutation repr) =>
298 Permutation repr b ->
299 Permutation repr (Maybe a, b)
300 x <?&> y = optionalPerm x <.> y
307 ProductFunctor (Permutation repr) =>
309 Permutation repr b ->
310 Permutation repr ([a],b)
311 x <*&> y = permWithDefault [] (many1 x) <.> y
318 ProductFunctor (Permutation repr) =>
320 Permutation repr b ->
321 Permutation repr ([a],b)
322 x <+&> y = perm (many1 x) <.> y
330 {-# INLINE (<?&>) #-}
331 {-# INLINE (<*&>) #-}
332 {-# INLINE (<+&>) #-}
334 -- * Class 'Routable'
335 class Routable repr where
336 (<!>) :: repr a -> repr b -> repr (a, b)
337 (<!>) = liftDerived2 (<!>)
339 FromDerived2 Routable repr =>
340 repr a -> repr b -> repr (a,b)
342 -- | Like @(,)@ but @infixr@.
343 -- Mostly useful for clarity when using 'Routable'.
344 pattern (:!:) :: a -> b -> (a,b)
345 pattern a:!:b <- (a,b)
349 -- * Class 'Voidable'
350 -- | FIXME: this class should likely be removed
351 class Voidable repr where
352 void :: a -> repr a -> repr ()
353 void = liftDerived1 Fun.. void
355 FromDerived1 Voidable repr =>
356 a -> repr a -> repr ()
358 -- * Class 'Substractable'
359 class Substractable repr where
360 (<->) :: repr a -> repr b -> repr a
361 (<->) = liftDerived2 (<->)
363 FromDerived2 Substractable repr =>
364 repr a -> repr b -> repr a