{-# LANGUAGE LambdaCase #-}

module RON.Prelude (
    module X,
    ByteStringL,
    fmapL,
    foldr1,
    headMay,
    lastDef,
    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.Exception as X (Exception, catch, evaluate, throwIO)
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, 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.Hashable as X (Hashable, hash)
import           Data.HashMap.Strict as X (HashMap)
import           Data.Int as X (Int, Int16, Int32, Int64, Int8)
import           Data.IORef as X (IORef, atomicModifyIORef', newIORef,
                                  readIORef, writeIORef)
import           Data.List as X (drop, filter, genericLength, intercalate,
                                 isPrefixOf, isSuffixOf, lookup, map, partition,
                                 repeat, replicate, sort, sortBy, sortOn, span,
                                 splitAt, take, takeWhile, unlines, unwords,
                                 zip, 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.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 qualified Data.ByteString.Lazy as BSL
import qualified Data.Foldable
import           Data.List (last, maximum, maximumBy, minimum, minimumBy)
import           Data.String (IsString, fromString)
import qualified Text.Show

type ByteStringL = BSL.ByteString

fmapL :: (a -> b) -> Either a c -> Either b c
fmapL :: (a -> b) -> Either a c -> Either b c
fmapL a -> b
f = (a -> Either b c) -> (c -> Either b c) -> Either a c -> Either b c
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (b -> Either b c
forall a b. a -> Either a b
Left (b -> Either b c) -> (a -> b) -> a -> Either b c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> b
f) c -> Either b c
forall a b. b -> Either a b
Right

foldr1 :: (a -> a -> a) -> NonEmpty a -> a
foldr1 :: (a -> a -> a) -> NonEmpty a -> a
foldr1 = (a -> a -> a) -> NonEmpty a -> a
forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
Data.Foldable.foldr1

headMay :: [a] -> Maybe a
headMay :: [a] -> Maybe a
headMay = \case
    []  -> Maybe a
forall a. Maybe a
Nothing
    a
a:[a]
_ -> a -> Maybe a
forall a. a -> Maybe a
Just a
a

lastDef :: a -> [a] -> a
lastDef :: a -> [a] -> a
lastDef a
def = a -> ([a] -> a) -> [a] -> a
forall b a. b -> ([a] -> b) -> [a] -> b
list' a
def [a] -> a
forall a. [a] -> a
last

list' :: b -> ([a] -> b) -> [a] -> b
list' :: b -> ([a] -> b) -> [a] -> b
list' b
onEmpty [a] -> b
onNonEmpty = \case
    [] -> b
onEmpty
    [a]
xs -> [a] -> b
onNonEmpty [a]
xs

maximumDef :: Ord a => a -> [a] -> a
maximumDef :: a -> [a] -> a
maximumDef a
def = a -> ([a] -> a) -> [a] -> a
forall b a. b -> ([a] -> b) -> [a] -> b
list' a
def [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum

maximumMay :: Ord a => [a] -> Maybe a
maximumMay :: [a] -> Maybe a
maximumMay = Maybe a -> ([a] -> Maybe a) -> [a] -> Maybe a
forall b a. b -> ([a] -> b) -> [a] -> b
list' Maybe a
forall a. Maybe a
Nothing (a -> Maybe a
forall a. a -> Maybe a
Just (a -> Maybe a) -> ([a] -> a) -> [a] -> Maybe a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum)

maximumMayOn :: Ord b => (a -> b) -> [a] -> Maybe a
maximumMayOn :: (a -> b) -> [a] -> Maybe a
maximumMayOn a -> b
key = Maybe a -> ([a] -> Maybe a) -> [a] -> Maybe a
forall b a. b -> ([a] -> b) -> [a] -> b
list' Maybe a
forall a. Maybe a
Nothing (a -> Maybe a
forall a. a -> Maybe a
Just (a -> Maybe a) -> ([a] -> a) -> [a] -> Maybe a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> a -> Ordering) -> [a] -> a
forall (t :: * -> *) a.
Foldable t =>
(a -> a -> Ordering) -> t a -> a
maximumBy ((a -> b) -> a -> a -> Ordering
forall a b. Ord a => (b -> a) -> b -> b -> Ordering
comparing a -> b
key))

maxOn :: Ord b => (a -> b) -> a -> a -> a
maxOn :: (a -> b) -> a -> a -> a
maxOn a -> b
f a
x a
y = if a -> b
f a
x b -> b -> Bool
forall a. Ord a => a -> a -> Bool
< a -> b
f a
y then a
y else a
x

minimumDef :: Ord a => a -> [a] -> a
minimumDef :: a -> [a] -> a
minimumDef a
def = a -> ([a] -> a) -> [a] -> a
forall b a. b -> ([a] -> b) -> [a] -> b
list' a
def [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
minimum

minimumMay :: Ord a => [a] -> Maybe a
minimumMay :: [a] -> Maybe a
minimumMay = Maybe a -> ([a] -> Maybe a) -> [a] -> Maybe a
forall b a. b -> ([a] -> b) -> [a] -> b
list' Maybe a
forall a. Maybe a
Nothing (a -> Maybe a
forall a. a -> Maybe a
Just (a -> Maybe a) -> ([a] -> a) -> [a] -> Maybe a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
minimum)

minimumMayOn :: Ord b => (a -> b) -> [a] -> Maybe a
minimumMayOn :: (a -> b) -> [a] -> Maybe a
minimumMayOn a -> b
key = Maybe a -> ([a] -> Maybe a) -> [a] -> Maybe a
forall b a. b -> ([a] -> b) -> [a] -> b
list' Maybe a
forall a. Maybe a
Nothing (a -> Maybe a
forall a. a -> Maybe a
Just (a -> Maybe a) -> ([a] -> a) -> [a] -> Maybe a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> a -> Ordering) -> [a] -> a
forall (t :: * -> *) a.
Foldable t =>
(a -> a -> Ordering) -> t a -> a
minimumBy ((a -> b) -> a -> a -> Ordering
forall a b. Ord a => (b -> a) -> b -> b -> Ordering
comparing a -> b
key))

minOn :: Ord b => (a -> b) -> a -> a -> a
minOn :: (a -> b) -> a -> a -> a
minOn a -> b
f a
x a
y = if a -> b
f a
x b -> b -> Bool
forall a. Ord a => a -> a -> Bool
< a -> b
f a
y then a
x else a
y

note :: e -> Maybe a -> Either e a
note :: e -> Maybe a -> Either e a
note e
e = Either e a -> (a -> Either e a) -> Maybe a -> Either e a
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (e -> Either e a
forall a b. a -> Either a b
Left e
e) a -> Either e a
forall a b. b -> Either a b
Right

replicateM2 :: Applicative m => m a -> m (a, a)
replicateM2 :: m a -> m (a, a)
replicateM2 m a
ma = (,) (a -> a -> (a, a)) -> m a -> m (a -> (a, a))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m a
ma m (a -> (a, a)) -> m a -> m (a, a)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> m a
ma

replicateM3 :: Applicative m => m a -> m (a, a, a)
replicateM3 :: m a -> m (a, a, a)
replicateM3 m a
ma = (,,) (a -> a -> a -> (a, a, a)) -> m a -> m (a -> a -> (a, a, a))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m a
ma m (a -> a -> (a, a, a)) -> m a -> m (a -> (a, a, a))
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> m a
ma m (a -> (a, a, a)) -> m a -> m (a, a, a)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> m a
ma

show :: (Show a, IsString s) => a -> s
show :: a -> s
show = String -> s
forall a. IsString a => String -> a
fromString (String -> s) -> (a -> String) -> a -> s
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> String
forall a. Show a => a -> String
Text.Show.show

whenJust :: Applicative m => Maybe a -> (a -> m ()) -> m ()
whenJust :: Maybe a -> (a -> m ()) -> m ()
whenJust Maybe a
m a -> m ()
f = m () -> (a -> m ()) -> Maybe a -> m ()
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (() -> m ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()) a -> m ()
f Maybe a
m

(!!) :: [a] -> Int -> Maybe a
[a]
xs !! :: [a] -> Int -> Maybe a
!! Int
i
    | Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0     = Maybe a
forall a. Maybe a
Nothing
    | Bool
otherwise = [a] -> Maybe a
forall a. [a] -> Maybe a
headMay ([a] -> Maybe a) -> [a] -> Maybe a
forall a b. (a -> b) -> a -> b
$ Int -> [a] -> [a]
forall a. Int -> [a] -> [a]
drop Int
i [a]
xs

-- | An infix form of 'fromMaybe' with arguments flipped.
(?:) :: Maybe a -> a -> a
Maybe a
maybeA ?: :: Maybe a -> a -> a
?: a
b = a -> Maybe a -> a
forall a. a -> Maybe a -> a
fromMaybe a
b Maybe a
maybeA
{-# INLINABLE (?:) #-}
infixr 0 ?: