{-# LANGUAGE CPP #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE Safe #-} {-# LANGUAGE DeriveGeneric #-} #if MIN_VERSION_base(4,9,0) #define LIFTED_FUNCTOR_CLASSES 1 #else #if MIN_VERSION_transformers(0,5,0) #define LIFTED_FUNCTOR_CLASSES 1 #else #if MIN_VERSION_transformers_compat(0,5,0) && !MIN_VERSION_transformers(0,4,0) #define LIFTED_FUNCTOR_CLASSES 1 #endif #endif #endif ----------------------------------------------------------------------------- -- | -- -- The strict variant of the standard Haskell 'L.Maybe' type and the -- corresponding variants of the functions from "Data.Maybe". -- -- Note that in contrast to the standard lazy 'L.Maybe' type, the strict -- 'Maybe' type is not an applicative functor, and therefore also not a monad. -- The problem is the /homomorphism/ law, which states that -- -- @'pure' f '<*>' 'pure' x = 'pure' (f x) -- must hold for all f@ -- -- This law does not hold for the expected applicative functor instance of -- 'Maybe', as this instance does not satisfy @pure f \<*\> pure _|_ = pure (f -- _|_)@ for @f = const@. -- ----------------------------------------------------------------------------- module Data.Strict.Maybe ( Maybe(..) , isJust , isNothing , fromJust , fromMaybe , maybe , listToMaybe , maybeToList , catMaybes , mapMaybe ) where -- import parts explicitly, helps with compatibility import Prelude (Functor (..), Eq (..), Ord (..), Show (..), Read (..), Bool (..), (.) ,error, Ordering (..), ($), showString, showParen, return, lex, readParen) import Control.Applicative (pure, (<$>)) import Data.Monoid (Monoid (..)) import Data.Semigroup (Semigroup (..)) import Data.Foldable (Foldable (..)) import Data.Traversable (Traversable (..)) -- Lazy variants import qualified Prelude as L import Control.DeepSeq (NFData (..)) import Data.Binary (Binary (..)) import Data.Hashable (Hashable(..)) import Data.Hashable.Lifted (Hashable1 (..)) import GHC.Generics (Generic) import Data.Data (Data (..), Typeable) #if __GLASGOW_HASKELL__ >= 706 import GHC.Generics (Generic1) #endif #if MIN_VERSION_deepseq(1,4,3) import Control.DeepSeq (NFData1 (..)) #endif #ifdef LIFTED_FUNCTOR_CLASSES import Data.Functor.Classes (Eq1 (..), Ord1 (..), Read1 (..), Show1 (..)) #else import Data.Functor.Classes (Eq1 (..), Ord1 (..), Read1 (..), Show1 (..)) #endif -- | The type of strict optional values. data Maybe a = Nothing | Just !a deriving (Eq, Ord, Read, Show, Typeable, Data, Generic #if __GLASGOW_HASKELL__ >= 706 , Generic1 #endif ) toStrict :: L.Maybe a -> Maybe a toStrict L.Nothing = Nothing toStrict (L.Just x) = Just x toLazy :: Maybe a -> L.Maybe a toLazy Nothing = L.Nothing toLazy (Just x) = L.Just x -- | Yields 'True' iff the argument is of the form @Just _@. isJust :: Maybe a -> Bool isJust Nothing = False isJust _ = True -- | Yields 'True' iff the argument is 'Nothing'. isNothing :: Maybe a -> Bool isNothing Nothing = True isNothing _ = False -- | Extracts the element out of a 'Just' and throws an error if the argument -- is 'Nothing'. fromJust :: Maybe a -> a fromJust Nothing = error "Data.Strict.Maybe.fromJust: Nothing" fromJust (Just x) = x -- | Given a default value and a 'Maybe', yield the default value if the -- 'Maybe' argument is 'Nothing' and extract the value out of the 'Just' -- otherwise. fromMaybe :: a -> Maybe a -> a fromMaybe x Nothing = x fromMaybe _ (Just y) = y -- | Given a default value, a function and a 'Maybe' value, yields the default -- value if the 'Maybe' value is 'Nothing' and applies the function to the -- value stored in the 'Just' otherwise. maybe :: b -> (a -> b) -> Maybe a -> b maybe x _ Nothing = x maybe _ f (Just y) = f y -- | Analogous to 'L.listToMaybe' in "Data.Maybe". listToMaybe :: [a] -> Maybe a listToMaybe [] = Nothing listToMaybe (a:_) = Just a -- | Analogous to 'L.maybeToList' in "Data.Maybe". maybeToList :: Maybe a -> [a] maybeToList Nothing = [] maybeToList (Just x) = [x] -- | Analogous to 'L.catMaybes' in "Data.Maybe". catMaybes :: [Maybe a] -> [a] catMaybes ls = [x | Just x <- ls] -- | Analogous to 'L.mapMaybe' in "Data.Maybe". mapMaybe :: (a -> Maybe b) -> [a] -> [b] mapMaybe _ [] = [] mapMaybe f (x:xs) = case f x of Nothing -> rs Just r -> r:rs where rs = mapMaybe f xs -- Instances ------------ instance Semigroup a => Semigroup (Maybe a) where Nothing <> m = m m <> Nothing = m Just x1 <> Just x2 = Just (x1 <> x2) #if MIN_VERSION_base(4,11,0) instance Semigroup a => Monoid (Maybe a) where mempty = Nothing #else instance Monoid a => Monoid (Maybe a) where mempty = Nothing Nothing `mappend` m = m m `mappend` Nothing = m Just x1 `mappend` Just x2 = Just (x1 `mappend` x2) #endif instance Functor Maybe where fmap _ Nothing = Nothing fmap f (Just x) = Just (f x) instance Foldable Maybe where foldMap _ Nothing = mempty foldMap f (Just x) = f x instance Traversable Maybe where traverse _ Nothing = pure Nothing traverse f (Just x) = Just <$> f x -- deepseq instance NFData a => NFData (Maybe a) where rnf = rnf . toLazy #if MIN_VERSION_deepseq(1,4,3) instance NFData1 Maybe where liftRnf rnfA = liftRnf rnfA . toLazy #endif -- binary instance Binary a => Binary (Maybe a) where put = put . toLazy get = toStrict <$> get -- hashable instance Hashable a => Hashable (Maybe a) where hashWithSalt salt = hashWithSalt salt . toLazy instance Hashable1 Maybe where liftHashWithSalt hashA salt = liftHashWithSalt hashA salt . toLazy -- Data.Functor.Classes #ifdef LIFTED_FUNCTOR_CLASSES instance Eq1 Maybe where liftEq f (Just a) (Just a') = f a a' liftEq _ Nothing Nothing = True liftEq _ _ _ = False instance Ord1 Maybe where liftCompare _ Nothing Nothing = EQ liftCompare _ Nothing (Just _) = LT liftCompare _ (Just _) Nothing = GT liftCompare f (Just a) (Just a') = f a a' instance Show1 Maybe where liftShowsPrec _ _ _ Nothing = showString "Nothing" liftShowsPrec sa _ d (Just a) = showParen (d > 10) $ showString "Just " . sa 11 a instance Read1 Maybe where liftReadsPrec ra _ d = readParen (d > 10) cons where cons s0 = do (ident, s1) <- lex s0 case ident of "Nothing" -> return (Nothing, s1) "Just" -> do (a, s2) <- ra 11 s1 return (Just a, s2) _ -> [] #else instance Eq1 Maybe where eq1 = (==) instance Ord1 Maybe where compare1 = compare instance Show1 Maybe where showsPrec1 = showsPrec instance Read1 Maybe where readsPrec1 = readsPrec #endif