Jump to content

Haskell/Libraries/Maybe

From Wikibooks, open books for an open world

The Maybe data is used with functions that might be unsuccessful. The full description is in Maybe monad chapter.

Definition

[edit | edit source]

The Standard Prelude defines the Maybe type as follows:

data Maybe a = Nothing | Just a

Recall that the type a is polymorphic and can contain complex types or even other monads (such as IO () types).

Library functions

[edit | edit source]

The module Data.Maybe, in the standard hierarchical libraries, contains a wealth of functions for working with Maybe values.

Querying

[edit | edit source]

Two obvious functions give you information about a Maybe value:

isJust

[edit | edit source]

isJust returns True if when given an argument in the form Just _.

isJust :: Maybe a -> Bool
isJust (Just _) = True
isJust Nothing  = False

isNothing

[edit | edit source]

isNothing returns True if its argument is Nothing.

isNothing :: Maybe a -> Bool
isNothing (Just _) = False
isNothing Nothing  = True

Getting out

[edit | edit source]

There are a handful of functions for converting Maybe values to non-Maybe values.

maybe

[edit | edit source]

maybe applies a given function to the internal value passed by a Just but otherwise returns a default value when given Nothing.

maybe :: b -> (a -> b) -> Maybe a -> b
maybe _ f (Just x) = f x
maybe z _ Nothing  = z

fromMaybe

[edit | edit source]

We might want to use maybe without applying any function to the Just. We can do that by calling maybe with the function id. Data.Maybe already has this as fromMaybe:

fromMaybe :: a -> Maybe a -> a
fromMaybe z = maybe z id

Note the use of point-free style. maybe z id evaluates to a function that is ready to take a Maybe value.

Lists and Maybe

[edit | edit source]

The many similarities between lists and Maybe are discussed in the List monad chapter. Given the connections, there are a couple of functions for converting between one and the other:

listToMaybe

[edit | edit source]

Failed computations return [] for lists and Nothing for Maybe. listToMaybe converts from the list to the Maybe monad. As Maybe can only hold one value, listToMaybe only takes the first solution from a list.

listToMaybe :: [a] -> Maybe a
listToMaybe []    = Nothing
listToMaybe (x:_) = Just x

maybeToList

[edit | edit source]

The reverse listToMaybe is, of course, maybeToList:

maybeToList :: Maybe a -> [a]
maybeToList Nothing  = []
maybeToList (Just x) = [x]

Lists manipulation

[edit | edit source]

There are a couple of functions which are analogues of the normal Prelude list manipulation functions but are specialized to Maybe values.

Continue on some failures

[edit | edit source]

We might want an OR function that won't make a whole computation fail just because one part failed.

catMaybes
[edit | edit source]

Given a list of Maybe values, catMaybes extracts all the values in the form Just _, and strips off the Just constructors. List comprehension does the job here (as we showed in the pattern matching chapter):

catMaybes :: [Maybe a] -> [a]
catMaybes ms = [ x | Just x <- ms ]
mapMaybe
[edit | edit source]

mapMaybe applies a function to a list and collects the successes. It can be understood as a composition of functions you already know:

mapMaybe :: (a -> Maybe b) -> [a] -> [b]
mapMaybe f xs = catMaybes (map f xs)

However, the actual definition in Data.Maybe traverses the list is potentially more efficient:

mapMaybe :: (a -> Maybe b) -> [a] -> [b]
mapMaybe _ []     = []
mapMaybe f (x:xs) = 
  case f x of
    Just y  -> y : mapMaybe f xs
    Nothing -> mapMaybe f xs

Stop on failure

[edit | edit source]

Rather than OR, we might want to collect values if and only if all succeed.

sequence
[edit | edit source]
sequence :: [Maybe a] -> Maybe [a]
sequence []           = Just []
sequence (Nothing:xs) = Nothing
sequence (Just x:xs)  = case sequence xs of
  Just xs' -> Just (x:xs')
  _        -> Nothing