symparsec-2.0.0: src/Symparsec/Parser/Applicative.hs
{-# LANGUAGE UndecidableInstances #-}
-- | Type-level string parsers shaped like 'Applicative' functions.
module Symparsec.Parser.Applicative
( type (<*>), type Pure
, type LiftA2
, type (*>), type (<*)
) where
import Symparsec.Parser.Common
import Symparsec.Parser.Functor
import DeFun.Function ( type IdSym, type ConstSym )
-- | '<*>' for parsers. Sequence two parsers, left to right.
type (<*>) :: PParser (a ~> b) -> PParser a -> PParser b
infixl 4 <*>
data (<*>) l r s
type instance App (l <*> r) s = ApL r (l @@ s)
type ApL :: PParser a -> PReply (a ~> b) -> PReply b
type family ApL r rep where
ApL r ('Reply (OK fa) s) = (fa <$> r) @@ s
ApL r ('Reply (Err e) s) = 'Reply (Err e) s
-- | 'pure' for parsers. Non-consuming parser that just returns the given value.
type Pure :: a -> PParser a
data Pure a s
type instance App (Pure a) s = 'Reply (OK a) s
-- | 'liftA2' for parsers. Sequence two parsers, and combine their results with
-- a binary type function.
type LiftA2 :: (a ~> b ~> c) -> PParser a -> PParser b -> PParser c
type LiftA2 f l r = (f <$> l) <*> r
-- | '*>' for parsers. Sequence two parsers left to right, discarding the value
-- of the left parser.
type (*>) :: PParser a -> PParser b -> PParser b
infixl 4 *>
type l *> r = (IdSym <$ l) <*> r
-- | '<*' for parsers. Sequence two parsers left to right, discarding the value
-- of the right parser.
type (<*) :: PParser a -> PParser b -> PParser a
infixl 4 <*
type l <* r = LiftA2 ConstSym l r