packages feed

parser-combinators 1.0.0 → 1.3.1

raw patch · 12 files changed

Files

CHANGELOG.md view
@@ -1,3 +1,57 @@+## Parser combinators 1.3.1++* Compiles with [MicroHs](https://github.com/augustss/MicroHs).++## Parser combinators 1.3.0++* Changed the `Control.Applicative.Permutations` module to only require+  `Applicative` and not `Monad`. This module is the least restrictive and works+  with parsers which are not `Monad`s.++* Added the `Control.Monad.Permutations` module. This module may be+  substantially more efficient for some parsers which are `Monad`s.++* Corrected how permutation parsers intercalate effects and components; parsing+  an effect requires that a component immediately follows or else a parse error+  will result.++## Parser combinators 1.2.1++* The tests in `parser-combinators-tests` now work with Megaparsec 8.++* Dropped support for GHC 8.2.++## Parser combinators 1.2.0++* Added `manyTill_` and `someTill_` combinators which work like the older+  `manyTill` and `someTill` except they also return the result of the `end`+  parser.++* Dropped support for GHC 8.0.++## Parser combinators 1.1.0++* Added support for ternary operators; see `TernR` in+  `Control.Monad.Combinators.Expr`.++## Parser combinators 1.0.3++* Dropped support for GHC 7.10.++* Added a test suite as a separate package called+  `parser-combinators-tests`.++## Parser combinators 1.0.2++* Defined `liftA2` for `Permutation` manually. The new definition should be+  more efficient.++* Made inner `Maybe` field in `Permutation` strict.++## Parser combinators 1.0.1++* Cosmetic changes in the source code.+ ## Parser combinators 1.0.0  * Added the `Control.Monad.Combinators.Expr` module.
Control/Applicative/Combinators.hs view
@@ -1,6 +1,9 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE TupleSections #-}+ -- | -- Module      :  Control.Applicative.Combinators--- Copyright   :  © 2017–2018 Mark Karpov+-- Copyright   :  © 2017–present Mark Karpov -- License     :  BSD 3 clause -- -- Maintainer  :  Mark Karpov <markkarpov92@gmail.com>@@ -41,53 +44,49 @@ -- backtrack in order for the alternative branch of parsing to be tried. -- Thus it is the responsibility of the programmer to wrap more complex, -- composite parsers in @try@ to achieve correct behavior.--{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE CPP          #-}- module Control.Applicative.Combinators   ( -- * Re-exports from "Control.Applicative"-    (<|>)+    (<|>),     -- $assocbo-  , many+    many,     -- $many-  , some+    some,     -- $some-  , optional+    optional,     -- $optional-  , empty+    empty,     -- $empty      -- * Original combinators-  , between-  , choice-  , count-  , count'-  , eitherP-  , endBy-  , endBy1-  , manyTill-  , someTill-  , option-  , sepBy-  , sepBy1-  , sepEndBy-  , sepEndBy1-  , skipMany-  , skipSome-  , skipCount-  , skipManyTill-  , skipSomeTill )+    between,+    choice,+    count,+    count',+    eitherP,+    endBy,+    endBy1,+    manyTill,+    manyTill_,+    someTill,+    someTill_,+    option,+    sepBy,+    sepBy1,+    sepEndBy,+    sepEndBy1,+    skipMany,+    skipSome,+    skipCount,+    skipManyTill,+    skipSomeTill,+  ) where -import Control.Applicative-import Data.Foldable--#if MIN_VERSION_base(4,9,0)+-- MicroHs has @Control.Applicative.asum :: Alternative f => [f a] -> f a@+-- so we use @Data.Foldable.asum@+import Control.Applicative hiding (asum) import Control.Monad (replicateM, replicateM_)-#elif !MIN_VERSION_base(4,8,0)-import Data.Traversable (sequenceA)-#endif+import Data.Foldable (asum)  ---------------------------------------------------------------------------- -- Re-exports from "Control.Applicative"@@ -135,8 +134,7 @@ -- Returns the value returned by @p@. -- -- > braces = between (symbol "{") (symbol "}")--between :: Applicative m => m open -> m close -> m a -> m a+between :: (Applicative m) => m open -> m close -> m a -> m a between open close p = open *> p <* close {-# INLINE between #-} @@ -144,7 +142,6 @@ -- until one of them succeeds. Returns the value of the succeeding parser. -- -- > choice = asum- choice :: (Foldable f, Alternative m) => f (m a) -> m a choice = asum {-# INLINE choice #-}@@ -156,13 +153,8 @@ -- > count = replicateM -- -- See also: 'skipCount', 'count''.--count :: Applicative m => Int -> m a -> m [a]-#if MIN_VERSION_base(4,9,0)+count :: (Applicative m) => Int -> m a -> m [a] count = replicateM-#else-count n p = sequenceA (replicate n p)-#endif {-# INLINE count #-}  -- | @'count'' m n p@ parses from @m@ to @n@ occurrences of @p@. If @n@ is@@ -173,21 +165,19 @@ -- as if it were equal to zero. -- -- See also: 'skipCount', 'count'.--count' :: Alternative m => Int -> Int -> m a -> m [a]+count' :: (Alternative m) => Int -> Int -> m a -> m [a] count' m' n' p = go m' n'   where     go !m !n       | n <= 0 || m > n = pure []-      | m > 0           = liftA2 (:) p (go (m - 1) (n - 1))-      | otherwise       = liftA2 (:) p (go 0 (n - 1)) <|> pure []+      | m > 0 = liftA2 (:) p (go (m - 1) (n - 1))+      | otherwise = liftA2 (:) p (go 0 (n - 1)) <|> pure [] {-# INLINE count' #-}  -- | Combine two alternatives. -- -- > eitherP a b = (Left <$> a) <|> (Right <$> b)--eitherP :: Alternative m => m a -> m b -> m (Either a b)+eitherP :: (Alternative m) => m a -> m b -> m (Either a b) eitherP a b = (Left <$> a) <|> (Right <$> b) {-# INLINE eitherP #-} @@ -195,38 +185,64 @@ -- ended by @sep@. Returns a list of values returned by @p@. -- -- > cStatements = cStatement `endBy` semicolon--endBy :: Alternative m => m a -> m sep -> m [a]+endBy :: (Alternative m) => m a -> m sep -> m [a] endBy p sep = many (p <* sep) {-# INLINE endBy #-}  -- | @'endBy1' p sep@ parses /one/ or more occurrences of @p@, separated and -- ended by @sep@. Returns a list of values returned by @p@.--endBy1 :: Alternative m => m a -> m sep -> m [a]+endBy1 :: (Alternative m) => m a -> m sep -> m [a] endBy1 p sep = some (p <* sep) {-# INLINE endBy1 #-}  -- | @'manyTill' p end@ applies parser @p@ /zero/ or more times until parser--- @end@ succeeds. Returns the list of values returned by @p@.+-- @end@ succeeds. Returns the list of values returned by @p@. @end@ result+-- is consumed and lost. Use 'manyTill_' if you wish to keep it. -- -- See also: 'skipMany', 'skipManyTill'.--manyTill :: Alternative m => m a -> m end -> m [a]+manyTill :: (Alternative m) => m a -> m end -> m [a] manyTill p end = go   where     go = ([] <$ end) <|> liftA2 (:) p go {-# INLINE manyTill #-} +-- | @'manyTill_' p end@ applies parser @p@ /zero/ or more times until+-- parser @end@ succeeds. Returns the list of values returned by @p@ and the+-- @end@ result. Use 'manyTill' if you have no need in the result of the+-- @end@.+--+-- See also: 'skipMany', 'skipManyTill'.+--+-- @since 1.2.0+manyTill_ :: (Alternative m) => m a -> m end -> m ([a], end)+manyTill_ p end = go+  where+    go = (([],) <$> end) <|> liftA2 (\x (xs, y) -> (x : xs, y)) p go+{-# INLINE manyTill_ #-}+ -- | @'someTill' p end@ works similarly to @'manyTill' p end@, but @p@--- should succeed at least once.+-- should succeed at least once. @end@ result is consumed and lost. Use+-- 'someTill_' if you wish to keep it. --+-- > someTill p end = liftA2 (:) p (manyTill p end)+-- -- See also: 'skipSome', 'skipSomeTill'.--someTill :: Alternative m => m a -> m end -> m [a]+someTill :: (Alternative m) => m a -> m end -> m [a] someTill p end = liftA2 (:) p (manyTill p end) {-# INLINE someTill #-} +-- | @'someTill_' p end@ works similarly to @'manyTill_' p end@, but @p@+-- should succeed at least once. Use 'someTill' if you have no need in the+-- result of the @end@.+--+-- See also: 'skipSome', 'skipSomeTill'.+--+-- @since 1.2.0+someTill_ :: (Alternative m) => m a -> m end -> m ([a], end)+someTill_ p end =+  liftA2 (\x (xs, y) -> (x : xs, y)) p (manyTill_ p end)+{-# INLINE someTill_ #-}+ -- | @'option' x p@ tries to apply the parser @p@. If @p@ fails without -- consuming input, it returns the value @x@, otherwise the value returned -- by @p@.@@ -234,8 +250,7 @@ -- > option x p = p <|> pure x -- -- See also: 'optional'.--option :: Alternative m => a -> m a -> m a+option :: (Alternative m) => a -> m a -> m a option x p = p <|> pure x {-# INLINE option #-} @@ -243,29 +258,25 @@ -- @sep@. Returns a list of values returned by @p@. -- -- > commaSep p = p `sepBy` comma--sepBy :: Alternative m => m a -> m sep -> m [a]+sepBy :: (Alternative m) => m a -> m sep -> m [a] sepBy p sep = sepBy1 p sep <|> pure [] {-# INLINE sepBy #-}  -- | @'sepBy1' p sep@ parses /one/ or more occurrences of @p@, separated by -- @sep@. Returns a list of values returned by @p@.--sepBy1 :: Alternative m => m a -> m sep -> m [a]+sepBy1 :: (Alternative m) => m a -> m sep -> m [a] sepBy1 p sep = liftA2 (:) p (many (sep *> p)) {-# INLINE sepBy1 #-}  -- | @'sepEndBy' p sep@ parses /zero/ or more occurrences of @p@, separated -- and optionally ended by @sep@. Returns a list of values returned by @p@.--sepEndBy :: Alternative m => m a -> m sep -> m [a]+sepEndBy :: (Alternative m) => m a -> m sep -> m [a] sepEndBy p sep = sepEndBy1 p sep <|> pure [] {-# INLINE sepEndBy #-}  -- | @'sepEndBy1' p sep@ parses /one/ or more occurrences of @p@, separated -- and optionally ended by @sep@. Returns a list of values returned by @p@.--sepEndBy1 :: Alternative m => m a -> m sep -> m [a]+sepEndBy1 :: (Alternative m) => m a -> m sep -> m [a] sepEndBy1 p sep = liftA2 (:) p ((sep *> sepEndBy p sep) <|> pure []) {-# INLINEABLE sepEndBy1 #-} @@ -273,8 +284,7 @@ -- its result. -- -- See also: 'manyTill', 'skipManyTill'.--skipMany :: Alternative m => m a -> m ()+skipMany :: (Alternative m) => m a -> m () skipMany p = go   where     go = (p *> go) <|> pure ()@@ -284,27 +294,20 @@ -- result. -- -- See also: 'someTill', 'skipSomeTill'.--skipSome :: Alternative m => m a -> m ()+skipSome :: (Alternative m) => m a -> m () skipSome p = p *> skipMany p {-# INLINE skipSome #-}  -- | @'skipCount' n p@ parses @n@ occurrences of @p@, skipping its result.--- If @n@ is not positive, the parser equals to @'pure' []@. Returns a list--- of @n@ values.+-- If @n@ is not positive, the parser equals to @'pure' ()@. -- -- > skipCount = replicateM_ -- -- See also: 'count', 'count''. -- -- @since 0.3.0--skipCount :: Applicative m => Int -> m a -> m ()-#if MIN_VERSION_base(4,9,0)+skipCount :: (Applicative m) => Int -> m a -> m () skipCount = replicateM_-#else-skipCount n p = sequenceA_ (replicate n p)-#endif {-# INLINE skipCount #-}  -- | @'skipManyTill' p end@ applies the parser @p@ /zero/ or more times@@ -312,8 +315,7 @@ -- then returned. -- -- See also: 'manyTill', 'skipMany'.--skipManyTill :: Alternative m => m a -> m end -> m end+skipManyTill :: (Alternative m) => m a -> m end -> m end skipManyTill p end = go   where     go = end <|> (p *> go)@@ -324,7 +326,6 @@ -- then returned. -- -- See also: 'someTill', 'skipSome'.--skipSomeTill :: Alternative m => m a -> m end -> m end+skipSomeTill :: (Alternative m) => m a -> m end -> m end skipSomeTill p end = p *> skipManyTill p end {-# INLINE skipSomeTill #-}
Control/Applicative/Combinators/NonEmpty.hs view
@@ -1,6 +1,6 @@ -- | -- Module      :  Control.Applicative.Combinators--- Copyright   :  © 2017–2018 Mark Karpov+-- Copyright   :  © 2017–present Mark Karpov -- License     :  BSD 3 clause -- -- Maintainer  :  Mark Karpov <markkarpov92@gmail.com>@@ -11,33 +11,31 @@ -- from "Control.Applicative.Combinators". -- -- @since 0.2.0- module Control.Applicative.Combinators.NonEmpty-  ( some-  , endBy1-  , someTill-  , sepBy1-  , sepEndBy1 )+  ( some,+    endBy1,+    someTill,+    sepBy1,+    sepEndBy1,+  ) where  import Control.Applicative hiding (some)-import Data.List.NonEmpty (NonEmpty (..)) import qualified Control.Applicative.Combinators as C-import qualified Data.List.NonEmpty              as NE+import Data.List.NonEmpty (NonEmpty (..))+import qualified Data.List.NonEmpty as NE  -- | @'some' p@ applies the parser @p@ /one/ or more times and returns a -- list of the values returned by @p@. -- -- > word = some letter--some :: Alternative m => m a -> m (NonEmpty a)+some :: (Alternative m) => m a -> m (NonEmpty a) some p = NE.fromList <$> C.some p {-# INLINE some #-}  -- | @'endBy1' p sep@ parses /one/ or more occurrences of @p@, separated and -- ended by @sep@. Returns a non-empty list of values returned by @p@.--endBy1 :: Alternative m => m a -> m sep -> m (NonEmpty a)+endBy1 :: (Alternative m) => m a -> m sep -> m (NonEmpty a) endBy1 p sep = NE.fromList <$> C.endBy1 p sep {-# INLINE endBy1 #-} @@ -45,22 +43,19 @@ -- should succeed at least once. -- -- See also: 'C.skipSome', 'C.skipSomeTill'.--someTill :: Alternative m => m a -> m end -> m (NonEmpty a)+someTill :: (Alternative m) => m a -> m end -> m (NonEmpty a) someTill p end = NE.fromList <$> C.someTill p end {-# INLINE someTill #-}  -- | @'sepBy1' p sep@ parses /one/ or more occurrences of @p@, separated by -- @sep@. Returns a non-empty list of values returned by @p@.--sepBy1 :: Alternative m => m a -> m sep -> m (NonEmpty a)+sepBy1 :: (Alternative m) => m a -> m sep -> m (NonEmpty a) sepBy1 p sep = NE.fromList <$> C.sepBy1 p sep {-# INLINE sepBy1 #-}  -- | @'sepEndBy1' p sep@ parses /one/ or more occurrences of @p@, separated -- and optionally ended by @sep@. Returns a non-empty list of values returned by -- @p@.--sepEndBy1 :: Alternative m => m a -> m sep -> m (NonEmpty a)+sepEndBy1 :: (Alternative m) => m a -> m sep -> m (NonEmpty a) sepEndBy1 p sep = NE.fromList <$> C.sepEndBy1 p sep {-# INLINE sepEndBy1 #-}
Control/Applicative/Permutations.hs view
@@ -1,6 +1,8 @@+{-# LANGUAGE ExistentialQuantification #-}+ -- | -- Module      :  Control.Applicative.Permutations--- Copyright   :  © 2017–2018 Mark Karpov+-- Copyright   :  © 2017–present Alex Washburn -- License     :  BSD 3 clause -- -- Maintainer  :  Mark Karpov <markkarpov92@gmail.com>@@ -30,8 +32,8 @@ -- -- For example, suppose we want to parse a permutation of: an optional -- string of @a@'s, the character @b@ and an optional @c@. Using a standard--- parsing library combinator @char@, this can be described using the--- 'Applicative' instance by:+-- parsing library combinator @char@ (e.g. 'Text.ParserCombinators.ReadP.ReadP')+-- this can be described using the 'Applicative' instance by: -- -- > test = runPermutation $ -- >          (,,) <$> toPermutationWithDefault ""  (some (char 'a'))@@ -39,45 +41,56 @@ -- >               <*> toPermutationWithDefault '_' (char 'c') -- -- @since 0.2.0- module Control.Applicative.Permutations   ( -- ** Permutation type-    Permutation+    Permutation,+     -- ** Permutation evaluators-  , runPermutation-  , intercalateEffect+    runPermutation,+    intercalateEffect,+     -- ** Permutation constructors-  , toPermutation-  , toPermutationWithDefault )+    toPermutation,+    toPermutationWithDefault,+  ) where  import Control.Applicative+import Data.Function ((&))  -- | An 'Applicative' wrapper-type for constructing permutation parsers.+data Permutation m a = P !(Maybe a) [Branch m a] -data Permutation m a = P (Maybe a) (m (Permutation m a))+data Branch m a = forall z. Branch (Permutation m (z -> a)) (m z) -instance Functor m => Functor (Permutation m) where-  fmap f (P v p) = P (f <$> v) (fmap f <$> p)+instance (Functor m) => Functor (Permutation m) where+  fmap f (P v bs) = P (f <$> v) (fmap f <$> bs) -instance Alternative m => Applicative (Permutation m) where+instance (Functor p) => Functor (Branch p) where+  fmap f (Branch perm p) = Branch (fmap (f .) perm) p++instance (Functor m) => Applicative (Permutation m) where   pure value = P (Just value) empty-  lhs@(P f v) <*> rhs@(P g w) = P (f <*> g) (lhsAlt <|> rhsAlt)+  lhs@(P f v) <*> rhs@(P g w) = P (f <*> g) $ (ins2 <$> v) <> (ins1 <$> w)     where-      lhsAlt = (<*> rhs) <$> v-      rhsAlt = (lhs <*>) <$> w+      ins1 (Branch perm p) = Branch ((.) <$> lhs <*> perm) p+      ins2 (Branch perm p) = Branch (flip <$> perm <*> rhs) p+  liftA2 f lhs@(P x v) rhs@(P y w) = P (liftA2 f x y) $ (ins2 <$> v) <> (ins1 <$> w)+    where+      ins1 (Branch perm p) = Branch (liftA2 ((.) . f) lhs perm) p+      ins2 (Branch perm p) = Branch (liftA2 (\b g z -> f (g z) b) rhs perm) p  -- | \"Unlifts\" a permutation parser into a parser to be evaluated.--runPermutation-  :: ( Alternative m-     , Monad m)-  => Permutation m a -- ^ Permutation specification-  -> m a             -- ^ Resulting base monad capable of handling the permutation-runPermutation (P value parser) = optional parser >>= f-   where-      f  Nothing = maybe empty pure value-      f (Just p) = runPermutation p+runPermutation ::+  (Alternative m) =>+  -- | Permutation specification+  Permutation m a ->+  -- | Resulting base monad capable of handling the permutation+  m a+runPermutation = foldAlt f+  where+    -- INCORRECT   = runPerms t <*> p+    f (Branch t p) = (&) <$> p <*> runPermutation t  -- | \"Unlifts\" a permutation parser into a parser to be evaluated with an -- intercalated effect. Useful for separators between permutation elements.@@ -105,41 +118,48 @@ --       permutation. --     * No effects are intercalated between missing components with a --       default value.--intercalateEffect-  :: ( Alternative m-     , Monad m)-  => m b             -- ^ Effect to be intercalated between permutation components-  -> Permutation m a -- ^ Permutation specification-  -> m a             -- ^ Resulting base monad capable of handling the permutation-intercalateEffect = run noEffect-   where-     noEffect = pure ()+--     * If an effect is encountered after a component, another component must+--       immediately follow the effect.+intercalateEffect ::+  (Alternative m) =>+  -- | Effect to be intercalated between permutation components+  m b ->+  -- | Permutation specification+  Permutation m a ->+  -- | Resulting base applicative capable of handling the permutation+  m a+intercalateEffect effect = foldAlt (runBranchEff effect)+  where+    runPermEff :: (Alternative m) => m b -> Permutation m a -> m a+    runPermEff eff (P v bs) =+      eff *> foldr ((<|>) . runBranchEff eff) empty bs <|> maybe empty pure v -     run :: (Alternative m, Monad m) => m c -> m b -> Permutation m a -> m a-     run headSep tailSep (P value parser) = optional headSep >>= f-       where-         f  Nothing = maybe empty pure value-         f (Just _) = optional parser >>= g-         g  Nothing = maybe empty pure value-         g (Just p) = run tailSep tailSep p+    runBranchEff :: (Alternative m) => m b -> Branch m a -> m a+    runBranchEff eff (Branch t p) = (&) <$> p <*> runPermEff eff t  -- | \"Lifts\" a parser to a permutation parser.--toPermutation-  :: Alternative m-  => m a -- ^ Permutation component-  -> Permutation m a-toPermutation p = P Nothing $ pure <$> p+toPermutation ::+  (Alternative m) =>+  -- | Permutation component+  m a ->+  Permutation m a+toPermutation = P Nothing . pure . branch  -- | \"Lifts\" a parser with a default value to a permutation parser. -- -- If no permutation containing the supplied parser can be parsed from the input, -- then the supplied default value is returned in lieu of a parse result.+toPermutationWithDefault ::+  (Alternative m) =>+  -- | Default Value+  a ->+  -- | Permutation component+  m a ->+  Permutation m a+toPermutationWithDefault v = P (Just v) . pure . branch -toPermutationWithDefault-  :: Alternative m-  => a   -- ^ Default Value-  -> m a -- ^ Permutation component-  -> Permutation m a-toPermutationWithDefault v p = P (Just v) $ pure <$> p+branch :: (Functor m) => m a -> Branch m a+branch = Branch $ pure id++foldAlt :: (Alternative m) => (Branch m a -> m a) -> Permutation m a -> m a+foldAlt f (P v bs) = foldr ((<|>) . f) (maybe empty pure v) bs
Control/Monad/Combinators.hs view
@@ -1,6 +1,8 @@+{-# LANGUAGE BangPatterns #-}+ -- | -- Module      :  Control.Monad.Combinators--- Copyright   :  © 2017–2018 Mark Karpov+-- Copyright   :  © 2017–present Mark Karpov -- License     :  BSD 3 clause -- -- Maintainer  :  Mark Karpov <markkarpov92@gmail.com>@@ -15,45 +17,44 @@ -- "Control.Applicative.Combinators". -- -- @since 0.4.0--{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE CPP          #-}- module Control.Monad.Combinators   ( -- * Re-exports from "Control.Applicative"-    (C.<|>)+    (C.<|>),     -- $assocbo-  , C.optional+    C.optional,     -- $optional-  , C.empty+    C.empty,     -- $empty      -- * Original combinators-  , C.between-  , C.choice-  , count-  , count'-  , C.eitherP-  , endBy-  , endBy1-  , many-  , manyTill-  , some-  , someTill-  , C.option-  , sepBy-  , sepBy1-  , sepEndBy-  , sepEndBy1-  , skipMany-  , skipSome-  , skipCount-  , skipManyTill-  , skipSomeTill )+    C.between,+    C.choice,+    count,+    count',+    C.eitherP,+    endBy,+    endBy1,+    many,+    manyTill,+    manyTill_,+    some,+    someTill,+    someTill_,+    C.option,+    sepBy,+    sepBy1,+    sepEndBy,+    sepEndBy1,+    skipMany,+    skipSome,+    skipCount,+    skipManyTill,+    skipSomeTill,+  ) where -import Control.Monad import qualified Control.Applicative.Combinators as C+import Control.Monad  ---------------------------------------------------------------------------- -- Re-exports from "Control.Applicative"@@ -86,16 +87,15 @@ -- values. -- -- See also: 'skipCount', 'count''.--count :: Monad m => Int -> m a -> m [a]-count n' p = liftM ($ []) (go id n')+count :: (Monad m) => Int -> m a -> m [a]+count n' p = go id n'   where     go f !n =       if n <= 0-        then return f+        then return (f [])         else do           x <- p-          go (f . (x:)) (n - 1)+          go (f . (x :)) (n - 1) {-# INLINE count #-}  -- | @'count'' m n p@ parses from @m@ to @n@ occurrences of @p@. If @n@ is@@ -106,143 +106,160 @@ -- as if it were equal to zero. -- -- See also: 'skipCount', 'count'.--count' :: MonadPlus m => Int -> Int -> m a -> m [a]+count' :: (MonadPlus m) => Int -> Int -> m a -> m [a] count' m' n' p =   if n' > 0 && n' >= m'-    then liftM ($ []) (gom id m')+    then gom id m'     else return []   where     gom f !m =       if m > 0         then do           x <- p-          gom (f . (x:)) (m - 1)+          gom (f . (x :)) (m - 1)         else god f (if m' <= 0 then n' else n' - m')     god f !d =       if d > 0         then do-          r <- optional p+          r <- C.optional p           case r of-            Nothing -> return f-            Just  x -> god (f . (x:)) (d - 1)-        else return f+            Nothing -> return (f [])+            Just x -> god (f . (x :)) (d - 1)+        else return (f []) {-# INLINE count' #-}  -- | @'endBy' p sep@ parses /zero/ or more occurrences of @p@, separated and -- ended by @sep@. Returns a list of values returned by @p@. -- -- > cStatements = cStatement `endBy` semicolon--endBy :: MonadPlus m => m a -> m sep -> m [a]-endBy p sep = many (p >>= \x -> re x sep)+endBy :: (MonadPlus m) => m a -> m sep -> m [a]+endBy p sep = many (p >>= \x -> x <$ sep) {-# INLINE endBy #-}  -- | @'endBy1' p sep@ parses /one/ or more occurrences of @p@, separated and -- ended by @sep@. Returns a list of values returned by @p@.--endBy1 :: MonadPlus m => m a -> m sep -> m [a]-endBy1 p sep = some (p >>= \x -> re x sep)+endBy1 :: (MonadPlus m) => m a -> m sep -> m [a]+endBy1 p sep = some (p >>= \x -> x <$ sep) {-# INLINE endBy1 #-}  -- | @'many' p@ applies the parser @p@ /zero/ or more times and returns a -- list of the values returned by @p@. -- -- > identifier = (:) <$> letter <*> many (alphaNumChar <|> char '_')--many :: MonadPlus m => m a -> m [a]-many p = liftM ($ []) (go id)+many :: (MonadPlus m) => m a -> m [a]+many p = go id   where     go f = do-      r <- optional p+      r <- C.optional p       case r of-        Nothing -> return f-        Just  x -> go (f . (x:))+        Nothing -> return (f [])+        Just x -> go (f . (x :)) {-# INLINE many #-}  -- | @'manyTill' p end@ applies parser @p@ /zero/ or more times until parser--- @end@ succeeds. Returns the list of values returned by @p@.+-- @end@ succeeds. Returns the list of values returned by @p@. __Note__ that+-- @end@ result is consumed and lost. Use 'manyTill_' if you wish to keep+-- it. -- -- See also: 'skipMany', 'skipManyTill'.+manyTill :: (MonadPlus m) => m a -> m end -> m [a]+manyTill p end = fst <$> manyTill_ p end+{-# INLINE manyTill #-} -manyTill :: MonadPlus m => m a -> m end -> m [a]-manyTill p end = liftM ($ []) (go id)+-- | @'manyTill_' p end@ applies parser @p@ /zero/ or more times until+-- parser @end@ succeeds. Returns the list of values returned by @p@ and the+-- @end@ result. Use 'manyTill' if you have no need in the result of the+-- @end@.+--+-- See also: 'skipMany', 'skipManyTill'.+--+-- @since 1.2.0+manyTill_ :: (MonadPlus m) => m a -> m end -> m ([a], end)+manyTill_ p end = go id   where     go f = do-      done <- option False (re True end)-      if done-        then return f-        else do+      done <- C.optional end+      case done of+        Just done' -> return (f [], done')+        Nothing -> do           x <- p-          go (f . (x:))-{-# INLINE manyTill #-}+          go (f . (x :))+{-# INLINE manyTill_ #-}  -- | @'some' p@ applies the parser @p@ /one/ or more times and returns a -- list of the values returned by @p@. -- -- > word = some letter--some :: MonadPlus m => m a -> m [a]+some :: (MonadPlus m) => m a -> m [a] some p = liftM2 (:) p (many p) {-# INLINE some #-}  -- | @'someTill' p end@ works similarly to @'manyTill' p end@, but @p@--- should succeed at least once.+-- should succeed at least once. __Note__ that @end@ result is consumed and+-- lost. Use 'someTill_' if you wish to keep it. --+-- > someTill p end = liftM2 (:) p (manyTill p end)+-- -- See also: 'skipSome', 'skipSomeTill'.--someTill :: MonadPlus m => m a -> m end -> m [a]+someTill :: (MonadPlus m) => m a -> m end -> m [a] someTill p end = liftM2 (:) p (manyTill p end) {-# INLINE someTill #-} +-- | @'someTill_' p end@ works similarly to @'manyTill_' p end@, but @p@+-- should succeed at least once. Use 'someTill' if you have no need in the+-- result of the @end@.+--+-- See also: 'skipSome', 'skipSomeTill'.+--+-- @since 1.2.0+someTill_ :: (MonadPlus m) => m a -> m end -> m ([a], end)+someTill_ p end = liftM2 (\x (xs, y) -> (x : xs, y)) p (manyTill_ p end)+{-# INLINE someTill_ #-}+ -- | @'sepBy' p sep@ parses /zero/ or more occurrences of @p@, separated by -- @sep@. Returns a list of values returned by @p@. -- -- > commaSep p = p `sepBy` comma--sepBy :: MonadPlus m => m a -> m sep -> m [a]+sepBy :: (MonadPlus m) => m a -> m sep -> m [a] sepBy p sep = do-  r <- optional p+  r <- C.optional p   case r of     Nothing -> return []-    Just  x -> liftM (x:) (many (sep >> p))+    Just x -> (x :) <$> many (sep >> p) {-# INLINE sepBy #-}  -- | @'sepBy1' p sep@ parses /one/ or more occurrences of @p@, separated by -- @sep@. Returns a list of values returned by @p@.--sepBy1 :: MonadPlus m => m a -> m sep -> m [a]+sepBy1 :: (MonadPlus m) => m a -> m sep -> m [a] sepBy1 p sep = do   x <- p-  liftM (x:) (many (sep >> p))+  (x :) <$> many (sep >> p) {-# INLINE sepBy1 #-}  -- | @'sepEndBy' p sep@ parses /zero/ or more occurrences of @p@, separated -- and optionally ended by @sep@. Returns a list of values returned by @p@.--sepEndBy :: MonadPlus m => m a -> m sep -> m [a]-sepEndBy p sep = liftM ($ []) (go id)+sepEndBy :: (MonadPlus m) => m a -> m sep -> m [a]+sepEndBy p sep = go id   where     go f = do-      r <- optional p+      r <- C.optional p       case r of-        Nothing -> return f-        Just  x -> do-          more <- option False (re True sep)+        Nothing -> return (f [])+        Just x -> do+          more <- C.option False (True <$ sep)           if more-            then go (f . (x:))-            else return (f . (x:))+            then go (f . (x :))+            else return (f [x]) {-# INLINE sepEndBy #-}  -- | @'sepEndBy1' p sep@ parses /one/ or more occurrences of @p@, separated -- and optionally ended by @sep@. Returns a list of values returned by @p@.--sepEndBy1 :: MonadPlus m => m a -> m sep -> m [a]+sepEndBy1 :: (MonadPlus m) => m a -> m sep -> m [a] sepEndBy1 p sep = do   x <- p-  more <- option False (re True sep)+  more <- C.option False (True <$ sep)   if more-    then liftM (x:) (sepEndBy p sep)+    then (x :) <$> sepEndBy p sep     else return [x] {-# INLINE sepEndBy1 #-} @@ -250,12 +267,11 @@ -- its result. -- -- See also: 'manyTill', 'skipManyTill'.--skipMany :: MonadPlus m => m a -> m ()+skipMany :: (MonadPlus m) => m a -> m () skipMany p = go   where     go = do-      more <- option False (re True p)+      more <- C.option False (True <$ p)       when more go {-# INLINE skipMany #-} @@ -263,18 +279,15 @@ -- result. -- -- See also: 'someTill', 'skipSomeTill'.--skipSome :: MonadPlus m => m a -> m ()+skipSome :: (MonadPlus m) => m a -> m () skipSome p = p >> skipMany p {-# INLINE skipSome #-}  -- | @'skipCount' n p@ parses @n@ occurrences of @p@, skipping its result.--- If @n@ is smaller or equal to zero, the parser equals to @'return' []@.--- Returns a list of @n@ values.+-- If @n@ is smaller or equal to zero, the parser equals to @'return' ()@. -- -- See also: 'count', 'count''.--skipCount :: Monad m => Int -> m a -> m ()+skipCount :: (Monad m) => Int -> m a -> m () skipCount n' p = go n'   where     go !n =@@ -287,15 +300,14 @@ -- then returned. -- -- See also: 'manyTill', 'skipMany'.--skipManyTill :: MonadPlus m => m a -> m end -> m end+skipManyTill :: (MonadPlus m) => m a -> m end -> m end skipManyTill p end = go   where     go = do-      r <- optional end+      r <- C.optional end       case r of         Nothing -> p >> go-        Just  x -> return x+        Just x -> return x {-# INLINE skipManyTill #-}  -- | @'skipSomeTill' p end@ applies the parser @p@ /one/ or more times@@ -303,22 +315,6 @@ -- then returned. -- -- See also: 'someTill', 'skipSome'.--skipSomeTill :: MonadPlus m => m a -> m end -> m end+skipSomeTill :: (MonadPlus m) => m a -> m end -> m end skipSomeTill p end = p >> skipManyTill p end {-# INLINE skipSomeTill #-}--------------------------------------------------------------------------------- Compat helpers (for older GHCs)--re :: Monad m => a -> m b -> m a-re x = liftM (const x)-{-# INLINE re #-}--option :: MonadPlus m => a -> m a -> m a-option x p = p `mplus` return x-{-# INLINE option #-}--optional :: MonadPlus m => m a -> m (Maybe a)-optional p = liftM Just p `mplus` return Nothing-{-# INLINE optional #-}
Control/Monad/Combinators/Expr.hs view
@@ -1,6 +1,6 @@ -- | -- Module      :  Control.Monad.Combinators.Expr--- Copyright   :  © 2017–2018 Mark Karpov+-- Copyright   :  © 2017–present Mark Karpov -- License     :  BSD 3 clause -- -- Maintainer  :  Mark Karpov <markkarpov92@gmail.com>@@ -11,10 +11,10 @@ -- of operators. -- -- @since 1.0.0- module Control.Monad.Combinators.Expr-  ( Operator (..)-  , makeExprParser )+  ( Operator (..),+    makeExprParser,+  ) where  import Control.Monad@@ -23,13 +23,29 @@ -- | This data type specifies operators that work on values of type @a@. An -- operator is either binary infix or unary prefix or postfix. A binary -- operator has also an associated associativity.- data Operator m a-  = InfixN  (m (a -> a -> a)) -- ^ Non-associative infix-  | InfixL  (m (a -> a -> a)) -- ^ Left-associative infix-  | InfixR  (m (a -> a -> a)) -- ^ Right-associative infix-  | Prefix  (m (a -> a))      -- ^ Prefix-  | Postfix (m (a -> a))      -- ^ Postfix+  = -- | Non-associative infix+    InfixN (m (a -> a -> a))+  | -- | Left-associative infix+    InfixL (m (a -> a -> a))+  | -- | Right-associative infix+    InfixR (m (a -> a -> a))+  | -- | Prefix+    Prefix (m (a -> a))+  | -- | Postfix+    Postfix (m (a -> a))+  | -- | Right-associative ternary. Right-associative means that+    -- @a ? b : d ? e : f@ parsed as+    -- @a ? b : (d ? e : f)@ and not as @(a ? b : d) ? e : f@.+    --+    -- The outer monadic action parses the first separator (e.g. @?@) and+    -- returns an action (of type @m (a -> a -> a -> a)@) that parses the+    -- second separator (e.g. @:@).+    --+    -- Example usage:+    --+    -- >>> TernR ((If <$ char ':') <$ char '?')+    TernR (m (m (a -> a -> a -> a)))  -- | @'makeExprParser' term table@ builds an expression parser for terms -- @term@ with operators from @table@, taking the associativity and@@ -76,36 +92,38 @@ -- > binary  name f = InfixL  (f <$ symbol name) -- > prefix  name f = Prefix  (f <$ symbol name) -- > postfix name f = Postfix (f <$ symbol name)--makeExprParser :: MonadPlus m-  => m a               -- ^ Term parser-  -> [[Operator m a]]  -- ^ Operator table, see 'Operator'-  -> m a               -- ^ Resulting expression parser+makeExprParser ::+  (MonadPlus m) =>+  -- | Term parser+  m a ->+  -- | Operator table, see 'Operator'+  [[Operator m a]] ->+  -- | Resulting expression parser+  m a makeExprParser = foldl addPrecLevel {-# INLINEABLE makeExprParser #-}  -- | @addPrecLevel p ops@ adds the ability to parse operators in table @ops@ -- to parser @p@.--addPrecLevel :: MonadPlus m => m a -> [Operator m a] -> m a+addPrecLevel :: (MonadPlus m) => m a -> [Operator m a] -> m a addPrecLevel term ops =-  term' >>= \x -> choice [ras' x, las' x, nas' x, return x]+  term' >>= \x -> choice [ras' x, las' x, nas' x, tern' x, return x]   where-    (ras, las, nas, prefix, postfix) = foldr splitOp ([],[],[],[],[]) ops+    (ras, las, nas, prefix, postfix, tern) = foldr splitOp ([], [], [], [], [], []) ops     term' = pTerm (choice prefix) term (choice postfix)-    ras'  = pInfixR (choice ras) term'-    las'  = pInfixL (choice las) term'-    nas'  = pInfixN (choice nas) term'+    ras' = pInfixR (choice ras) term'+    las' = pInfixL (choice las) term'+    nas' = pInfixN (choice nas) term'+    tern' = pTernR (choice tern) term' {-# INLINEABLE addPrecLevel #-}  -- | @pTerm prefix term postfix@ parses a @term@ surrounded by optional -- prefix and postfix unary operators. Parsers @prefix@ and @postfix@ are -- allowed to fail, in this case 'id' is used.--pTerm :: MonadPlus m => m (a -> a) -> m a -> m (a -> a) -> m a+pTerm :: (MonadPlus m) => m (a -> a) -> m a -> m (a -> a) -> m a pTerm prefix term postfix = do-  pre  <- option id prefix-  x    <- term+  pre <- option id prefix+  x <- term   post <- option id postfix   return . post . pre $ x {-# INLINE pTerm #-}@@ -113,8 +131,7 @@ -- | @pInfixN op p x@ parses non-associative infix operator @op@, then term -- with parser @p@, then returns result of the operator application on @x@ -- and the term.--pInfixN :: MonadPlus m => m (a -> a -> a) -> m a -> a -> m a+pInfixN :: (MonadPlus m) => m (a -> a -> a) -> m a -> a -> m a pInfixN op p x = do   f <- op   y <- p@@ -124,8 +141,7 @@ -- | @pInfixL op p x@ parses left-associative infix operator @op@, then term -- with parser @p@, then returns result of the operator application on @x@ -- and the term.--pInfixL :: MonadPlus m => m (a -> a -> a) -> m a -> a -> m a+pInfixL :: (MonadPlus m) => m (a -> a -> a) -> m a -> a -> m a pInfixL op p x = do   f <- op   y <- p@@ -136,27 +152,38 @@ -- | @pInfixR op p x@ parses right-associative infix operator @op@, then -- term with parser @p@, then returns result of the operator application on -- @x@ and the term.--pInfixR :: MonadPlus m => m (a -> a -> a) -> m a -> a -> m a+pInfixR :: (MonadPlus m) => m (a -> a -> a) -> m a -> a -> m a pInfixR op p x = do   f <- op   y <- p >>= \r -> pInfixR op p r <|> return r   return $ f x y {-# INLINE pInfixR #-} +-- | Parse the first separator of a ternary operator+pTernR :: (MonadPlus m) => m (m (a -> a -> a -> a)) -> m a -> a -> m a+pTernR sep1 p x = do+  sep2 <- sep1+  y <- p >>= \r -> pTernR sep1 p r `mplus` return r+  f <- sep2+  z <- p >>= \r -> pTernR sep1 p r `mplus` return r+  return $ f x y z+{-# INLINE pTernR #-}+ type Batch m a =-  ( [m (a -> a -> a)]-  , [m (a -> a -> a)]-  , [m (a -> a -> a)]-  , [m (a -> a)]-  , [m (a -> a)] )+  ( [m (a -> a -> a)],+    [m (a -> a -> a)],+    [m (a -> a -> a)],+    [m (a -> a)],+    [m (a -> a)],+    [m (m (a -> a -> a -> a))]+  )  -- | A helper to separate various operators (binary, unary, and according to -- associativity) and return them in a tuple.- splitOp :: Operator m a -> Batch m a -> Batch m a-splitOp (InfixR  op) (r, l, n, pre, post) = (op:r, l, n, pre, post)-splitOp (InfixL  op) (r, l, n, pre, post) = (r, op:l, n, pre, post)-splitOp (InfixN  op) (r, l, n, pre, post) = (r, l, op:n, pre, post)-splitOp (Prefix  op) (r, l, n, pre, post) = (r, l, n, op:pre, post)-splitOp (Postfix op) (r, l, n, pre, post) = (r, l, n, pre, op:post)+splitOp (InfixR op) (r, l, n, pre, post, tern) = (op : r, l, n, pre, post, tern)+splitOp (InfixL op) (r, l, n, pre, post, tern) = (r, op : l, n, pre, post, tern)+splitOp (InfixN op) (r, l, n, pre, post, tern) = (r, l, op : n, pre, post, tern)+splitOp (Prefix op) (r, l, n, pre, post, tern) = (r, l, n, op : pre, post, tern)+splitOp (Postfix op) (r, l, n, pre, post, tern) = (r, l, n, pre, op : post, tern)+splitOp (TernR op) (r, l, n, pre, post, tern) = (r, l, n, pre, post, op : tern)
Control/Monad/Combinators/NonEmpty.hs view
@@ -1,6 +1,6 @@ -- | -- Module      :  Control.Monad.Combinators.NonEmpty--- Copyright   :  © 2017–2018 Mark Karpov+-- Copyright   :  © 2017–present Mark Karpov -- License     :  BSD 3 clause -- -- Maintainer  :  Mark Karpov <markkarpov92@gmail.com>@@ -11,56 +11,51 @@ -- from "Control.Monad.Combinators". -- -- @since 0.4.0- module Control.Monad.Combinators.NonEmpty-  ( some-  , endBy1-  , someTill-  , sepBy1-  , sepEndBy1 )+  ( some,+    endBy1,+    someTill,+    sepBy1,+    sepEndBy1,+  ) where  import Control.Monad-import Data.List.NonEmpty (NonEmpty (..)) import qualified Control.Monad.Combinators as C-import qualified Data.List.NonEmpty        as NE+import Data.List.NonEmpty (NonEmpty (..))+import qualified Data.List.NonEmpty as NE  -- | @'some' p@ applies the parser @p@ /one/ or more times and returns a -- list of the values returned by @p@. -- -- > word = some letter--some :: MonadPlus m => m a -> m (NonEmpty a)-some p = liftM NE.fromList (C.some p)+some :: (MonadPlus m) => m a -> m (NonEmpty a)+some p = NE.fromList <$> C.some p {-# INLINE some #-}  -- | @'endBy1' p sep@ parses /one/ or more occurrences of @p@, separated and -- ended by @sep@. Returns a non-empty list of values returned by @p@.--endBy1 :: MonadPlus m => m a -> m sep -> m (NonEmpty a)-endBy1 p sep = liftM NE.fromList (C.endBy1 p sep)+endBy1 :: (MonadPlus m) => m a -> m sep -> m (NonEmpty a)+endBy1 p sep = NE.fromList <$> C.endBy1 p sep {-# INLINE endBy1 #-}  -- | @'someTill' p end@ works similarly to @'C.manyTill' p end@, but @p@ -- should succeed at least once. -- -- See also: 'C.skipSome', 'C.skipSomeTill'.--someTill :: MonadPlus m => m a -> m end -> m (NonEmpty a)-someTill p end = liftM NE.fromList (C.someTill p end)+someTill :: (MonadPlus m) => m a -> m end -> m (NonEmpty a)+someTill p end = NE.fromList <$> C.someTill p end {-# INLINE someTill #-}  -- | @'sepBy1' p sep@ parses /one/ or more occurrences of @p@, separated by -- @sep@. Returns a non-empty list of values returned by @p@.--sepBy1 :: MonadPlus m => m a -> m sep -> m (NonEmpty a)-sepBy1 p sep = liftM NE.fromList (C.sepBy1 p sep)+sepBy1 :: (MonadPlus m) => m a -> m sep -> m (NonEmpty a)+sepBy1 p sep = NE.fromList <$> C.sepBy1 p sep {-# INLINE sepBy1 #-}  -- | @'sepEndBy1' p sep@ parses /one/ or more occurrences of @p@, separated -- and optionally ended by @sep@. Returns a non-empty list of values returned by -- @p@.--sepEndBy1 :: MonadPlus m => m a -> m sep -> m (NonEmpty a)-sepEndBy1 p sep = liftM NE.fromList (C.sepEndBy1 p sep)+sepEndBy1 :: (MonadPlus m) => m a -> m sep -> m (NonEmpty a)+sepEndBy1 p sep = NE.fromList <$> C.sepEndBy1 p sep {-# INLINE sepEndBy1 #-}
+ Control/Monad/Permutations.hs view
@@ -0,0 +1,104 @@+-- |+-- Module      :  Control.Monad.Permutations+-- Copyright   :  © 2017–present Alex Washburn+-- License     :  BSD 3 clause+--+-- Maintainer  :  Mark Karpov <markkarpov92@gmail.com>+-- Stability   :  experimental+-- Portability :  portable+--+-- This module specialized the interface to 'Monad' for potential efficiency+-- considerations, depending on the monad the permutations are run over.+--+-- For a more general interface requiring only 'Applicative', and for more+-- complete documentation, see the "Control.Applicative.Permutations" module.+--+-- @since 1.3.0+module Control.Monad.Permutations+  ( -- ** Permutation type+    Permutation,++    -- ** Permutation evaluators+    runPermutation,+    intercalateEffect,++    -- ** Permutation constructors+    toPermutation,+    toPermutationWithDefault,+  )+where++import Control.Applicative++-- | An 'Applicative' wrapper-type for constructing permutation parsers.+data Permutation m a = P !(Maybe a) (m (Permutation m a))++instance (Functor m) => Functor (Permutation m) where+  fmap f (P v p) = P (f <$> v) (fmap f <$> p)++instance (Alternative m) => Applicative (Permutation m) where+  pure value = P (Just value) empty+  lhs@(P f v) <*> rhs@(P g w) = P (f <*> g) (lhsAlt <|> rhsAlt)+    where+      lhsAlt = (<*> rhs) <$> v+      rhsAlt = (lhs <*>) <$> w+  liftA2 f lhs@(P x v) rhs@(P y w) = P (liftA2 f x y) (lhsAlt <|> rhsAlt)+    where+      lhsAlt = (\p -> liftA2 f p rhs) <$> v+      rhsAlt = liftA2 f lhs <$> w++-- | \"Unlifts\" a permutation parser into a parser to be evaluated.+runPermutation ::+  ( Alternative m,+    Monad m+  ) =>+  -- | Permutation specification+  Permutation m a ->+  -- | Resulting base monad capable of handling the permutation+  m a+runPermutation (P value parser) = optional parser >>= f+  where+    f Nothing = maybe empty pure value+    f (Just p) = runPermutation p++-- | \"Unlifts\" a permutation parser into a parser to be evaluated with an+-- intercalated effect. Useful for separators between permutation elements.+intercalateEffect ::+  ( Alternative m,+    Monad m+  ) =>+  -- | Effect to be intercalated between permutation components+  m b ->+  -- | Permutation specification+  Permutation m a ->+  -- | Resulting base monad capable of handling the permutation+  m a+intercalateEffect = run noEffect+  where+    noEffect = pure ()+    run :: (Alternative m, Monad m) => m c -> m b -> Permutation m a -> m a+    run headSep tailSep (P value parser) = optional (headSep *> parser) >>= f+      where+        f Nothing = maybe empty pure value+        f (Just p) = run tailSep tailSep p++-- | \"Lifts\" a parser to a permutation parser.+toPermutation ::+  (Alternative m) =>+  -- | Permutation component+  m a ->+  Permutation m a+toPermutation p = P Nothing $ pure <$> p++-- | \"Lifts\" a parser with a default value to a permutation parser.+--+-- If no permutation containing the supplied parser can be parsed from the input,+-- then the supplied default value is returned in lieu of a parse result.+toPermutationWithDefault ::+  (Alternative m) =>+  -- | Default Value+  a ->+  -- | Permutation component+  m a ->+  Permutation m a+toPermutationWithDefault v p = P (Just v) $ pure <$> p
LICENSE.md view
@@ -1,4 +1,4 @@-Copyright © 2017–2018 Mark Karpov+Copyright © 2017–present Mark Karpov  All rights reserved. 
README.md view
@@ -4,23 +4,22 @@ [![Hackage](https://img.shields.io/hackage/v/parser-combinators.svg?style=flat)](https://hackage.haskell.org/package/parser-combinators) [![Stackage Nightly](http://stackage.org/package/parser-combinators/badge/nightly)](http://stackage.org/nightly/package/parser-combinators) [![Stackage LTS](http://stackage.org/package/parser-combinators/badge/lts)](http://stackage.org/lts/package/parser-combinators)-[![Build Status](https://travis-ci.org/mrkkrp/parser-combinators.svg?branch=master)](https://travis-ci.org/mrkkrp/parser-combinators)+[![CI](https://github.com/mrkkrp/parser-combinators/actions/workflows/ci.yaml/badge.svg)](https://github.com/mrkkrp/parser-combinators/actions/workflows/ci.yaml)  The package provides common parser combinators defined in terms of `Applicative` and `Alternative` without any dependencies but `base`. There are also more efficient versions of the combinators defined in terms of-`Monad` and `MonadPlus`. Test suite and benchmarks can be found in the-[Megaparsec repo](https://github.com/mrkkrp/megaparsec).+`Monad` and `MonadPlus`.  ## Contribution  Issues, bugs, and questions may be reported in [the GitHub issue tracker for this project](https://github.com/mrkkrp/parser-combinators/issues). -Pull requests are also welcome and will be reviewed quickly.+Pull requests are also welcome.  ## License -Copyright © 2017–2018 Mark Karpov+Copyright © 2017–present Mark Karpov  Distributed under BSD 3 clause license.
− Setup.hs
@@ -1,6 +0,0 @@-module Main (main) where--import Distribution.Simple--main :: IO ()-main = defaultMain
parser-combinators.cabal view
@@ -1,49 +1,54 @@-name:                 parser-combinators-version:              1.0.0-cabal-version:        1.18-tested-with:          GHC==7.10.3, GHC==8.0.2, GHC==8.2.2, GHC==8.4.2-license:              BSD3-license-file:         LICENSE.md-author:               Mark Karpov <markkarpov92@gmail.com>-maintainer:           Mark Karpov <markkarpov92@gmail.com>-homepage:             https://github.com/mrkkrp/parser-combinators-bug-reports:          https://github.com/mrkkrp/parser-combinators/issues-category:             Parsing-synopsis:             Lightweight package providing commonly useful parser combinators-build-type:           Simple-description:          Lightweight package providing commonly useful parser combinators.-extra-doc-files:      CHANGELOG.md-                    , README.md+cabal-version:   2.4+name:            parser-combinators+version:         1.3.1+license:         BSD-3-Clause+license-file:    LICENSE.md+maintainer:      Mark Karpov <markkarpov92@gmail.com>+author:+    Mark Karpov <markkarpov92@gmail.com>+    Alex Washburn <github@recursion.ninja> +tested-with:     ghc ==9.8.4 ghc ==9.10.3 ghc ==9.12.1+homepage:        https://github.com/mrkkrp/parser-combinators+bug-reports:     https://github.com/mrkkrp/parser-combinators/issues+synopsis:+    Lightweight package providing commonly useful parser combinators++description:+    Lightweight package providing commonly useful parser combinators.++category:        Parsing+build-type:      Simple+extra-doc-files:+    CHANGELOG.md+    README.md+ source-repository head-  type:               git-  location:           https://github.com/mrkkrp/parser-combinators.git+    type:     git+    location: https://github.com/mrkkrp/parser-combinators.git  flag dev-  description:        Turn on development settings.-  manual:             True-  default:            False+    description: Turn on development settings.+    default:     False+    manual:      True  library-  build-depends:      base             >= 4.8 && < 5.0+    exposed-modules:+        Control.Applicative.Combinators+        Control.Applicative.Combinators.NonEmpty+        Control.Applicative.Permutations+        Control.Monad.Combinators+        Control.Monad.Combinators.Expr+        Control.Monad.Combinators.NonEmpty+        Control.Monad.Permutations -  if !impl(ghc >= 8.0)-    build-depends:    semigroups == 0.18.*+    default-language: Haskell2010+    build-depends:    base >=4.15 && <5 -  exposed-modules:    Control.Applicative.Combinators-                    , Control.Applicative.Combinators.NonEmpty-                    , Control.Applicative.Permutations-                    , Control.Monad.Combinators-                    , Control.Monad.Combinators.Expr-                    , Control.Monad.Combinators.NonEmpty-  if flag(dev)-    ghc-options:      -Wall -Werror-  else-    ghc-options:      -O2 -Wall-  if flag(dev) && impl(ghc >= 8.0)-    ghc-options:      -Wcompat-                      -Wincomplete-record-updates-                      -Wincomplete-uni-patterns-                      -Wnoncanonical-monad-instances-                      -Wnoncanonical-monadfail-instances-  default-language:   Haskell2010+    if flag(dev)+        ghc-options:+            -Wall -Werror -Wredundant-constraints -Wpartial-fields+            -Wunused-packages++    else+        ghc-options: -O2 -Wall