Agda-2.7.0: src/full/Agda/Utils/Null.hs
{-# OPTIONS_GHC -Wunused-imports #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
-- | Overloaded @null@ and @empty@ for collections and sequences.
module Agda.Utils.Null where
import Prelude hiding (null)
import Control.Monad ( when, unless )
import Control.Monad.Except ( ExceptT )
import Control.Monad.Identity ( Identity(..) )
import Control.Monad.Reader ( ReaderT )
import Control.Monad.State ( StateT )
import Control.Monad.Writer ( WriterT )
import Control.Monad.Trans ( lift )
import Data.Maybe ( isNothing )
import qualified Data.ByteString.Char8 as ByteStringChar8
import qualified Data.ByteString.Lazy as ByteStringLazy
import Data.HashMap.Strict (HashMap)
import qualified Data.HashMap.Strict as HashMap
import Data.HashSet (HashSet)
import qualified Data.HashSet as HashSet
import Data.IntMap (IntMap)
import qualified Data.IntMap as IntMap
import Data.IntSet (IntSet)
import qualified Data.IntSet as IntSet
import qualified Data.List as List
import Data.Map (Map)
import qualified Data.Map as Map
import Data.Sequence (Seq)
import qualified Data.Sequence as Seq
import Data.Set (Set)
import qualified Data.Set as Set
import Data.Text (Text)
import qualified Data.Text as Text
import Text.PrettyPrint.Annotated (Doc, isEmpty)
import Agda.Utils.Bag (Bag)
import qualified Agda.Utils.Bag as Bag
import Agda.Utils.Unsafe (unsafeComparePointers)
import Agda.Utils.Impossible
class Null a where
empty :: a
null :: a -> Bool
-- ^ Satisfying @null empty == True@.
-- | The default implementation of 'null' compares with 'empty',
-- first trying pointer equality, then falling back to 'Eq' equality.
default null :: Eq a => a -> Bool
null a = unsafeComparePointers a empty || a == empty
instance Null () where
empty = ()
null _ = True
instance (Null a, Null b) => Null (a,b) where
empty = (empty, empty)
null (a,b) = null a && null b
instance (Null a, Null b, Null c) => Null (a,b,c) where
empty = (empty, empty, empty)
null (a,b,c) = null a && null b && null c
instance (Null a, Null b, Null c, Null d) => Null (a,b,c,d) where
empty = (empty, empty, empty, empty)
null (a,b,c,d) = null a && null b && null c && null d
instance Null ByteStringChar8.ByteString where
empty = ByteStringChar8.empty
null = ByteStringChar8.null
instance Null ByteStringLazy.ByteString where
empty = ByteStringLazy.empty
null = ByteStringLazy.null
instance Null Text where
empty = Text.empty
null = Text.null
instance Null [a] where
empty = []
null = List.null
instance Null (Bag a) where
empty = Bag.empty
null = Bag.null
instance Null (IntMap a) where
empty = IntMap.empty
null = IntMap.null
instance Null IntSet where
empty = IntSet.empty
null = IntSet.null
instance Null (Map k a) where
empty = Map.empty
null = Map.null
instance Null (HashMap k a) where
empty = HashMap.empty
null = HashMap.null
instance Null (HashSet a) where
empty = HashSet.empty
null = HashSet.null
instance Null (Seq a) where
empty = Seq.empty
null = Seq.null
instance Null (Set a) where
empty = Set.empty
null = Set.null
-- | A 'Maybe' is 'null' when it corresponds to the empty list.
instance Null (Maybe a) where
empty = Nothing
null = isNothing
-- | Viewing 'Bool' as @'Maybe' ()@, a boolean is 'null' when it is false.
instance Null Bool where
empty = False
null = not
instance Null (Doc a) where
empty = mempty
null = isEmpty
instance Null a => Null (Identity a) where
empty = return empty
null = null . runIdentity
instance Null a => Null (IO a) where
empty = return empty
null = __IMPOSSIBLE__
instance (Null (m a), Monad m) => Null (ExceptT e m a) where
empty = lift empty
null = __IMPOSSIBLE__
instance (Null (m a), Monad m) => Null (ReaderT r m a) where
empty = lift empty
null = __IMPOSSIBLE__
instance (Null (m a), Monad m) => Null (StateT s m a) where
empty = lift empty
null = __IMPOSSIBLE__
instance (Null (m a), Monad m, Monoid w) => Null (WriterT w m a) where
empty = lift empty
null = __IMPOSSIBLE__
-- * Testing for null.
ifNull :: (Null a) => a -> b -> (a -> b) -> b
ifNull a b k = if null a then b else k a
ifNotNull :: (Null a) => a -> (a -> b) -> b -> b
ifNotNull a k b = ifNull a b k
ifNullM :: (Monad m, Null a) => m a -> m b -> (a -> m b) -> m b
ifNullM ma mb k = ma >>= \ a -> ifNull a mb k
ifNotNullM :: (Monad m, Null a) => m a -> (a -> m b) -> m b -> m b
ifNotNullM ma k mb = ifNullM ma mb k
whenNull :: (Monad m, Null a) => a -> m () -> m ()
whenNull = when . null
unlessNull :: (Monad m, Null a) => a -> (a -> m ()) -> m ()
unlessNull a k = unless (null a) $ k a
whenNullM :: (Monad m, Null a) => m a -> m () -> m ()
whenNullM ma k = ma >>= (`whenNull` k)
unlessNullM :: (Monad m, Null a) => m a -> (a -> m ()) -> m ()
unlessNullM ma k = ma >>= (`unlessNull` k)
applyUnlessNull :: (Null a) => a -> (a -> b -> b) -> (b -> b)
applyUnlessNull a f = if null a then id else f a