    {-# LANGUAGE CPP
                ,MultiParamTypeClasses
                ,TypeFamilies
                ,FlexibleInstances #-}

    module Data.ListLike.Chars

    where

    import           Control.DeepSeq
    --import           Control.Monad
    import           Data.String as String (IsString)
    #if !MIN_VERSION_base(4,11,0)
    import Data.Semigroup (Semigroup(..))
    #endif
    import qualified Data.Text.Lazy as T
    --import qualified Data.Text.Lazy.IO as TI
    import qualified Data.Text.Lazy.Builder as Builder
    --import           Data.Text.Encoding (decodeUtf8)
    import           Data.ListLike.Base as LL
    import           Data.ListLike.FoldableLL as LL
    import           Data.ListLike.IO
    import           Data.ListLike.String as LL
    import           Data.ListLike.Text ()
    import           GHC.Exts (IsList(..))

    data Chars
        = B Builder.Builder
        | T T.Text
        deriving (Int -> Chars -> ShowS
    [Chars] -> ShowS
    Chars -> String
    (Int -> Chars -> ShowS)
    -> (Chars -> String) -> ([Chars] -> ShowS) -> Show Chars
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> Chars -> ShowS
    showsPrec :: Int -> Chars -> ShowS
    $cshow :: Chars -> String
    show :: Chars -> String
    $cshowList :: [Chars] -> ShowS
    showList :: [Chars] -> ShowS
    Show, Chars -> Chars -> Bool
    (Chars -> Chars -> Bool) -> (Chars -> Chars -> Bool) -> Eq Chars
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Chars -> Chars -> Bool
    == :: Chars -> Chars -> Bool
    $c/= :: Chars -> Chars -> Bool
    /= :: Chars -> Chars -> Bool
    Eq, Eq Chars
    Eq Chars =>
    (Chars -> Chars -> Ordering)
    -> (Chars -> Chars -> Bool)
    -> (Chars -> Chars -> Bool)
    -> (Chars -> Chars -> Bool)
    -> (Chars -> Chars -> Bool)
    -> (Chars -> Chars -> Chars)
    -> (Chars -> Chars -> Chars)
    -> Ord Chars
    Chars -> Chars -> Bool
    Chars -> Chars -> Ordering
    Chars -> Chars -> Chars
    forall a.
    Eq a =>
    (a -> a -> Ordering)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> Ord a
    $ccompare :: Chars -> Chars -> Ordering
    compare :: Chars -> Chars -> Ordering
    $c< :: Chars -> Chars -> Bool
    < :: Chars -> Chars -> Bool
    $c<= :: Chars -> Chars -> Bool
    <= :: Chars -> Chars -> Bool
    $c> :: Chars -> Chars -> Bool
    > :: Chars -> Chars -> Bool
    $c>= :: Chars -> Chars -> Bool
    >= :: Chars -> Chars -> Bool
    $cmax :: Chars -> Chars -> Chars
    max :: Chars -> Chars -> Chars
    $cmin :: Chars -> Chars -> Chars
    min :: Chars -> Chars -> Chars
    Ord)

    builder :: Chars -> Builder.Builder
    builder :: Chars -> Builder
    builder (B Builder
    x) = Builder
    x
    builder (T Text
    s) = Text -> Builder
    Builder.fromLazyText Text
    s
    {-# INLINE builder #-}

    instance Semigroup Chars where
      Chars
    a <> :: Chars -> Chars -> Chars
    <> Chars
    b = Builder -> Chars
    B (Builder -> Chars) -> Builder -> Chars
    forall a b. (a -> b) -> a -> b
    $ Chars -> Builder
    builder Chars
    a Builder -> Builder -> Builder
    forall a. Semigroup a => a -> a -> a
    <> Chars -> Builder
    builder Chars
    b

    instance Monoid Chars where
      mempty :: Chars
    mempty  = Builder -> Chars
    B Builder
    forall a. Monoid a => a
    mempty
      mappend :: Chars -> Chars -> Chars
    mappend = Chars -> Chars -> Chars
    forall a. Semigroup a => a -> a -> a
    (<>)

    instance String.IsString Chars where
      -- Builder already has an IsString instance, do we want to use it?
      -- fromString = B . String.fromString
      -- or do we want the implementation that used to be in the StringLike instance?
      fromString :: String -> Chars
    fromString = Builder -> Chars
    B (Builder -> Chars) -> (String -> Builder) -> String -> Chars
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> Builder
    Builder.fromLazyText (Text -> Builder) -> (String -> Text) -> String -> Builder
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> Text
    forall a. IsString a => String -> a
    LL.fromString

    instance FoldableLL Chars Char where
        foldl :: forall a. (a -> Char -> a) -> a -> Chars -> a
    foldl a -> Char -> a
    f a
    r0 (B Builder
    b) = (a -> Char -> a) -> a -> Text -> a
    forall a. (a -> Char -> a) -> a -> Text -> a
    forall full item a.
    FoldableLL full item =>
    (a -> item -> a) -> a -> full -> a
    LL.foldl a -> Char -> a
    f a
    r0 (Text -> a) -> (Builder -> Text) -> Builder -> a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Builder -> Text
    Builder.toLazyText (Builder -> a) -> Builder -> a
    forall a b. (a -> b) -> a -> b
    $ Builder
    b
        foldl a -> Char -> a
    f a
    r0 (T Text
    s) = (a -> Char -> a) -> a -> Text -> a
    forall a. (a -> Char -> a) -> a -> Text -> a
    forall full item a.
    FoldableLL full item =>
    (a -> item -> a) -> a -> full -> a
    LL.foldl a -> Char -> a
    f a
    r0 (Text -> a) -> Text -> a
    forall a b. (a -> b) -> a -> b
    $ Text
    s
        foldr :: forall b. (Char -> b -> b) -> b -> Chars -> b
    foldr Char -> b -> b
    f b
    r0 (B Builder
    b) = (Char -> b -> b) -> b -> Text -> b
    forall b. (Char -> b -> b) -> b -> Text -> b
    forall full item b.
    FoldableLL full item =>
    (item -> b -> b) -> b -> full -> b
    LL.foldr Char -> b -> b
    f b
    r0 (Text -> b) -> (Builder -> Text) -> Builder -> b
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Builder -> Text
    Builder.toLazyText (Builder -> b) -> Builder -> b
    forall a b. (a -> b) -> a -> b
    $ Builder
    b
        foldr Char -> b -> b
    f b
    r0 (T Text
    s) = (Char -> b -> b) -> b -> Text -> b
    forall b. (Char -> b -> b) -> b -> Text -> b
    forall full item b.
    FoldableLL full item =>
    (item -> b -> b) -> b -> full -> b
    LL.foldr Char -> b -> b
    f b
    r0 (Text -> b) -> Text -> b
    forall a b. (a -> b) -> a -> b
    $ Text
    s
        --
        foldl' :: forall a. (a -> Char -> a) -> a -> Chars -> a
    foldl' a -> Char -> a
    f a
    r0 (B Builder
    b) = (a -> Char -> a) -> a -> Text -> a
    forall a. (a -> Char -> a) -> a -> Text -> a
    forall full item a.
    FoldableLL full item =>
    (a -> item -> a) -> a -> full -> a
    LL.foldl' a -> Char -> a
    f a
    r0 (Text -> a) -> (Builder -> Text) -> Builder -> a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Builder -> Text
    Builder.toLazyText (Builder -> a) -> Builder -> a
    forall a b. (a -> b) -> a -> b
    $ Builder
    b
        foldl' a -> Char -> a
    f a
    r0 (T Text
    s) = (a -> Char -> a) -> a -> Text -> a
    forall a. (a -> Char -> a) -> a -> Text -> a
    forall full item a.
    FoldableLL full item =>
    (a -> item -> a) -> a -> full -> a
    LL.foldl' a -> Char -> a
    f a
    r0 (Text -> a) -> Text -> a
    forall a b. (a -> b) -> a -> b
    $ Text
    s
        foldl1 :: (Char -> Char -> Char) -> Chars -> Char
    foldl1 Char -> Char -> Char
    f (B Builder
    b) = (Char -> Char -> Char) -> Text -> Char
    forall full item.
    FoldableLL full item =>
    (item -> item -> item) -> full -> item
    LL.foldl1 Char -> Char -> Char
    f (Text -> Char) -> (Builder -> Text) -> Builder -> Char
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Builder -> Text
    Builder.toLazyText (Builder -> Char) -> Builder -> Char
    forall a b. (a -> b) -> a -> b
    $ Builder
    b
        foldl1 Char -> Char -> Char
    f (T Text
    s) = (Char -> Char -> Char) -> Text -> Char
    forall full item.
    FoldableLL full item =>
    (item -> item -> item) -> full -> item
    LL.foldl1 Char -> Char -> Char
    f (Text -> Char) -> Text -> Char
    forall a b. (a -> b) -> a -> b
    $ Text
    s
        foldr' :: forall b. (Char -> b -> b) -> b -> Chars -> b
    foldr' Char -> b -> b
    f b
    r0 (B Builder
    b) = (Char -> b -> b) -> b -> Text -> b
    forall b. (Char -> b -> b) -> b -> Text -> b
    forall full item b.
    FoldableLL full item =>
    (item -> b -> b) -> b -> full -> b
    LL.foldr' Char -> b -> b
    f b
    r0 (Text -> b) -> (Builder -> Text) -> Builder -> b
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Builder -> Text
    Builder.toLazyText (Builder -> b) -> Builder -> b
    forall a b. (a -> b) -> a -> b
    $ Builder
    b
        foldr' Char -> b -> b
    f b
    r0 (T Text
    s) = (Char -> b -> b) -> b -> Text -> b
    forall b. (Char -> b -> b) -> b -> Text -> b
    forall full item b.
    FoldableLL full item =>
    (item -> b -> b) -> b -> full -> b
    LL.foldr' Char -> b -> b
    f b
    r0 (Text -> b) -> Text -> b
    forall a b. (a -> b) -> a -> b
    $ Text
    s
        foldr1 :: (Char -> Char -> Char) -> Chars -> Char
    foldr1 Char -> Char -> Char
    f (B Builder
    b) = (Char -> Char -> Char) -> Text -> Char
    forall full item.
    FoldableLL full item =>
    (item -> item -> item) -> full -> item
    LL.foldr1 Char -> Char -> Char
    f (Text -> Char) -> (Builder -> Text) -> Builder -> Char
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Builder -> Text
    Builder.toLazyText (Builder -> Char) -> Builder -> Char
    forall a b. (a -> b) -> a -> b
    $ Builder
    b
        foldr1 Char -> Char -> Char
    f (T Text
    s) = (Char -> Char -> Char) -> Text -> Char
    forall full item.
    FoldableLL full item =>
    (item -> item -> item) -> full -> item
    LL.foldr1 Char -> Char -> Char
    f (Text -> Char) -> Text -> Char
    forall a b. (a -> b) -> a -> b
    $ Text
    s

    instance IsList Chars where
        type Item Chars = Char
        toList :: Chars -> [Item Chars]
    toList = Chars -> String
    Chars -> [Item Chars]
    forall full item. ListLike full item => full -> [item]
    LL.toList'
        fromList :: [Item Chars] -> Chars
    fromList = String -> Chars
    [Item Chars] -> Chars
    forall full item. ListLike full item => [item] -> full
    LL.fromList'

    instance ListLike Chars Char where
        singleton :: Char -> Chars
    singleton = Builder -> Chars
    B (Builder -> Chars) -> (Char -> Builder) -> Char -> Chars
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Char -> Builder
    Builder.singleton
        uncons :: Chars -> Maybe (Char, Chars)
    uncons (B Builder
    b) =
            case Text -> Maybe (Char, Text)
    forall full item. ListLike full item => full -> Maybe (item, full)
    LL.uncons (Builder -> Text
    Builder.toLazyText Builder
    b) of
              Maybe (Char, Text)
    Nothing -> Maybe (Char, Chars)
    forall a. Maybe a
    Nothing
              Just (Char
    c, Text
    s) -> (Char, Chars) -> Maybe (Char, Chars)
    forall a. a -> Maybe a
    Just (Char
    c, Text -> Chars
    T Text
    s)
        uncons (T Text
    s) =
            case Text -> Maybe (Char, Text)
    forall full item. ListLike full item => full -> Maybe (item, full)
    LL.uncons Text
    s of
              Maybe (Char, Text)
    Nothing -> Maybe (Char, Chars)
    forall a. Maybe a
    Nothing
              Just (Char
    c, Text
    s') -> (Char, Chars) -> Maybe (Char, Chars)
    forall a. a -> Maybe a
    Just (Char
    c, Text -> Chars
    T Text
    s')
        null :: Chars -> Bool
    null (B Builder
    b) = Text -> Bool
    forall full item. ListLike full item => full -> Bool
    LL.null (Text -> Bool) -> (Builder -> Text) -> Builder -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Builder -> Text
    Builder.toLazyText (Builder -> Bool) -> Builder -> Bool
    forall a b. (a -> b) -> a -> b
    $ Builder
    b
        null (T Text
    t) = Text -> Bool
    forall full item. ListLike full item => full -> Bool
    LL.null Text
    t

    instance ListLikeIO Chars Char where
        hGetLine :: Handle -> IO Chars
    hGetLine Handle
    h = Text -> Chars
    T (Text -> Chars) -> IO Text -> IO Chars
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Handle -> IO Text
    forall full item. ListLikeIO full item => Handle -> IO full
    hGetLine Handle
    h
        hGetContents :: Handle -> IO Chars
    hGetContents Handle
    h = Text -> Chars
    T (Text -> Chars) -> IO Text -> IO Chars
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Handle -> IO Text
    forall full item. ListLikeIO full item => Handle -> IO full
    hGetContents Handle
    h
        hGet :: Handle -> Int -> IO Chars
    hGet Handle
    h Int
    n = Text -> Chars
    T (Text -> Chars) -> IO Text -> IO Chars
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Handle -> Int -> IO Text
    forall full item. ListLikeIO full item => Handle -> Int -> IO full
    hGet Handle
    h Int
    n
        hGetNonBlocking :: Handle -> Int -> IO Chars
    hGetNonBlocking Handle
    h Int
    n = Text -> Chars
    T (Text -> Chars) -> IO Text -> IO Chars
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Handle -> Int -> IO Text
    forall full item. ListLikeIO full item => Handle -> Int -> IO full
    hGetNonBlocking Handle
    h Int
    n
        hPutStr :: Handle -> Chars -> IO ()
    hPutStr Handle
    h (B Builder
    b) = Handle -> Text -> IO ()
    forall full item. ListLikeIO full item => Handle -> full -> IO ()
    hPutStr Handle
    h (Text -> IO ()) -> (Builder -> Text) -> Builder -> IO ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Builder -> Text
    Builder.toLazyText (Builder -> IO ()) -> Builder -> IO ()
    forall a b. (a -> b) -> a -> b
    $ Builder
    b
        hPutStr Handle
    h (T Text
    s) = Handle -> Text -> IO ()
    forall full item. ListLikeIO full item => Handle -> full -> IO ()
    hPutStr Handle
    h (Text -> IO ()) -> Text -> IO ()
    forall a b. (a -> b) -> a -> b
    $ Text
    s

    instance StringLike Chars where
        toString :: Chars -> String
    toString (B Builder
    b) = Text -> String
    forall s. StringLike s => s -> String
    toString (Text -> String) -> (Builder -> Text) -> Builder -> String
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Builder -> Text
    Builder.toLazyText (Builder -> String) -> Builder -> String
    forall a b. (a -> b) -> a -> b
    $ Builder
    b
        toString (T Text
    s) = Text -> String
    forall s. StringLike s => s -> String
    toString (Text -> String) -> Text -> String
    forall a b. (a -> b) -> a -> b
    $ Text
    s
        fromLazyText :: StringLike Text => Text -> Chars
    fromLazyText = Builder -> Chars
    B (Builder -> Chars) -> (Text -> Builder) -> Text -> Chars
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> Builder
    Builder.fromLazyText
        fromText :: StringLike Text => Text -> Chars
    fromText = Builder -> Chars
    B (Builder -> Chars) -> (Text -> Builder) -> Text -> Chars
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> Builder
    Builder.fromText

    instance NFData Chars where
        rnf :: Chars -> ()
    rnf (B Builder
    b) = Text -> ()
    forall a. NFData a => a -> ()
    rnf (Text -> ()) -> (Builder -> Text) -> Builder -> ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Builder -> Text
    Builder.toLazyText (Builder -> ()) -> Builder -> ()
    forall a b. (a -> b) -> a -> b
    $ Builder
    b
        rnf (T Text
    s) = Text -> ()
    forall a. NFData a => a -> ()
    rnf Text
    s