content: {-# LANGUAGE ExplicitNamespaces #-}
  {-# LANGUAGE ImportQualifiedPost #-}
  {-# LANGUAGE LambdaCase #-}
  
  module RON.Prelude (
      module X,
      ByteStringL,
      fmapL,
      foldr1,
      headMay,
      lastDef,
      lastMay,
      maximumDef,
      maximumMay,
      maximumMayOn,
      maxOn,
      minimumDef,
      minimumMay,
      minimumMayOn,
      minOn,
      note,
      replicateM2,
      replicateM3,
      show,
      whenJust,
      (!!),
      (?:),
  ) where
  
  -- TODO import           RON.Prelude.Writer as X
  import Control.Monad.Writer.Strict as X (WriterT, runWriterT, tell)
  
  -- base
  import Control.Applicative as X (
      Alternative,
      Applicative,
      liftA2,
      many,
      optional,
      pure,
      some,
      (*>),
      (<*),
      (<*>),
      (<|>),
   )
  import Control.Arrow as X ((>>>))
  import Control.Exception as X (Exception)
  import Control.Monad as X (
      Monad,
      filterM,
      guard,
      unless,
      void,
      when,
      (<=<),
      (=<<),
      (>=>),
      (>>),
      (>>=),
   )
  import Control.Monad.Except as X (
      ExceptT (ExceptT),
      MonadError,
      catchError,
      liftEither,
      runExceptT,
      throwError,
   )
  import Control.Monad.Fail as X (MonadFail, fail)
  import Control.Monad.IO.Class as X (MonadIO, liftIO)
  import Control.Monad.Reader as X (
      MonadReader,
      ReaderT (ReaderT),
      ask,
      asks,
      reader,
      runReaderT,
   )
  import Control.Monad.State.Strict as X (
      MonadState,
      State,
      StateT,
      evalState,
      evalStateT,
      execStateT,
      get,
      gets,
      modify',
      put,
      runState,
      runStateT,
   )
  import Control.Monad.Trans as X (MonadTrans, lift)
  import Data.Bifunctor as X (bimap)
  import Data.Bool as X (Bool (False, True), not, otherwise, (&&), (||))
  import Data.ByteString as X (ByteString)
  import Data.Char as X (Char, chr, ord, toLower, toUpper)
  import Data.Coerce as X (Coercible, coerce)
  import Data.Data as X (Data)
  import Data.Either as X (Either (Left, Right), either)
  import Data.Eq as X (Eq, (/=), (==))
  import Data.Foldable as X (
      Foldable,
      all,
      and,
      any,
      asum,
      elem,
      fold,
      foldMap,
      foldl',
      foldr,
      for_,
      length,
      notElem,
      null,
      or,
      toList,
      traverse_,
   )
  import Data.Function as X (const, flip, id, on, ($), (&), (.))
  import Data.Functor as X (Functor, fmap, ($>), (<$), (<$>), (<&>))
  import Data.Functor.Identity as X (Identity)
  import Data.HashMap.Strict as X (HashMap)
  import Data.Hashable as X (Hashable, hash)
  import Data.IORef as X (IORef)
  import Data.Int as X (Int, Int16, Int32, Int64, Int8)
  import Data.List as X (
      drop,
      filter,
      genericLength,
      intercalate,
      isPrefixOf,
      isSuffixOf,
      lookup,
      map,
      partition,
      repeat,
      replicate,
      reverse,
      sort,
      sortBy,
      sortOn,
      span,
      splitAt,
      take,
      takeWhile,
      unlines,
      unwords,
      zip,
      zip3,
      zipWith,
      (++),
   )
  import Data.List.NonEmpty as X (NonEmpty ((:|)), nonEmpty)
  import Data.Map.Strict as X (Map)
  import Data.Maybe as X (
      Maybe (Just, Nothing),
      catMaybes,
      fromMaybe,
      listToMaybe,
      mapMaybe,
      maybe,
      maybeToList,
   )
  import Data.Monoid as X (Last (Last), Monoid, mempty)
  import Data.Ord as X (
      Down (Down),
      Ord,
      Ordering (EQ, GT, LT),
      compare,
      comparing,
      max,
      min,
      (<),
      (<=),
      (>),
      (>=),
   )
  import Data.Proxy as X (Proxy (Proxy))
  import Data.Ratio as X ((%))
  import Data.Semigroup as X (Semigroup, sconcat, (<>))
  import Data.Sequence as X (Seq)
  import Data.Set as X (Set)
  import Data.String as X (String)
  import Data.Text as X (Text)
  import Data.Time as X (UTCTime)
  import Data.Traversable as X (for, sequence, sequenceA, traverse)
  import Data.Tuple as X (fst, snd, uncurry)
  import Data.Type.Equality as X (type (~))
  import Data.Typeable as X (Typeable)
  import Data.Vector as X (Vector)
  import Data.Word as X (Word, Word16, Word32, Word64, Word8)
  import GHC.Enum as X (
      Bounded,
      Enum,
      fromEnum,
      maxBound,
      minBound,
      pred,
      succ,
      toEnum,
   )
  import GHC.Err as X (error, undefined)
  import GHC.Exts as X (Double)
  import GHC.Generics as X (Generic)
  import GHC.Integer as X (Integer)
  import GHC.Num as X (Num, negate, subtract, (*), (+), (-))
  import GHC.Real as X (
      Integral,
      fromIntegral,
      mod,
      realToFrac,
      round,
      (/),
      (^),
      (^^),
   )
  import GHC.Stack as X (HasCallStack)
  import System.IO as X (FilePath, IO)
  import Text.Read as X (readMaybe)
  import Text.Show as X (Show)
  
  --------------------------------------------------------------------------------
  
  import Data.ByteString.Lazy qualified as BSL
  import Data.Foldable qualified
  import Data.List (last, maximum, maximumBy, minimum, minimumBy)
  import Data.String (IsString, fromString)
  import Text.Show qualified
  
  type ByteStringL = BSL.ByteString
  
  fmapL :: (a -> b) -> Either a c -> Either b c
  fmapL f = either (Left . f) Right
  
  foldr1 :: (a -> a -> a) -> NonEmpty a -> a
  foldr1 = Data.Foldable.foldr1
  
  headMay :: [a] -> Maybe a
  headMay = \case
      [] -> Nothing
      a : _ -> Just a
  
  lastMay :: [a] -> Maybe a
  lastMay = \case
      [] -> Nothing
      x : xs -> Just $ lastMayImpl x xs
  
  lastMayImpl :: a -> [a] -> a
  lastMayImpl x = \case
      [] -> x
      y : ys -> lastMayImpl y ys
  
  lastDef :: a -> [a] -> a
  lastDef def = list' def last
  
  list' :: b -> ([a] -> b) -> [a] -> b
  list' onEmpty onNonEmpty = \case
      [] -> onEmpty
      xs -> onNonEmpty xs
  
  maximumDef :: (Ord a) => a -> [a] -> a
  maximumDef def = list' def maximum
  
  maximumMay :: (Ord a) => [a] -> Maybe a
  maximumMay = list' Nothing (Just . maximum)
  
  maximumMayOn :: (Ord b) => (a -> b) -> [a] -> Maybe a
  maximumMayOn key = list' Nothing (Just . maximumBy (comparing key))
  
  maxOn :: (Ord b) => (a -> b) -> a -> a -> a
  maxOn f x y = if f x < f y then y else x
  
  minimumDef :: (Ord a) => a -> [a] -> a
  minimumDef def = list' def minimum
  
  minimumMay :: (Ord a) => [a] -> Maybe a
  minimumMay = list' Nothing (Just . minimum)
  
  minimumMayOn :: (Ord b) => (a -> b) -> [a] -> Maybe a
  minimumMayOn key = list' Nothing (Just . minimumBy (comparing key))
  
  minOn :: (Ord b) => (a -> b) -> a -> a -> a
  minOn f x y = if f x < f y then x else y
  
  note :: e -> Maybe a -> Either e a
  note e = maybe (Left e) Right
  
  replicateM2 :: (Applicative m) => m a -> m (a, a)
  replicateM2 ma = (,) <$> ma <*> ma
  
  replicateM3 :: (Applicative m) => m a -> m (a, a, a)
  replicateM3 ma = (,,) <$> ma <*> ma <*> ma
  
  show :: (IsString s, Show a) => a -> s
  show = fromString . Text.Show.show
  
  whenJust :: (Applicative m) => Maybe a -> (a -> m ()) -> m ()
  whenJust m f = maybe (pure ()) f m
  
  (!!) :: [a] -> Int -> Maybe a
  xs !! i
      | i < 0 = Nothing
      | otherwise = headMay $ drop i xs
  
  -- | An infix form of 'fromMaybe' with arguments flipped.
  (?:) :: Maybe a -> a -> a
  maybeA ?: b = fromMaybe b maybeA
  {-# INLINEABLE (?:) #-}
  
  infixr 0 ?:
  