-- |
-- Module: Optics.Empty.Core
-- Description: A 'Prism' for a type that may be '_Empty'.
--
-- This module defines the 'AsEmpty' class, which provides a 'Prism' for a type
-- that may be '_Empty'.
--
-- Note that orphan instances for this class are defined in the @Optics.Empty@
-- module from @optics-extra@, so if you are not simply depending on @optics@
-- you may wish to import that module instead.
--
-- >>> isn't _Empty [1,2,3]
-- True
--
-- >>> case Nothing of { Empty -> True; _ -> False }
-- True
--
{-# LANGUAGE CPP #-}
module Optics.Empty.Core
  ( AsEmpty(..)
  , pattern Empty
  ) where

import Control.Applicative (ZipList(..))
import Data.Maybe (isNothing)
import Data.Monoid (Any (..), All (..), Product (..), Sum (..), Last (..), First (..), Dual (..))

import Data.Set (Set)
import qualified Data.Set as Set
import Data.IntMap (IntMap)
import qualified Data.IntMap as IntMap
import Data.IntSet (IntSet)
import qualified Data.IntSet as IntSet
import Data.Map (Map)
import qualified Data.Map as Map
import qualified Data.Sequence as Seq

import Data.Profunctor.Indexed

import Data.Maybe.Optics
import Optics.AffineTraversal
import Optics.Fold
import Optics.Iso
import Optics.Optic
import Optics.Prism
import Optics.Review

#if !defined(mingw32_HOST_OS) && !defined(ghcjs_HOST_OS)
import GHC.Event (Event)
#endif

-- | Class for types that may be '_Empty'.
--
class AsEmpty a where
  -- |
  --
  -- >>> isn't _Empty [1,2,3]
  -- True
  _Empty :: Prism' a ()
  default _Empty :: (Monoid a, Eq a) => Prism' a ()
  _Empty = forall a. Eq a => a -> Prism' a ()
only forall a. Monoid a => a
mempty
  {-# INLINE _Empty #-}

-- | Pattern synonym for matching on any type with an 'AsEmpty' instance.
--
-- >>> case Nothing of { Empty -> True; _ -> False }
-- True
--
pattern Empty :: forall a. AsEmpty a => a
pattern $bEmpty :: forall a. AsEmpty a => a
$mEmpty :: forall {r} {a}. AsEmpty a => a -> ((# #) -> r) -> ((# #) -> r) -> r
Empty <- (has _Empty -> True) where
  Empty = forall k (is :: IxList) t b.
Is k A_Review =>
Optic' k is t b -> b -> t
review forall a. AsEmpty a => Prism' a ()
_Empty ()

{- Default Monoid instances -}
instance AsEmpty Ordering
instance AsEmpty ()
instance AsEmpty Any
instance AsEmpty All
#if !defined(mingw32_HOST_OS) && !defined(ghcjs_HOST_OS)
instance AsEmpty Event
#endif
instance (Eq a, Num a) => AsEmpty (Product a)
instance (Eq a, Num a) => AsEmpty (Sum a)

instance AsEmpty (Maybe a) where
  _Empty :: Prism' (Maybe a) ()
_Empty = forall a. Prism' (Maybe a) ()
_Nothing
  {-# INLINE _Empty #-}

instance AsEmpty (Last a) where
  _Empty :: Prism' (Last a) ()
_Empty = forall a. a -> (a -> Bool) -> Prism' a ()
nearly (forall a. Maybe a -> Last a
Last forall a. Maybe a
Nothing) (forall a. Maybe a -> Bool
isNothing forall a b c. Coercible a b => (b -> c) -> (a -> b) -> a -> c
.# forall a. Last a -> Maybe a
getLast)
  {-# INLINE _Empty #-}

instance AsEmpty (First a) where
  _Empty :: Prism' (First a) ()
_Empty = forall a. a -> (a -> Bool) -> Prism' a ()
nearly (forall a. Maybe a -> First a
First forall a. Maybe a
Nothing) (forall a. Maybe a -> Bool
isNothing forall a b c. Coercible a b => (b -> c) -> (a -> b) -> a -> c
.# forall a. First a -> Maybe a
getFirst)
  {-# INLINE _Empty #-}

instance AsEmpty a => AsEmpty (Dual a) where
  _Empty :: Prism' (Dual a) ()
_Empty = forall s a b t. (s -> a) -> (b -> t) -> Iso s t a b
iso forall a. Dual a -> a
getDual forall a. a -> Dual a
Dual forall k l m (is :: IxList) (js :: IxList) (ks :: IxList) s t u v a
       b.
(JoinKinds k l m, AppendIndices is js ks) =>
Optic k is s t u v -> Optic l js u v a b -> Optic m ks s t a b
% forall a. AsEmpty a => Prism' a ()
_Empty
  {-# INLINE _Empty #-}

instance (AsEmpty a, AsEmpty b) => AsEmpty (a, b) where
  _Empty :: Prism' (a, b) ()
_Empty = forall b s a. (b -> s) -> (s -> Maybe a) -> Prism s s a b
prism'
    (\() -> (forall k (is :: IxList) t b.
Is k A_Review =>
Optic' k is t b -> b -> t
review forall a. AsEmpty a => Prism' a ()
_Empty (), forall k (is :: IxList) t b.
Is k A_Review =>
Optic' k is t b -> b -> t
review forall a. AsEmpty a => Prism' a ()
_Empty ()))
    (\(a
s, b
s') -> case forall k (is :: IxList) s t a b.
Is k An_AffineTraversal =>
Optic k is s t a b -> s -> Either t a
matching forall a. AsEmpty a => Prism' a ()
_Empty a
s of
        Right () -> case forall k (is :: IxList) s t a b.
Is k An_AffineTraversal =>
Optic k is s t a b -> s -> Either t a
matching forall a. AsEmpty a => Prism' a ()
_Empty b
s' of
          Right () -> forall a. a -> Maybe a
Just ()
          Left b
_   -> forall a. Maybe a
Nothing
        Left a
_   -> forall a. Maybe a
Nothing)
  {-# INLINE _Empty #-}

instance (AsEmpty a, AsEmpty b, AsEmpty c) => AsEmpty (a, b, c) where
  _Empty :: Prism' (a, b, c) ()
_Empty = forall b s a. (b -> s) -> (s -> Maybe a) -> Prism s s a b
prism'
    (\() -> (forall k (is :: IxList) t b.
Is k A_Review =>
Optic' k is t b -> b -> t
review forall a. AsEmpty a => Prism' a ()
_Empty (), forall k (is :: IxList) t b.
Is k A_Review =>
Optic' k is t b -> b -> t
review forall a. AsEmpty a => Prism' a ()
_Empty (), forall k (is :: IxList) t b.
Is k A_Review =>
Optic' k is t b -> b -> t
review forall a. AsEmpty a => Prism' a ()
_Empty ()))
    (\(a
s, b
s', c
s'') -> case forall k (is :: IxList) s t a b.
Is k An_AffineTraversal =>
Optic k is s t a b -> s -> Either t a
matching forall a. AsEmpty a => Prism' a ()
_Empty a
s of
        Right () -> case forall k (is :: IxList) s t a b.
Is k An_AffineTraversal =>
Optic k is s t a b -> s -> Either t a
matching forall a. AsEmpty a => Prism' a ()
_Empty b
s' of
          Right () -> case forall k (is :: IxList) s t a b.
Is k An_AffineTraversal =>
Optic k is s t a b -> s -> Either t a
matching forall a. AsEmpty a => Prism' a ()
_Empty c
s'' of
            Right () -> forall a. a -> Maybe a
Just ()
            Left c
_   -> forall a. Maybe a
Nothing
          Left b
_   -> forall a. Maybe a
Nothing
        Left a
_   -> forall a. Maybe a
Nothing)
  {-# INLINE _Empty #-}

instance AsEmpty [a] where
  _Empty :: Prism' [a] ()
_Empty = forall a. a -> (a -> Bool) -> Prism' a ()
nearly [] forall (t :: * -> *) a. Foldable t => t a -> Bool
Prelude.null
  {-# INLINE _Empty #-}

instance AsEmpty (ZipList a) where
  _Empty :: Prism' (ZipList a) ()
_Empty = forall a. a -> (a -> Bool) -> Prism' a ()
nearly (forall a. [a] -> ZipList a
ZipList []) (forall (t :: * -> *) a. Foldable t => t a -> Bool
Prelude.null forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. ZipList a -> [a]
getZipList)
  {-# INLINE _Empty #-}

instance AsEmpty (Map k a) where
  _Empty :: Prism' (Map k a) ()
_Empty = forall a. a -> (a -> Bool) -> Prism' a ()
nearly forall k a. Map k a
Map.empty forall k a. Map k a -> Bool
Map.null
  {-# INLINE _Empty #-}

instance AsEmpty (IntMap a) where
  _Empty :: Prism' (IntMap a) ()
_Empty = forall a. a -> (a -> Bool) -> Prism' a ()
nearly forall a. IntMap a
IntMap.empty forall a. IntMap a -> Bool
IntMap.null
  {-# INLINE _Empty #-}

instance AsEmpty (Set a) where
  _Empty :: Prism' (Set a) ()
_Empty = forall a. a -> (a -> Bool) -> Prism' a ()
nearly forall a. Set a
Set.empty forall a. Set a -> Bool
Set.null
  {-# INLINE _Empty #-}

instance AsEmpty IntSet where
  _Empty :: Prism' IntSet ()
_Empty = forall a. a -> (a -> Bool) -> Prism' a ()
nearly IntSet
IntSet.empty IntSet -> Bool
IntSet.null
  {-# INLINE _Empty #-}

instance AsEmpty (Seq.Seq a) where
  _Empty :: Prism' (Seq a) ()
_Empty = forall a. a -> (a -> Bool) -> Prism' a ()
nearly forall a. Seq a
Seq.empty forall a. Seq a -> Bool
Seq.null
  {-# INLINE _Empty #-}

-- $setup
-- >>> import Optics.Core