    -- | Folds for text streams

    module Control.Foldl.Text (
        -- * Folding
          fold
        , foldM

        -- * Folds
        , head
        , last
        , null
        , length
        , any
        , all
        , maximum
        , minimum
        , elem
        , notElem
        , find
        , index
        , elemIndex
        , findIndex
        , count
        , lazy

        -- * Re-exports
        -- $reexports
        , module Control.Foldl
        , module Data.Text
        ) where

    import Control.Foldl (Fold, FoldM)
    import Control.Foldl.Internal (Maybe'(..), strict, Either'(..), hush)
    import Data.Text (Text)
    import Prelude hiding (
        head, last, null, length, any, all, maximum, minimum, elem, notElem )

    import qualified Control.Foldl
    import qualified Control.Foldl.Internal
    import qualified Data.Text
    import qualified Data.Text.Lazy

    -- | Apply a strict left 'Fold' to lazy text
    fold :: Fold Text a -> Data.Text.Lazy.Text -> a
    fold :: forall a. Fold Text a -> Text -> a
    fold (Control.Foldl.Fold x -> Text -> x
    step x
    begin x -> a
    done) Text
    as =
        x -> a
    done ((x -> Text -> x) -> x -> Text -> x
    forall a. (a -> Text -> a) -> a -> Text -> a
    Data.Text.Lazy.foldlChunks x -> Text -> x
    step x
    begin Text
    as)
    {-# INLINABLE fold #-}

    -- | Apply a strict monadic left 'FoldM' to lazy text
    foldM :: Monad m => FoldM m Text a -> Data.Text.Lazy.Text -> m a
    foldM :: forall (m :: * -> *) a. Monad m => FoldM m Text a -> Text -> m a
    foldM (Control.Foldl.FoldM x -> Text -> m x
    step m x
    begin x -> m a
    done) Text
    as = do
        x
    x <- (m x -> Text -> m x) -> m x -> Text -> m x
    forall a. (a -> Text -> a) -> a -> Text -> a
    Data.Text.Lazy.foldlChunks m x -> Text -> m x
    step' m x
    begin Text
    as
        x -> m a
    done x
    x
      where
        step' :: m x -> Text -> m x
    step' m x
    mx Text
    bs = do
          x
    x <- m x
    mx
          x
    x x -> m x -> m x
    forall a b. a -> b -> b
    `seq` x -> Text -> m x
    step x
    x Text
    bs
    {-# INLINABLE foldM #-}

    {-| Get the first character of a text stream or return 'Nothing' if the stream
        is empty
    -}
    head :: Fold Text (Maybe Char)
    head :: Fold Text (Maybe Char)
    head = (Maybe' Char -> Text -> Maybe' Char)
    -> Maybe' Char
    -> (Maybe' Char -> Maybe Char)
    -> Fold Text (Maybe Char)
    forall a b x. (x -> a -> x) -> x -> (x -> b) -> Fold a b
    Control.Foldl.Fold Maybe' Char -> Text -> Maybe' Char
    step Maybe' Char
    forall a. Maybe' a
    Nothing' Maybe' Char -> Maybe Char
    forall a. Maybe' a -> Maybe a
    Control.Foldl.Internal.lazy
      where
        step :: Maybe' Char -> Text -> Maybe' Char
    step Maybe' Char
    mc Text
    txt =
            if Text -> Bool
    Data.Text.null Text
    txt
            then Maybe' Char
    mc
            else case Maybe' Char
    mc of
                Just' Char
    _  -> Maybe' Char
    mc
                Maybe' Char
    Nothing' -> Char -> Maybe' Char
    forall a. a -> Maybe' a
    Just' (HasCallStack => Text -> Char
    Text -> Char
    Data.Text.head Text
    txt)
    {-# INLINABLE head #-}

    {-| Get the last character of a text stream or return 'Nothing' if the text
        stream is empty
    -}
    last :: Fold Text (Maybe Char)
    last :: Fold Text (Maybe Char)
    last = (Maybe' Char -> Text -> Maybe' Char)
    -> Maybe' Char
    -> (Maybe' Char -> Maybe Char)
    -> Fold Text (Maybe Char)
    forall a b x. (x -> a -> x) -> x -> (x -> b) -> Fold a b
    Control.Foldl.Fold Maybe' Char -> Text -> Maybe' Char
    step Maybe' Char
    forall a. Maybe' a
    Nothing' Maybe' Char -> Maybe Char
    forall a. Maybe' a -> Maybe a
    Control.Foldl.Internal.lazy
      where
        step :: Maybe' Char -> Text -> Maybe' Char
    step Maybe' Char
    mc Text
    txt =
            if Text -> Bool
    Data.Text.null Text
    txt
            then Maybe' Char
    mc
            else Char -> Maybe' Char
    forall a. a -> Maybe' a
    Just' (HasCallStack => Text -> Char
    Text -> Char
    Data.Text.last Text
    txt)
            -- TODO: Use `unsafeLast` when Debian Stable Haskell Platform has it
    {-# INLINABLE last #-}

    -- | Returns 'True' if the text stream is empty, 'False' otherwise
    null :: Fold Text Bool
    null :: Fold Text Bool
    null = (Bool -> Text -> Bool) -> Bool -> (Bool -> Bool) -> Fold Text Bool
    forall a b x. (x -> a -> x) -> x -> (x -> b) -> Fold a b
    Control.Foldl.Fold Bool -> Text -> Bool
    step Bool
    True Bool -> Bool
    forall a. a -> a
    id
      where
        step :: Bool -> Text -> Bool
    step Bool
    isNull Text
    txt = Bool
    isNull Bool -> Bool -> Bool
    && Text -> Bool
    Data.Text.null Text
    txt
    {-# INLINABLE null #-}

    -- | Return the length of the text stream in characters
    length :: Num n => Fold Text n
    length :: forall n. Num n => Fold Text n
    length =
        (n -> Text -> n) -> n -> (n -> n) -> Fold Text n
    forall a b x. (x -> a -> x) -> x -> (x -> b) -> Fold a b
    Control.Foldl.Fold (\n
    n Text
    txt -> n
    n n -> n -> n
    forall a. Num a => a -> a -> a
    + Int -> n
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Text -> Int
    Data.Text.length Text
    txt)) n
    0 n -> n
    forall a. a -> a
    id
    {-# INLINABLE length #-}

    {-| @(all predicate)@ returns 'True' if all characters satisfy the predicate,
        'False' otherwise
    -}
    all :: (Char -> Bool) -> Fold Text Bool
    all :: (Char -> Bool) -> Fold Text Bool
    all Char -> Bool
    predicate =
        (Bool -> Text -> Bool) -> Bool -> (Bool -> Bool) -> Fold Text Bool
    forall a b x. (x -> a -> x) -> x -> (x -> b) -> Fold a b
    Control.Foldl.Fold (\Bool
    b Text
    txt -> Bool
    b Bool -> Bool -> Bool
    && (Char -> Bool) -> Text -> Bool
    Data.Text.all Char -> Bool
    predicate Text
    txt) Bool
    True Bool -> Bool
    forall a. a -> a
    id
    {-# INLINABLE all #-}

    {-| @(any predicate)@ returns 'True' if any character satisfies the predicate,
        'False' otherwise
    -}
    any :: (Char -> Bool) -> Fold Text Bool
    any :: (Char -> Bool) -> Fold Text Bool
    any Char -> Bool
    predicate =
        (Bool -> Text -> Bool) -> Bool -> (Bool -> Bool) -> Fold Text Bool
    forall a b x. (x -> a -> x) -> x -> (x -> b) -> Fold a b
    Control.Foldl.Fold (\Bool
    b Text
    txt -> Bool
    b Bool -> Bool -> Bool
    || (Char -> Bool) -> Text -> Bool
    Data.Text.any Char -> Bool
    predicate Text
    txt) Bool
    False Bool -> Bool
    forall a. a -> a
    id
    {-# INLINABLE any #-}

    -- | Computes the maximum character
    maximum :: Fold Text (Maybe Char)
    maximum :: Fold Text (Maybe Char)
    maximum = (Maybe' Char -> Text -> Maybe' Char)
    -> Maybe' Char
    -> (Maybe' Char -> Maybe Char)
    -> Fold Text (Maybe Char)
    forall a b x. (x -> a -> x) -> x -> (x -> b) -> Fold a b
    Control.Foldl.Fold Maybe' Char -> Text -> Maybe' Char
    step Maybe' Char
    forall a. Maybe' a
    Nothing' Maybe' Char -> Maybe Char
    forall a. Maybe' a -> Maybe a
    Control.Foldl.Internal.lazy
      where
        step :: Maybe' Char -> Text -> Maybe' Char
    step Maybe' Char
    mc Text
    txt =
            if Text -> Bool
    Data.Text.null Text
    txt
            then Maybe' Char
    mc
            else Char -> Maybe' Char
    forall a. a -> Maybe' a
    Just' (case Maybe' Char
    mc of
                Maybe' Char
    Nothing' -> HasCallStack => Text -> Char
    Text -> Char
    Data.Text.maximum Text
    txt
                Just' Char
    c -> Char -> Char -> Char
    forall a. Ord a => a -> a -> a
    max Char
    c (HasCallStack => Text -> Char
    Text -> Char
    Data.Text.maximum Text
    txt) )
    {-# INLINABLE maximum #-}

    -- | Computes the minimum character
    minimum :: Fold Text (Maybe Char)
    minimum :: Fold Text (Maybe Char)
    minimum = (Maybe' Char -> Text -> Maybe' Char)
    -> Maybe' Char
    -> (Maybe' Char -> Maybe Char)
    -> Fold Text (Maybe Char)
    forall a b x. (x -> a -> x) -> x -> (x -> b) -> Fold a b
    Control.Foldl.Fold Maybe' Char -> Text -> Maybe' Char
    step Maybe' Char
    forall a. Maybe' a
    Nothing' Maybe' Char -> Maybe Char
    forall a. Maybe' a -> Maybe a
    Control.Foldl.Internal.lazy
      where
        step :: Maybe' Char -> Text -> Maybe' Char
    step Maybe' Char
    mc Text
    txt =
            if Text -> Bool
    Data.Text.null Text
    txt
            then Maybe' Char
    mc
            else Char -> Maybe' Char
    forall a. a -> Maybe' a
    Just' (case Maybe' Char
    mc of
                Maybe' Char
    Nothing' -> HasCallStack => Text -> Char
    Text -> Char
    Data.Text.minimum Text
    txt
                Just' Char
    c -> Char -> Char -> Char
    forall a. Ord a => a -> a -> a
    min Char
    c (HasCallStack => Text -> Char
    Text -> Char
    Data.Text.minimum Text
    txt) )
    {-# INLINABLE minimum #-}

    {-| @(elem c)@ returns 'True' if the text stream has a character equal to @c@,
        'False' otherwise
    -}
    elem :: Char -> Fold Text Bool
    elem :: Char -> Fold Text Bool
    elem Char
    c = (Char -> Bool) -> Fold Text Bool
    any (Char
    c Char -> Char -> Bool
    forall a. Eq a => a -> a -> Bool
    ==)
    {-# INLINABLE elem #-}

    {-| @(notElem c)@ returns 'False' if the text stream has a character equal to
        @c@, 'True' otherwise
    -}
    notElem :: Char -> Fold Text Bool
    notElem :: Char -> Fold Text Bool
    notElem Char
    c = (Char -> Bool) -> Fold Text Bool
    all (Char
    c Char -> Char -> Bool
    forall a. Eq a => a -> a -> Bool
    /=)
    {-# INLINABLE notElem #-}

    {-| @(find predicate)@ returns the first character that satisfies the predicate
        or 'Nothing' if no character satisfies the predicate
    -}
    find :: (Char -> Bool) -> Fold Text (Maybe Char)
    find :: (Char -> Bool) -> Fold Text (Maybe Char)
    find Char -> Bool
    predicate = (Maybe' Char -> Text -> Maybe' Char)
    -> Maybe' Char
    -> (Maybe' Char -> Maybe Char)
    -> Fold Text (Maybe Char)
    forall a b x. (x -> a -> x) -> x -> (x -> b) -> Fold a b
    Control.Foldl.Fold Maybe' Char -> Text -> Maybe' Char
    step Maybe' Char
    forall a. Maybe' a
    Nothing' Maybe' Char -> Maybe Char
    forall a. Maybe' a -> Maybe a
    Control.Foldl.Internal.lazy
      where
        step :: Maybe' Char -> Text -> Maybe' Char
    step Maybe' Char
    mc Text
    txt = case Maybe' Char
    mc of
            Maybe' Char
    Nothing' -> Maybe Char -> Maybe' Char
    forall a. Maybe a -> Maybe' a
    strict ((Char -> Bool) -> Text -> Maybe Char
    Data.Text.find Char -> Bool
    predicate Text
    txt)
            Just' Char
    _  -> Maybe' Char
    mc
    {-# INLINABLE find #-}

    {-| @(index n)@ returns the @n@th character of the text stream, or 'Nothing' if
        the stream has an insufficient number of characters
    -}
    index :: Integral n => n -> Fold Text (Maybe Char)
    index :: forall n. Integral n => n -> Fold Text (Maybe Char)
    index n
    i = (Either' Int Char -> Text -> Either' Int Char)
    -> Either' Int Char
    -> (Either' Int Char -> Maybe Char)
    -> Fold Text (Maybe Char)
    forall a b x. (x -> a -> x) -> x -> (x -> b) -> Fold a b
    Control.Foldl.Fold Either' Int Char -> Text -> Either' Int Char
    step (Int -> Either' Int Char
    forall a b. a -> Either' a b
    Left' (n -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral n
    i)) Either' Int Char -> Maybe Char
    forall a b. Either' a b -> Maybe b
    hush
      where
        step :: Either' Int Char -> Text -> Either' Int Char
    step Either' Int Char
    x Text
    txt = case Either' Int Char
    x of
            Left' Int
    remainder ->
                let len :: Int
    len = Text -> Int
    Data.Text.length Text
    txt
                in  if Int
    remainder Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    < Int
    len
                    then Char -> Either' Int Char
    forall a b. b -> Either' a b
    Right' (HasCallStack => Text -> Int -> Char
    Text -> Int -> Char
    Data.Text.index Text
    txt Int
    remainder)
                    else Int -> Either' Int Char
    forall a b. a -> Either' a b
    Left'  (Int
    remainder Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    len)
            Either' Int Char
    _               -> Either' Int Char
    x
    {-# INLINABLE index #-}

    {-| @(elemIndex c)@ returns the index of the first character that equals @c@,
        or 'Nothing' if no character matches
    -}
    elemIndex :: Num n => Char -> Fold Text (Maybe n)
    elemIndex :: forall n. Num n => Char -> Fold Text (Maybe n)
    elemIndex Char
    c = (Char -> Bool) -> Fold Text (Maybe n)
    forall n. Num n => (Char -> Bool) -> Fold Text (Maybe n)
    findIndex (Char
    c Char -> Char -> Bool
    forall a. Eq a => a -> a -> Bool
    ==)
    {-# INLINABLE elemIndex #-}

    {-| @(findIndex predicate)@ returns the index of the first character that
        satisfies the predicate, or 'Nothing' if no character satisfies the
        predicate
    -}
    findIndex :: Num n => (Char -> Bool) -> Fold Text (Maybe n)
    findIndex :: forall n. Num n => (Char -> Bool) -> Fold Text (Maybe n)
    findIndex Char -> Bool
    predicate = (Either' n n -> Text -> Either' n n)
    -> Either' n n -> (Either' n n -> Maybe n) -> Fold Text (Maybe n)
    forall a b x. (x -> a -> x) -> x -> (x -> b) -> Fold a b
    Control.Foldl.Fold Either' n n -> Text -> Either' n n
    forall {b}. Num b => Either' b b -> Text -> Either' b b
    step (n -> Either' n n
    forall a b. a -> Either' a b
    Left' n
    0) Either' n n -> Maybe n
    forall a b. Either' a b -> Maybe b
    hush
      where
        step :: Either' b b -> Text -> Either' b b
    step Either' b b
    x Text
    txt = case Either' b b
    x of
            Left' b
    m -> case (Char -> Bool) -> Text -> Maybe Int
    Data.Text.findIndex Char -> Bool
    predicate Text
    txt of
                Maybe Int
    Nothing -> b -> Either' b b
    forall a b. a -> Either' a b
    Left'  (b
    m b -> b -> b
    forall a. Num a => a -> a -> a
    + Int -> b
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Text -> Int
    Data.Text.length Text
    txt))
                Just Int
    n  -> b -> Either' b b
    forall a b. b -> Either' a b
    Right' (b
    m b -> b -> b
    forall a. Num a => a -> a -> a
    + Int -> b
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    n)
            Either' b b
    _       -> Either' b b
    x
    {-# INLINABLE findIndex #-}

    -- | @(count c)@ returns the number of times @c@ appears
    count :: Num n => Char -> Fold Text n
    count :: forall n. Num n => Char -> Fold Text n
    count Char
    c = (n -> Text -> n) -> n -> (n -> n) -> Fold Text n
    forall a b x. (x -> a -> x) -> x -> (x -> b) -> Fold a b
    Control.Foldl.Fold n -> Text -> n
    forall {a}. Num a => a -> Text -> a
    step n
    0 n -> n
    forall a. a -> a
    id
      where
        step :: a -> Text -> a
    step a
    n Text
    txt = a
    n a -> a -> a
    forall a. Num a => a -> a -> a
    + Int -> a
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (HasCallStack => Text -> Text -> Int
    Text -> Text -> Int
    Data.Text.count (Char -> Text
    Data.Text.singleton Char
    c) Text
    txt)
    {-# INLINABLE count #-}

    -- | Combine all the strict `Text` chunks to build a lazy `Text`
    lazy :: Fold Text Data.Text.Lazy.Text
    lazy :: Fold Text Text
    lazy = ([Text] -> Text) -> Fold Text [Text] -> Fold Text Text
    forall a b. (a -> b) -> Fold Text a -> Fold Text b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap [Text] -> Text
    Data.Text.Lazy.fromChunks Fold Text [Text]
    forall a. Fold a [a]
    Control.Foldl.list
    {-# INLINABLE lazy #-}

    {- $reexports
        "Control.Foldl" re-exports the 'Fold' type

        @Data.Text@ re-exports the 'Text' type
    -}