{-# LANGUAGE NoImplicitPrelude, UnicodeSyntax #-}

{-|
Module     : PreludePlus.Prelude
Copyright  : 2018 Joshua Booth
License    : BSD3 (see the file LICENSE)
Maintainer : Joshua Booth <joshua.n.booth@gmail.com>

Generalizes List functions to MonadPlus etc. and replaces partials and group(By) with NonEmpty equivalents.
-}
module PreludePlus (module Import, concat, concatMap, catMaybes, filter, fromList, mapMaybe, map, mapM, mapM_, sequence, sequence_) where

import PreludePlus.Unicode as Import
import Prelude             as Import hiding ((!!), (++), concat, concatMap, filter, head, last, map, mapM, mapM_, sequence, sequence_, tail, init)
import Data.Foldable       as Import hiding (concat, concatMap, mapM, mapM_, sequence, sequence_)
import Data.List           as Import hiding ((!!), (++), concat, concatMap, filter, group, groupBy, head, last, map, tail, init, insert)
import Data.List.NonEmpty  as Import (NonEmpty(..), (!!), group, groupBy, head, last, tail, init)
import Data.Maybe          as Import hiding (catMaybes, mapMaybe)

import Control.Applicative (Alternative)
import Control.Monad       (MonadPlus, mfilter, mzero)
import Data.Monoid         ((<>))

-- | '<>'
(++)  Semigroup a  a  a  a
(++) = (<>)

-- | 'asum'
concat  (Foldable t, Alternative f)  t (f a)  f a
concat = asum

-- | 'asum' . 'fmap'
concatMap  (Alternative f, Foldable t, Functor t)  (a  f b)  t a  f b
concatMap f = asum  fmap f

-- | Reduces a collection of Maybes to its Just values.
catMaybes  MonadPlus m  m (Maybe a)  m a
catMaybes xs = do
    x  xs
    case x of
      Just a   return a
      Nothing  mzero

-- | 'mfilter'
filter   MonadPlus m  (a  Bool)  m a  m a
filter = mfilter

-- | Transforms a list into any 'MonadPlus' using 'asum'.
fromList  MonadPlus m  [a]  m a
fromList = asum  fmap return

-- | 'fmap'
map  Functor f  (a  b)  f a  f b
map = fmap

-- | 'traverse'
mapM  (Applicative f, Traversable t)  (a  f b)  t a  f (t b)
mapM = traverse

-- | 'traverse_'
mapM_  (Foldable t, Applicative f)  (a  f b)  t a  f ()
mapM_ = traverse_

-- | 'catMaybes' . 'fmap'
mapMaybe  MonadPlus m  (a  Maybe b)  m a  m b
mapMaybe f = catMaybes  fmap f

-- | 'sequenceA'
sequence  (Traversable t, Applicative f)  t (f a)  f (t a)
sequence = sequenceA

-- | 'sequenceA_'
sequence_  (Foldable t, Applicative f)  t (f a)  f ()
sequence_ = sequenceA_