    \begin{code}
    {-# LANGUAGE RecordWildCards            #-}
    {-# LANGUAGE FlexibleContexts           #-}
    {-# LANGUAGE FlexibleInstances          #-}
    {-# LANGUAGE UndecidableInstances       #-}
    {-# LANGUAGE MultiParamTypeClasses      #-}
    {-# LANGUAGE DeriveDataTypeable         #-}
    {-# LANGUAGE MonoLocalBinds             #-}
    \end{code}

    \begin{code}
    module Text.RE.ZeInternals.Types.Matches
      ( Matches(..)
      , anyMatches
      , countMatches
      , matches
      , mainCaptures
      ) where
    \end{code}

    \begin{code}
    import           Data.Typeable
    import           Text.RE.ZeInternals.Types.Capture
    import           Text.RE.ZeInternals.Types.CaptureID
    import           Text.RE.ZeInternals.Types.Match
    import           Text.Regex.Base
    \end{code}

    \begin{code}
    -- | the result of matching a RE against a text (with @*=~@), retaining
    -- the text that was matched against
    data Matches a =
      Matches
        { forall a. Matches a -> a
    matchesSource :: !a          -- ^ the source text being matched
        , forall a. Matches a -> [Match a]
    allMatches    :: ![Match a]  -- ^ all 'Match' instances found, left to right
        }
      deriving (Int -> Matches a -> ShowS
    [Matches a] -> ShowS
    Matches a -> String
    (Int -> Matches a -> ShowS)
    -> (Matches a -> String)
    -> ([Matches a] -> ShowS)
    -> Show (Matches a)
    forall a. Show a => Int -> Matches a -> ShowS
    forall a. Show a => [Matches a] -> ShowS
    forall a. Show a => Matches a -> String
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: forall a. Show a => Int -> Matches a -> ShowS
    showsPrec :: Int -> Matches a -> ShowS
    $cshow :: forall a. Show a => Matches a -> String
    show :: Matches a -> String
    $cshowList :: forall a. Show a => [Matches a] -> ShowS
    showList :: [Matches a] -> ShowS
    Show,Matches a -> Matches a -> Bool
    (Matches a -> Matches a -> Bool)
    -> (Matches a -> Matches a -> Bool) -> Eq (Matches a)
    forall a. Eq a => Matches a -> Matches a -> Bool
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: forall a. Eq a => Matches a -> Matches a -> Bool
    == :: Matches a -> Matches a -> Bool
    $c/= :: forall a. Eq a => Matches a -> Matches a -> Bool
    /= :: Matches a -> Matches a -> Bool
    Eq,Typeable)
    \end{code}

    \begin{code}
    instance Functor Matches where
      fmap :: forall a b. (a -> b) -> Matches a -> Matches b
    fmap a -> b
    f Matches{a
    [Match a]
    matchesSource :: forall a. Matches a -> a
    allMatches :: forall a. Matches a -> [Match a]
    matchesSource :: a
    allMatches :: [Match a]
    ..} =
        Matches
          { matchesSource :: b
    matchesSource = a -> b
    f a
    matchesSource
          , allMatches :: [Match b]
    allMatches    = (Match a -> Match b) -> [Match a] -> [Match b]
    forall a b. (a -> b) -> [a] -> [b]
    map ((a -> b) -> Match a -> Match b
    forall a b. (a -> b) -> Match a -> Match b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap a -> b
    f) [Match a]
    allMatches
          }
    \end{code}

    \begin{code}
    -- | tests whether the RE matched the source text at all
    anyMatches :: Matches a -> Bool
    anyMatches :: forall a. Matches a -> Bool
    anyMatches = Bool -> Bool
    not (Bool -> Bool) -> (Matches a -> Bool) -> Matches a -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [Match a] -> Bool
    forall a. [a] -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null ([Match a] -> Bool)
    -> (Matches a -> [Match a]) -> Matches a -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Matches a -> [Match a]
    forall a. Matches a -> [Match a]
    allMatches

    -- | count the matches
    countMatches :: Matches a -> Int
    countMatches :: forall a. Matches a -> Int
    countMatches = [Match a] -> Int
    forall a. [a] -> Int
    forall (t :: * -> *) a. Foldable t => t a -> Int
    length ([Match a] -> Int) -> (Matches a -> [Match a]) -> Matches a -> Int
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Matches a -> [Match a]
    forall a. Matches a -> [Match a]
    allMatches

    -- | list the texts that Matched
    matches :: Matches a -> [a]
    matches :: forall a. Matches a -> [a]
    matches = (Capture a -> a) -> [Capture a] -> [a]
    forall a b. (a -> b) -> [a] -> [b]
    map Capture a -> a
    forall a. Capture a -> a
    capturedText ([Capture a] -> [a])
    -> (Matches a -> [Capture a]) -> Matches a -> [a]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Matches a -> [Capture a]
    forall a. Matches a -> [Capture a]
    mainCaptures

    -- | extract the main capture from each match
    mainCaptures :: Matches a -> [Capture a]
    mainCaptures :: forall a. Matches a -> [Capture a]
    mainCaptures Matches a
    ac = [ CaptureID -> Match a -> Capture a
    forall a. CaptureID -> Match a -> Capture a
    capture CaptureID
    c0 Match a
    cs | Match a
    cs<-Matches a -> [Match a]
    forall a. Matches a -> [Match a]
    allMatches Matches a
    ac ]
      where
        c0 :: CaptureID
    c0 = CaptureOrdinal -> CaptureID
    IsCaptureOrdinal (CaptureOrdinal -> CaptureID) -> CaptureOrdinal -> CaptureID
    forall a b. (a -> b) -> a -> b
    $ Int -> CaptureOrdinal
    CaptureOrdinal Int
    0
    \end{code}

    \begin{code}
    -- | this instance hooks 'Matches' into regex-base: regex consumers need
    -- not worry about any of this
    instance
        ( RegexContext regex source [MatchText source]
        , RegexLike    regex source
        , RegexFix     regex source
        ) =>
      RegexContext regex source (Matches source) where
        match :: regex -> source -> Matches source
    match  regex
    r source
    s = source -> [Match source] -> Matches source
    forall a. a -> [Match a] -> Matches a
    Matches source
    s ([Match source] -> Matches source)
    -> [Match source] -> Matches source
    forall a b. (a -> b) -> a -> b
    $ (MatchText source -> Match source)
    -> [MatchText source] -> [Match source]
    forall a b. (a -> b) -> [a] -> [b]
    map (regex -> source -> MatchText source -> Match source
    forall regex source.
    RegexFix regex source =>
    regex -> source -> MatchText source -> Match source
    convertMatchText regex
    r source
    s) ([MatchText source] -> [Match source])
    -> [MatchText source] -> [Match source]
    forall a b. (a -> b) -> a -> b
    $ regex -> source -> [MatchText source]
    forall regex source target.
    RegexContext regex source target =>
    regex -> source -> target
    match regex
    r source
    s
        matchM :: forall (m :: * -> *).
    MonadFail m =>
    regex -> source -> m (Matches source)
    matchM regex
    r source
    s = do
          y <- regex -> source -> m [MatchText source]
    forall regex source target (m :: * -> *).
    (RegexContext regex source target, MonadFail m) =>
    regex -> source -> m target
    forall (m :: * -> *).
    MonadFail m =>
    regex -> source -> m [MatchText source]
    matchM regex
    r source
    s
          return $ Matches s $ map (convertMatchText r s) y
    \end{code}