1 -- The default type signature of type class methods are changed
2 -- to introduce a Liftable constraint and the same type class but on the 'Output' repr,
3 -- this setup avoids to define the method with boilerplate code when its default
4 -- definition with lift* and 'trans' does what is expected by an instance
5 -- of the type class. This is almost as explained in:
6 -- https://ro-che.info/articles/2016-02-03-finally-tagless-boilerplate
7 {-# LANGUAGE DefaultSignatures #-}
8 {-# LANGUAGE DeriveGeneric #-} -- For NFData instances
9 {-# LANGUAGE DeriveAnyClass #-} -- For NFData instances
10 {-# LANGUAGE DeriveLift #-} -- For TH.Lift (Exception tok)
11 {-# LANGUAGE PatternSynonyms #-} -- For Failure
12 {-# LANGUAGE StandaloneDeriving #-} -- For Show (Exception (InputToken inp))
13 {-# LANGUAGE InstanceSigs #-}
14 {-# LANGUAGE TemplateHaskell #-}
15 {-# LANGUAGE ViewPatterns #-} -- For unSomeFailure
16 -- | Semantic of the grammar combinators used to express parsers,
17 -- in the convenient tagless-final encoding.
18 module Symantic.Parser.Grammar.Combinators where
20 import Data.Proxy (Proxy(..))
21 import Control.Monad (Monad(..))
22 import Control.DeepSeq (NFData(..))
23 import GHC.Generics (Generic)
24 -- import Data.Set (Set)
25 -- import GHC.TypeLits (KnownSymbol)
26 import Data.Bool (Bool(..), not, (||))
27 import Data.Char (Char)
28 import Data.Either (Either(..))
29 import Data.Eq (Eq(..))
30 import Data.Ord (Ord(..))
31 import Data.Functor (Functor)
32 import Data.Functor.Identity (Identity(..))
33 import Data.Functor.Product (Product(..))
34 import Data.Function ((.), flip, id, const)
36 import Data.Kind (Type, Constraint)
37 import Data.Maybe (Maybe(..))
39 import Data.String (String)
40 import Text.Show (Show(..))
41 import Type.Reflection (Typeable, typeRep, eqTypeRep, (:~~:)(..), SomeTypeRep(..))
42 import qualified Data.Functor as Functor
43 import qualified Data.List as List
44 import qualified Data.Set as Set
45 import qualified Language.Haskell.TH as TH
46 import qualified Language.Haskell.TH.Syntax as TH
47 import qualified Prelude
49 import qualified Symantic.Typed.Trans as Sym
50 import qualified Symantic.Typed.Lang as Prod
51 import qualified Symantic.Typed.View
52 import Symantic.Parser.Grammar.Production
55 type ReprComb = Type -> Type
57 -- * Class 'CombAlternable'
58 class CombAlternable repr where
59 -- | @('alt' es l r)@ parses @(l)@ and return its return value or,
60 -- if it fails with an 'Exception' within @(es)@,
61 -- parses @(r)@ from where @(l)@ has left the input stream,
62 -- and returns its return value,
63 -- otherwise throw the 'Exception' again.
64 alt :: Exception -> repr a -> repr a -> repr a
65 throw :: ExceptionLabel -> repr a
66 -- | @('try' ra)@ records the input stream position,
67 -- then parses like @(ra)@ and either returns its value it it succeeds or fails
68 -- if it fails but with a reset of the input stream to the recorded position.
69 -- Generally used on the first alternative: @('try' rl '<|>' rr)@.
70 try :: repr a -> repr a
72 Sym.Liftable2 repr => CombAlternable (Sym.Output repr) =>
73 Exception -> repr a -> repr a -> repr a
75 Sym.Liftable repr => CombAlternable (Sym.Output repr) =>
76 ExceptionLabel -> repr a
78 Sym.Liftable1 repr => CombAlternable (Sym.Output repr) =>
81 throw = Sym.lift . throw
84 failure :: SomeFailure -> repr a
86 Sym.Liftable repr => CombAlternable (Sym.Output repr) =>
88 failure = Sym.lift . failure
90 -- | @(empty)@ parses nothing, always failing to return a value.
92 empty = failure (SomeFailure FailureEmpty)
94 data instance Failure CombAlternable
96 deriving (Eq, Ord, Show, TH.Lift, Generic, NFData)
98 -- ** Data family 'Failure'
99 -- | 'Failure's of the 'Grammar'.
100 -- This is an extensible data-type.
102 (comb :: ReprComb -> Constraint)
106 -- | Convenient utility to pattern-match a 'SomeFailure'.
107 pattern Failure :: Typeable comb => Failure comb -> SomeFailure
108 pattern Failure x <- (unSomeFailure -> Just x)
111 -- ** Type 'SomeFailure'
114 ({-Trans (Failure comb repr) repr,-}
116 , Show (Failure comb)
117 , TH.Lift (Failure comb)
118 , NFData (Failure comb)
121 SomeFailure (Failure comb {-repr a-})
122 instance Eq SomeFailure where
123 SomeFailure (_x::Failure x) == SomeFailure (_y::Failure y) =
124 case typeRep @x `eqTypeRep` typeRep @y of
127 instance Ord SomeFailure where
128 SomeFailure (_x::Failure x) `compare` SomeFailure (_y::Failure y) =
129 SomeTypeRep (typeRep @x) `compare`
130 SomeTypeRep (typeRep @y)
131 instance Show SomeFailure where
132 showsPrec p (SomeFailure x) = showsPrec p x
133 instance TH.Lift SomeFailure where
134 liftTyped (SomeFailure x) = [|| SomeFailure $$(TH.liftTyped x) ||]
135 instance NFData SomeFailure where
136 rnf (SomeFailure x) = rnf x
139 instance Trans (SomeFailure repr) repr where
140 trans (SomeFailure x) = trans x
143 -- | @(unSomeFailure c :: 'Maybe' ('Failure' comb repr a))@
144 -- extract the data-constructor from the given 'SomeFailure'
145 -- iif. it belongs to the @('Failure' comb repr a)@ data-instance.
146 unSomeFailure :: forall comb. Typeable comb => SomeFailure -> Maybe (Failure comb)
147 unSomeFailure (SomeFailure (c::Failure c)) =
148 case typeRep @comb `eqTypeRep` typeRep @c of
152 -- ** Type 'Exception'
154 = ExceptionLabel ExceptionLabel
156 deriving (Eq, Ord, Show, TH.Lift, Generic, NFData)
157 type ExceptionLabel = String
158 -- type Exceptions = Set Exception
160 -- | Like @('<|>')@ but with different returning types for the alternatives,
161 -- and a return value wrapped in an 'Either' accordingly.
162 (<+>) :: CombApplicable repr => CombAlternable repr => repr a -> repr b -> repr (Either a b)
163 p <+> q = Prod.left <$> p <|> Prod.right <$> q
165 (<|>) :: CombAlternable repr => repr a -> repr a -> repr a
166 (<|>) = alt ExceptionFailure
170 optionally :: CombApplicable repr => CombAlternable repr => repr a -> Production b -> repr b
171 optionally p x = p $> x <|> pure x
173 optional :: CombApplicable repr => CombAlternable repr => repr a -> repr ()
174 optional = flip optionally Prod.unit
176 option :: CombApplicable repr => CombAlternable repr => Production a -> repr a -> repr a
177 option x p = p <|> pure x
179 choice :: CombAlternable repr => [repr a] -> repr a
180 choice = List.foldr (<|>) empty
181 -- FIXME: Here hlint suggests to use Data.Foldable.asum,
182 -- but at this point there is no asum for our own (<|>)
184 maybeP :: CombApplicable repr => CombAlternable repr => repr a -> repr (Maybe a)
185 maybeP p = option Prod.nothing (Prod.just <$> p)
187 manyTill :: CombApplicable repr => CombAlternable repr => repr a -> repr b -> repr [a]
188 manyTill p end = let go = end $> Prod.nil <|> p <:> go in go
190 -- * Class 'CombApplicable'
191 -- | This is like the usual 'Functor' and 'Applicative' type classes
192 -- from the @base@ package, but using @('Production' a)@ instead of just @(a)@
193 -- to be able to use and pattern match on some usual terms of type @(a)@ (like 'Prod.id')
194 -- and thus apply some optimizations.
195 -- @(repr)@, for "representation", is the usual tagless-final abstraction
196 -- over the many semantics that this syntax (formed by the methods
197 -- of type class like this one) will be interpreted.
198 class CombApplicable repr where
199 -- | @(a2b '<$>' ra)@ parses like @(ra)@ but maps its returned value with @(a2b)@.
200 (<$>) :: Production (a -> b) -> repr a -> repr b
201 (<$>) f = (pure f <*>)
202 (<$>%) :: (Production a -> Production b) -> repr a -> repr b
203 a2b <$>% ma = Prod.lam a2b <$> ma
205 -- | Like '<$>' but with its arguments 'flip'-ped.
206 (<&>) :: repr a -> Production (a -> b) -> repr b
209 -- | @(a '<$' rb)@ parses like @(rb)@ but discards its returned value by replacing it with @(a)@.
210 (<$) :: Production a -> repr b -> repr a
213 -- | @(ra '$>' b)@ parses like @(ra)@ but discards its returned value by replacing it with @(b)@.
214 ($>) :: repr a -> Production b -> repr b
217 -- | @('pure' a)@ parses the empty string, always succeeding in returning @(a)@.
218 pure :: Production a -> repr a
220 Sym.Liftable repr => CombApplicable (Sym.Output repr) =>
221 Production a -> repr a
222 pure = Sym.lift . pure
224 -- | @(ra2b '<*>' ra)@ parses sequentially @(ra2b)@ and then @(ra)@,
225 -- and returns the application of the function returned by @(ra2b)@
226 -- to the value returned by @(ra)@.
227 (<*>) :: repr (a -> b) -> repr a -> repr b
229 Sym.Liftable2 repr => CombApplicable (Sym.Output repr) =>
230 repr (a -> b) -> repr a -> repr b
231 (<*>) = Sym.lift2 (<*>)
233 -- | @(ra '<*' rb)@ parses sequentially @(ra)@ and then @(rb)@,
234 -- and returns like @(ra)@, discarding the return value of @(rb)@.
235 (<*) :: repr a -> repr b -> repr a
236 (<*) = liftA2 Prod.const
238 -- | @(ra '*>' rb)@ parses sequentially @(ra)@ and then @(rb)@,
239 -- and returns like @(rb)@, discarding the return value of @(ra)@.
240 (*>) :: repr a -> repr b -> repr b
241 x *> y = (Prod.id <$ x) <*> y
243 -- | Like '<*>' but with its arguments 'flip'-ped.
244 (<**>) :: repr a -> repr (a -> b) -> repr b
245 (<**>) = liftA2 (Prod.flip Prod..@ (Prod.$))
247 (<**>) :: repr a -> repr (a -> b) -> repr b
248 (<**>) = liftA2 (\a f -> f a)
250 -- | @('liftA2' a2b2c ra rb)@ parses sequentially @(ra)@ and then @(rb)@,
251 -- and returns the application of @(a2b2c)@ to the values returned by those parsers.
252 liftA2 :: Production (a -> b -> c) -> repr a -> repr b -> repr c
253 liftA2 f x = (<*>) (f <$> x)
255 infixl 4 <*>, <*, *>, <**>
256 data instance Failure CombApplicable
261 (<:>) :: CombApplicable repr => repr a -> repr [a] -> repr [a]
262 (<:>) = liftA2 Prod.cons
264 sequence :: CombApplicable repr => [repr a] -> repr [a]
265 sequence = List.foldr (<:>) (pure Prod.nil)
267 traverse :: CombApplicable repr => (a -> repr b) -> [a] -> repr [b]
268 traverse f = sequence . List.map f
269 -- FIXME: Here hlint suggests to use Control.Monad.mapM,
270 -- but at this point there is no mapM for our own sequence
272 repeat :: CombApplicable repr => Int -> repr a -> repr [a]
273 repeat n p = traverse (const p) [1..n]
275 between :: CombApplicable repr => repr o -> repr c -> repr a -> repr a
276 between open close p = open *> p <* close
278 void :: CombApplicable repr => repr a -> repr ()
281 unit :: CombApplicable repr => repr ()
282 unit = pure Prod.unit
284 -- * Class 'CombFoldable'
285 class CombFoldable repr where
286 chainPre :: repr (a -> a) -> repr a -> repr a
287 chainPost :: repr a -> repr (a -> a) -> repr a
290 Sym.Liftable2 repr => CombFoldable (Sym.Output repr) =>
291 repr (a -> a) -> repr a -> repr a
293 Sym.Liftable2 repr => CombFoldable (Sym.Output repr) =>
294 repr a -> repr (a -> a) -> repr a
295 chainPre = Sym.lift2 chainPre
296 chainPost = Sym.lift2 chainPost
299 CombApplicable repr =>
300 CombAlternable repr =>
301 repr (a -> a) -> repr a -> repr a
303 CombApplicable repr =>
304 CombAlternable repr =>
305 repr a -> repr (a -> a) -> repr a
306 chainPre op p = go <*> p where go = (Prod..) <$> op <*> go <|> pure Prod.id
307 chainPost p op = p <**> go where go = (Prod..) <$> op <*> go <|> pure Prod.id
309 chainPre op p = flip (foldr ($)) <$> many op <*> p
310 chainPost p op = foldl' (flip ($)) <$> p <*> many op
312 data instance Failure CombFoldable
315 conditional :: CombSelectable repr => [(Production (a -> Bool), repr b)] -> repr a -> repr b -> repr b
316 conditional cs p def = match p fs qs def
317 where (fs, qs) = List.unzip cs
322 CombApplicable repr => CombFoldable repr =>
323 Production (a -> b -> b) -> Production b -> repr a -> repr b
324 pfoldr f k p = chainPre (f <$> p) (pure k)
327 CombApplicable repr => CombFoldable repr =>
328 Production (a -> b -> b) -> Production b -> repr a -> repr b
329 pfoldr1 f k p = f <$> p <*> pfoldr f k p
332 CombApplicable repr => CombFoldable repr =>
333 Production (b -> a -> b) -> Production b -> repr a -> repr b
334 pfoldl f k p = chainPost (pure k) ((Prod.flip <$> pure f) <*> p)
337 CombApplicable repr => CombFoldable repr =>
338 Production (b -> a -> b) -> Production b -> repr a -> repr b
339 pfoldl1 f k p = chainPost (f <$> pure k <*> p) ((Prod.flip <$> pure f) <*> p)
343 CombApplicable repr => CombFoldable repr =>
344 Production (a -> b) -> repr a -> repr (b -> a -> b) -> repr b
345 chainl1' f p op = chainPost (f <$> p) (Prod.flip <$> op <*> p)
348 CombApplicable repr => CombFoldable repr =>
349 repr a -> repr (a -> a -> a) -> repr a
350 chainl1 = chainl1' Prod.id
353 chainr1' :: ParserOps rep => rep (a -> b) -> repr a -> repr (a -> b -> b) -> repr b
354 chainr1' f p op = newRegister_ Prod.id $ \acc ->
355 let go = bind p $ \x ->
356 modify acc (Prod.flip (Prod..@) <$> (op <*> x)) *> go
360 chainr1 :: repr a -> repr (a -> a -> a) -> repr a
361 chainr1 = chainr1' Prod.id
363 chainr :: repr a -> repr (a -> a -> a) -> Production a -> repr a
364 chainr p op x = option x (chainr1 p op)
368 CombApplicable repr => CombAlternable repr => CombFoldable repr =>
369 repr a -> repr (a -> a -> a) -> Production a -> repr a
370 chainl p op x = option x (chainl1 p op)
372 -- Derived Combinators
374 CombApplicable repr => CombFoldable repr =>
376 many = pfoldr Prod.cons Prod.nil
379 CombApplicable repr => CombFoldable repr =>
380 Int -> repr a -> repr [a]
381 manyN n p = List.foldr (const (p <:>)) (many p) [1..n]
384 CombApplicable repr => CombFoldable repr =>
389 CombApplicable repr => CombFoldable repr =>
391 --skipMany p = let skipManyp = p *> skipManyp <|> unit in skipManyp
392 skipMany = void . pfoldl Prod.const Prod.unit -- the void here will encourage the optimiser to recognise that the register is unused
395 CombApplicable repr => CombFoldable repr =>
396 Int -> repr a -> repr ()
397 skipManyN n p = List.foldr (const (p *>)) (skipMany p) [1..n]
400 CombApplicable repr => CombFoldable repr =>
402 skipSome = skipManyN 1
405 CombApplicable repr => CombAlternable repr => CombFoldable repr =>
406 repr a -> repr b -> repr [a]
407 sepBy p sep = option Prod.nil (sepBy1 p sep)
410 CombApplicable repr => CombAlternable repr => CombFoldable repr =>
411 repr a -> repr b -> repr [a]
412 sepBy1 p sep = p <:> many (sep *> p)
415 CombApplicable repr => CombAlternable repr => CombFoldable repr =>
416 repr a -> repr b -> repr [a]
417 endBy p sep = many (p <* sep)
420 CombApplicable repr => CombAlternable repr => CombFoldable repr =>
421 repr a -> repr b -> repr [a]
422 endBy1 p sep = some (p <* sep)
425 CombApplicable repr => CombAlternable repr => CombFoldable repr =>
426 repr a -> repr b -> repr [a]
427 sepEndBy p sep = option Prod.nil (sepEndBy1 p sep)
430 CombApplicable repr => CombAlternable repr => CombFoldable repr =>
431 repr a -> repr b -> repr [a]
433 let seb1 = p <**> (sep *> (Prod.flip Prod..@ Prod.cons <$> option Prod.nil seb1)
434 <|> pure (Prod.flip Prod..@ Prod.cons Prod..@ Prod.nil))
438 sepEndBy1 :: repr a -> repr b -> repr [a]
439 sepEndBy1 p sep = newRegister_ Prod.id $ \acc ->
440 let go = modify acc ((Prod.flip (Prod..)) Prod..@ Prod.cons <$> p)
441 *> (sep *> (go <|> get acc) <|> get acc)
442 in go <*> pure Prod.nil
445 -- * Class 'CombMatchable'
446 class CombMatchable repr where
448 Eq a => repr a -> [Production (a -> Bool)] -> [repr b] -> repr b -> repr b
449 default conditional ::
450 Sym.Unliftable repr => Sym.Liftable1 repr => CombMatchable (Sym.Output repr) =>
451 Eq a => repr a -> [Production (a -> Bool)] -> [repr b] -> repr b -> repr b
452 conditional a ps bs = Sym.lift1 (conditional (Sym.unlift a) ps (Sym.unlift Functor.<$> bs))
454 match :: Eq a => repr a -> [Production a] -> (Production a -> repr b) -> repr b -> repr b
455 match a as a2b = conditional a ((Prod.equal Prod..@) Functor.<$> as) (a2b Functor.<$> as)
456 -- match a as a2b = conditional a (((Prod.eq Prod..@ Prod.qual) Prod..@) Functor.<$> as) (a2b Functor.<$> as)
457 data instance Failure CombMatchable
459 -- * Class 'CombSatisfiable'
460 class CombSatisfiable tok repr where
461 -- | Like 'satisfyOrFail' but with no custom failure.
462 satisfy :: Production (tok -> Bool) -> repr tok
463 satisfy = satisfyOrFail Set.empty
464 -- | Like 'satisfy' but with a custom set of 'SomeFailure's.
467 Production (tok -> Bool) -> repr tok
468 default satisfyOrFail ::
469 Sym.Liftable repr => CombSatisfiable tok (Sym.Output repr) =>
471 Production (tok -> Bool) -> repr tok
472 satisfyOrFail fs = Sym.lift . satisfyOrFail fs
474 data instance Failure (CombSatisfiable tok)
476 | FailureHorizon Int -- FIXME: use Natural?
477 | FailureLabel String
479 deriving (Eq, Show, Typeable, Generic, NFData)
480 -- | Global 'TH.Name' to refer to the @(InputToken inp)@ type
481 -- from TemplateHaskell code.
482 inputTokenProxy :: TH.Name
483 inputTokenProxy = TH.mkName "inputToken"
484 instance TH.Lift tok => TH.Lift (Failure (CombSatisfiable tok)) where
485 liftTyped :: forall m. TH.Quote m => Failure (CombSatisfiable tok) -> TH.Code m (Failure (CombSatisfiable tok))
488 $$(let inputToken :: TH.Code m (Proxy tok) =
489 TH.unsafeCodeCoerce (return (TH.VarE inputTokenProxy))
491 (Proxy :: Proxy tok') ->
493 FailureAny -> [|| FailureAny @tok' ||]
494 FailureHorizon h -> [|| FailureHorizon @tok' h ||]
495 FailureLabel lbl -> [|| FailureLabel @tok' lbl ||]
496 FailureToken tok -> [|| FailureToken $$(TH.liftTyped tok) ||]
501 CombApplicable repr =>
502 CombSatisfiable Char repr =>
504 char c = satisfyOrFail
505 (Set.singleton (SomeFailure (FailureToken c)))
506 ((Prod.equal Prod..@ Prod.char c))
509 item :: forall tok repr.
510 Eq tok => Show tok => Typeable tok => TH.Lift tok => NFData tok =>
511 CombSatisfiable tok repr => repr tok
513 (Set.singleton (SomeFailure (FailureAny @tok)))
514 (Prod.const Prod..@ Prod.bool True)
517 CombAlternable repr =>
518 CombSatisfiable Char repr =>
523 CombApplicable repr => CombAlternable repr =>
524 CombSatisfiable Char repr =>
525 [Char] -> repr [Char]
526 string = try . traverse char
529 Eq tok => Show tok => Typeable tok => TH.Lift tok => NFData tok =>
530 CombSatisfiable tok repr =>
532 oneOf ts = satisfyOrFail
533 (Set.fromList (SomeFailure . FailureToken Functor.<$> ts))
536 [||\t -> $$(ofChars ts [||t||])||])
539 TH.Lift tok => Eq tok =>
540 CombSatisfiable tok repr =>
542 noneOf cs = satisfy (production
543 (not . (`List.elem` cs))
544 [||\c -> not $$(ofChars cs [||c||])||])
547 TH.Lift tok => Eq tok =>
548 {-alternatives-}[tok] ->
549 {-input-}TH.CodeQ tok ->
551 ofChars = List.foldr (\tok acc ->
552 \inp -> [|| tok == $$inp || $$(acc inp) ||])
556 CombAlternable repr =>
557 CombApplicable repr =>
558 CombSatisfiable Char repr =>
559 CombLookable repr => repr ()
560 more = look (void (item @Char))
563 TH.Lift tok => Show tok => Eq tok => Typeable tok =>
564 CombAlternable repr =>
565 CombApplicable repr =>
566 CombSatisfiable tok repr =>
568 token tok = satisfy (Prod.equal Prod..@ Prod.constant tok) $> Prod.constant tok
569 -- token tok = satisfy [ExceptionToken tok] (Prod.eq Prod..@ Prod.qual Prod..@ Prod.char tok) $> Prod.char tok
572 TH.Lift tok => Eq tok => Show tok => Typeable tok =>
573 CombApplicable repr => CombAlternable repr =>
574 CombSatisfiable tok repr => [tok] -> repr [tok]
575 tokens = try . traverse token
577 -- * Class 'CombSelectable'
578 class CombSelectable repr where
579 branch :: repr (Either a b) -> repr (a -> c) -> repr (b -> c) -> repr c
581 Sym.Liftable3 repr => CombSelectable (Sym.Output repr) =>
582 repr (Either a b) -> repr (a -> c) -> repr (b -> c) -> repr c
583 branch = Sym.lift3 branch
584 data instance Failure CombSelectable
586 -- * Class 'CombLookable'
587 class CombLookable repr where
588 look :: repr a -> repr a
589 negLook :: repr a -> repr ()
590 default look :: Sym.Liftable1 repr => CombLookable (Sym.Output repr) => repr a -> repr a
591 default negLook :: Sym.Liftable1 repr => CombLookable (Sym.Output repr) => repr a -> repr ()
592 look = Sym.lift1 look
593 negLook = Sym.lift1 negLook
597 default eof :: Sym.Liftable repr => CombLookable (Sym.Output repr) => repr ()
598 -- eof = negLook (satisfy @Char (Prod.const Prod..@ Prod.bool True))
600 data instance Failure CombLookable
602 deriving (Eq, Show, Typeable, TH.Lift, Generic, NFData)
604 -- Composite Combinators
605 -- someTill :: repr a -> repr b -> repr [a]
606 -- someTill p end = negLook end *> (p <:> manyTill p end)
609 constp :: CombApplicable repr => repr a -> repr (b -> a)
610 constp = (Prod.const <$>)
615 (>>) :: CombApplicable repr => repr a -> repr b -> repr b
618 -- Monoidal Operations
621 (<~>) :: CombApplicable repr => repr a -> repr b -> repr (a, b)
622 (<~>) = liftA2 (Prod.runtime (,))
625 (<~) :: CombApplicable repr => repr a -> repr b -> repr a
629 (~>) :: CombApplicable repr => repr a -> repr b -> repr b
634 CombApplicable repr =>
635 Production (a -> b -> c) -> repr a -> repr b -> repr c
636 liftA2 f x = (<*>) (fmap f x)
639 CombApplicable repr =>
640 Production (a -> b -> c -> d) -> repr a -> repr b -> repr c -> repr d
641 liftA3 f a b c = liftA2 f a b <*> c
646 -- Combinators interpreters for 'Sym.Any'.
647 instance CombApplicable repr => CombApplicable (Sym.Any repr)
648 instance CombSatisfiable repr => CombSatisfiable (Sym.Any repr)
649 instance CombAlternable repr => CombAlternable (Sym.Any repr)
650 instance CombSelectable repr => CombSelectable (Sym.Any repr)
651 instance CombMatchable repr => CombMatchable (Sym.Any repr)
652 instance CombLookable repr => CombLookable (Sym.Any repr)
653 instance CombFoldable repr => CombFoldable (Sym.Any repr)