{-# LANGUAGE Trustworthy #-} {-# LANGUAGE NoImplicitPrelude #-} ----------------------------------------------------------------------------- -- | -- Module : Data.Maybe -- Copyright : (c) The University of Glasgow 2001 -- License : BSD-style (see the file libraries/base/LICENSE) -- -- Maintainer : [email protected] -- Stability : stable -- Portability : portable -- -- The Maybe type, and associated operations. -- ----------------------------------------------------------------------------- module Data.Maybe ( Maybe(Nothing,Just) , maybe , isJust , isNothing , fromJust , fromMaybe , listToMaybe , maybeToList , catMaybes , mapMaybe ) where import GHC.Base -- $setup -- Allow the use of some Prelude functions in doctests. -- >>> import Prelude ( (*), odd, show, sum ) -- --------------------------------------------------------------------------- -- Functions over Maybe -- | The 'maybe' function takes a default value, a function, and a 'Maybe' -- value. If the 'Maybe' value is 'Nothing', the function returns the -- default value. Otherwise, it applies the function to the value inside -- the 'Just' and returns the result. -- -- ==== __Examples__ -- -- Basic usage: -- -- >>> maybe False odd (Just 3) -- True -- -- >>> maybe False odd Nothing -- False -- -- Read an integer from a string using 'readMaybe'. If we succeed, -- return twice the integer; that is, apply @(*2)@ to it. If instead -- we fail to parse an integer, return @0@ by default: -- -- >>> import Text.Read ( readMaybe ) -- >>> maybe 0 (*2) (readMaybe "5") -- 10 -- >>> maybe 0 (*2) (readMaybe "") -- 0 -- -- Apply 'show' to a @Maybe Int@. If we have @Just n@, we want to show -- the underlying 'Int' @n@. But if we have 'Nothing', we return the -- empty string instead of (for example) \"Nothing\": -- -- >>> maybe "" show (Just 5) -- "5" -- >>> maybe "" show Nothing -- "" -- maybe :: b -> (a -> b) -> Maybe a -> b maybe n _ Nothing = n maybe _ f (Just x) = f x -- | The 'isJust' function returns 'True' iff its argument is of the -- form @Just _@. -- -- ==== __Examples__ -- -- Basic usage: -- -- >>> isJust (Just 3) -- True -- -- >>> isJust (Just ()) -- True -- -- >>> isJust Nothing -- False -- -- Only the outer constructor is taken into consideration: -- -- >>> isJust (Just Nothing) -- True -- isJust :: Maybe a -> Bool isJust Nothing = False isJust _ = True -- | The 'isNothing' function returns 'True' iff its argument is 'Nothing'. -- -- ==== __Examples__ -- -- Basic usage: -- -- >>> isNothing (Just 3) -- False -- -- >>> isNothing (Just ()) -- False -- -- >>> isNothing Nothing -- True -- -- Only the outer constructor is taken into consideration: -- -- >>> isNothing (Just Nothing) -- False -- isNothing :: Maybe a -> Bool isNothing Nothing = True isNothing _ = False -- | The 'fromJust' function extracts the element out of a 'Just' and -- throws an error if its argument is 'Nothing'. -- -- ==== __Examples__ -- -- Basic usage: -- -- >>> fromJust (Just 1) -- 1 -- -- >>> 2 * (fromJust (Just 10)) -- 20 -- -- >>> 2 * (fromJust Nothing) -- *** Exception: Maybe.fromJust: Nothing -- fromJust :: Maybe a -> a fromJust Nothing = errorWithoutStackTrace "Maybe.fromJust: Nothing" -- yuck fromJust (Just x) = x -- | The 'fromMaybe' function takes a default value and and 'Maybe' -- value. If the 'Maybe' is 'Nothing', it returns the default values; -- otherwise, it returns the value contained in the 'Maybe'. -- -- ==== __Examples__ -- -- Basic usage: -- -- >>> fromMaybe "" (Just "Hello, World!") -- "Hello, World!" -- -- >>> fromMaybe "" Nothing -- "" -- -- Read an integer from a string using 'readMaybe'. If we fail to -- parse an integer, we want to return @0@ by default: -- -- >>> import Text.Read ( readMaybe ) -- >>> fromMaybe 0 (readMaybe "5") -- 5 -- >>> fromMaybe 0 (readMaybe "") -- 0 -- fromMaybe :: a -> Maybe a -> a fromMaybe d x = case x of {Nothing -> d;Just v -> v} -- | The 'maybeToList' function returns an empty list when given -- 'Nothing' or a singleton list when not given 'Nothing'. -- -- ==== __Examples__ -- -- Basic usage: -- -- >>> maybeToList (Just 7) -- [7] -- -- >>> maybeToList Nothing -- [] -- -- One can use 'maybeToList' to avoid pattern matching when combined -- with a function that (safely) works on lists: -- -- >>> import Text.Read ( readMaybe ) -- >>> sum $ maybeToList (readMaybe "3") -- 3 -- >>> sum $ maybeToList (readMaybe "") -- 0 -- maybeToList :: Maybe a -> [a] maybeToList Nothing = [] maybeToList (Just x) = [x] -- | The 'listToMaybe' function returns 'Nothing' on an empty list -- or @'Just' a@ where @a@ is the first element of the list. -- -- ==== __Examples__ -- -- Basic usage: -- -- >>> listToMaybe [] -- Nothing -- -- >>> listToMaybe [9] -- Just 9 -- -- >>> listToMaybe [1,2,3] -- Just 1 -- -- Composing 'maybeToList' with 'listToMaybe' should be the identity -- on singleton/empty lists: -- -- >>> maybeToList $ listToMaybe [5] -- [5] -- >>> maybeToList $ listToMaybe [] -- [] -- -- But not on lists with more than one element: -- -- >>> maybeToList $ listToMaybe [1,2,3] -- [1] -- listToMaybe :: [a] -> Maybe a listToMaybe [] = Nothing listToMaybe (a:_) = Just a -- | The 'catMaybes' function takes a list of 'Maybe's and returns -- a list of all the 'Just' values. -- -- ==== __Examples__ -- -- Basic usage: -- -- >>> catMaybes [Just 1, Nothing, Just 3] -- [1,3] -- -- When constructing a list of 'Maybe' values, 'catMaybes' can be used -- to return all of the \"success\" results (if the list is the result -- of a 'map', then 'mapMaybe' would be more appropriate): -- -- >>> import Text.Read ( readMaybe ) -- >>> [readMaybe x :: Maybe Int | x <- ["1", "Foo", "3"] ] -- [Just 1,Nothing,Just 3] -- >>> catMaybes $ [readMaybe x :: Maybe Int | x <- ["1", "Foo", "3"] ] -- [1,3] -- catMaybes :: [Maybe a] -> [a] catMaybes ls = [x | Just x <- ls] -- | The 'mapMaybe' function is a version of 'map' which can throw -- out elements. In particular, the functional argument returns -- something of type @'Maybe' b@. If this is 'Nothing', no element -- is added on to the result list. If it is @'Just' b@, then @b@ is -- included in the result list. -- -- ==== __Examples__ -- -- Using @'mapMaybe' f x@ is a shortcut for @'catMaybes' $ 'map' f x@ -- in most cases: -- -- >>> import Text.Read ( readMaybe ) -- >>> let readMaybeInt = readMaybe :: String -> Maybe Int -- >>> mapMaybe readMaybeInt ["1", "Foo", "3"] -- [1,3] -- >>> catMaybes $ map readMaybeInt ["1", "Foo", "3"] -- [1,3] -- -- If we map the 'Just' constructor, the entire list should be returned: -- -- >>> mapMaybe Just [1,2,3] -- [1,2,3] -- mapMaybe :: (a -> Maybe b) -> [a] -> [b] mapMaybe _ [] = [] mapMaybe f (x:xs) = let rs = mapMaybe f xs in case f x of Nothing -> rs Just r -> r:rs {-# NOINLINE [1] mapMaybe #-} {-# RULES "mapMaybe" [~1] forall f xs. mapMaybe f xs = build (\c n -> foldr (mapMaybeFB c f) n xs) "mapMaybeList" [1] forall f. foldr (mapMaybeFB (:) f) [] = mapMaybe f #-} {-# NOINLINE [0] mapMaybeFB #-} mapMaybeFB :: (b -> r -> r) -> (a -> Maybe b) -> a -> r -> r mapMaybeFB cons f x next = case f x of Nothing -> next Just r -> cons r next