Control.Monad.Combinators

parser-combinators-1.3.0: Lightweight package providing commonly useful parser combinators

Copyright | © 2017–present Mark Karpov
License | BSD 3 clause
Maintainer | Mark Karpov <markkarpov92@gmail.com>
Stability | experimental
Portability | portable
Safe Haskell | Safe-Inferred
Language | Haskell2010

Control.Monad.Combinators

Contents

- Re-exports from Control.Applicative
- Original combinators

Description

The module provides more efficient versions of the combinators from Control.Applicative.Combinators defined in terms of `Monad` and `MonadPlus` instead of `Applicative` and `Alternative`. When there is no difference in performance we just re-export the combinators from Control.Applicative.Combinators.

Since: 0.4.0

Synopsis

- (<|>) :: Alternative f => f a -> f a -> f a
- optional :: Alternative f => f a -> f (Maybe a)
- empty :: Alternative f => f a
- between :: Applicative m => m open -> m close -> m a -> m a
- choice :: (Foldable f, Alternative m) => f (m a) -> m a
- count :: Monad m => Int -> m a -> m [a]
- count' :: MonadPlus m => Int -> Int -> m a -> m [a]
- eitherP :: Alternative m => m a -> m b -> m (Either a b)
- endBy :: MonadPlus m => m a -> m sep -> m [a]
- endBy1 :: MonadPlus m => m a -> m sep -> m [a]
- many :: MonadPlus m => m a -> m [a]
- manyTill :: MonadPlus m => m a -> m end -> m [a]
- manyTill_ :: MonadPlus m => m a -> m end -> m ([a], end)
- some :: MonadPlus m => m a -> m [a]
- someTill :: MonadPlus m => m a -> m end -> m [a]
- someTill_ :: MonadPlus m => m a -> m end -> m ([a], end)
- option :: Alternative m => a -> m a -> m a
- sepBy :: MonadPlus m => m a -> m sep -> m [a]
- sepBy1 :: MonadPlus m => m a -> m sep -> m [a]
- sepEndBy :: MonadPlus m => m a -> m sep -> m [a]
- sepEndBy1 :: MonadPlus m => m a -> m sep -> m [a]
- skipMany :: MonadPlus m => m a -> m ()
- skipSome :: MonadPlus m => m a -> m ()
- skipCount :: Monad m => Int -> m a -> m ()
- skipManyTill :: MonadPlus m => m a -> m end -> m end
- skipSomeTill :: MonadPlus m => m a -> m end -> m end

# Re-exports from Control.Applicative

(<|>) :: Alternative f => f a -> f a -> f a infixl 3 #

An associative binary operation

This combinator implements choice. The parser `p `<|>` q` first applies `p`. If it succeeds, the value of `p` is returned. If `p` fails, parser `q` is tried.

optional :: Alternative f => f a -> f (Maybe a) #

One or none.

It is useful for modelling any computation that is allowed to fail.

#### Examples

Expand

Using the `Alternative` instance of Control.Monad.Except, the following functions:

    >>> import Control.Monad.Except

    >>> canFail = throwError "it failed" :: Except String Int
    >>> final = return 42                :: Except String Int

Can be combined by allowing the first function to fail:

    >>> runExcept $ canFail *> final
    Left "it failed"

    >>> runExcept $ optional canFail *> final
    Right 42

``optional` p` tries to apply the parser `p`. It will parse `p` or `Nothing`. It only fails if `p` fails after consuming input. On success result of `p` is returned inside of `Just`, on failure `Nothing` is returned.

See also: `option`.

empty :: Alternative f => f a #

The identity of `<|>`

    empty <|> a     == a
    a     <|> empty == a

This parser fails unconditionally without providing any information about the cause of the failure.

# Original combinators

between :: Applicative m => m open -> m close -> m a -> m a #

``between` open close p` parses `open`, followed by `p` and `close`. Returns the value returned by `p`.

    braces = between (symbol "{") (symbol "}")

choice :: (Foldable f, Alternative m) => f (m a) -> m a #

``choice` ps` tries to apply the parsers in the list `ps` in order, until one of them succeeds. Returns the value of the succeeding parser.

    choice = asum

count :: Monad m => Int -> m a -> m [a] #

``count` n p` parses `n` occurrences of `p`. If `n` is smaller or equal to zero, the parser equals to ``return` []`. Returns a list of `n` values.

See also: `skipCount`, `count'`.

count' :: MonadPlus m => Int -> Int -> m a -> m [a] #

``count'` m n p` parses from `m` to `n` occurrences of `p`. If `n` is not positive or `m > n`, the parser equals to ``return` []`. Returns a list of parsed values.

Please note that `m` may be negative, in this case effect is the same as if it were equal to zero.

See also: `skipCount`, `count`.

eitherP :: Alternative m => m a -> m b -> m (Either a b) #

Combine two alternatives.

    eitherP a b = (Left <$> a) <|> (Right <$> b)

endBy :: MonadPlus m => m a -> m sep -> m [a] #

``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

endBy1 :: MonadPlus m => m a -> m sep -> m [a] #

``endBy1` p sep` parses one or more occurrences of `p`, separated and ended by `sep`. Returns a list of values returned by `p`.

many :: MonadPlus m => m a -> m [a] #

``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 '_')

manyTill :: MonadPlus m => m a -> m end -> m [a] #

``manyTill` p end` applies parser `p` zero or more times until parser `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], end) #

``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

some :: MonadPlus m => m a -> m [a] #

``some` p` applies the parser `p` one or more times and returns a list of the values returned by `p`.

    word = some letter

someTill :: MonadPlus m => m a -> m end -> m [a] #

``someTill` p end` works similarly to ``manyTill` p end`, but `p` 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], end) #

``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

option :: Alternative m => a -> m a -> m a #

``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`.

    option x p = p <|> pure x

See also: `optional`.

sepBy :: MonadPlus m => m a -> m sep -> m [a] #

``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

sepBy1 :: MonadPlus m => m a -> m sep -> m [a] #

``sepBy1` p sep` parses one or more occurrences of `p`, separated by `sep`. Returns a list of values returned by `p`.

sepEndBy :: MonadPlus m => m a -> m sep -> m [a] #

``sepEndBy` p sep` parses zero 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` p sep` parses one or more occurrences of `p`, separated and optionally ended by `sep`. Returns a list of values returned by `p`.

skipMany :: MonadPlus m => m a -> m () #

``skipMany` p` applies the parser `p` zero or more times, skipping its result.

See also: `manyTill`, `skipManyTill`.

skipSome :: MonadPlus m => m a -> m () #

``skipSome` p` applies the parser `p` one or more times, skipping its result.

See also: `someTill`, `skipSomeTill`.

skipCount :: Monad m => Int -> m a -> m () #

``skipCount` n p` parses `n` occurrences of `p`, skipping its result. If `n` is smaller or equal to zero, the parser equals to ``return` ()`.

See also: `count`, `count'`.

skipManyTill :: MonadPlus m => m a -> m end -> m end #

``skipManyTill` p end` applies the parser `p` zero or more times skipping results until parser `end` succeeds. Result parsed by `end` is then returned.

See also: `manyTill`, `skipMany`.

skipSomeTill :: MonadPlus m => m a -> m end -> m end #

``skipSomeTill` p end` applies the parser `p` one or more times skipping results until parser `end` succeeds. Result parsed by `end` is then returned.

See also: `someTill`, `skipSome`.