How to get the value of a Maybe in Haskell

[edit from Author, 6 years later] This is a needlessly long answer, and I'm not sure why it was accepted. Use maybe or Data.Maybe.fromMaybe as suggested in the highest upvoted answer. What follows is more of a thought experiment rather than practical advice.

So you're trying to create a function that works for a bunch of different types. This is a good time to make a class. If you've programmed in Java or C++, a class in Haskell is kind of like an interface in those languages.

class Nothingish a where
    nada :: a

This class defines a value nada, which is supposed to be the class's equivalent of Nothing. Now the fun part: making instances of this class!

instance Nothingish (Maybe a) where
    nada = Nothing

For a value of type Maybe a, the Nothing-like value is, well, Nothing! This will be a weird example in a minute. But before then, let's make lists an instance of this class too.

instance Nothingish [a] where
    nada = []

An empty list is kind of like Nothing, right? So for a String (which is a list of Char), it will return the empty string, "".

Numbers are also an easy implementation. You've already indicated that 0 obviously represents "Nothingness" for numbers.

instance (Num a) => Nothingish a where
    nada = 0

This one will actually not work unless you put a special line at the top of your file

{-# LANGUAGE FlexibleInstances, UndecidableInstances, OverlappingInstances #-}

Or when you compile it you can set the flags for these language pragmas. Don't worry about them, they're just magic that makes more stuff work.

So now you've got this class and these instances of it...now let's just re-write your function to use them!

eliminate :: (Nothingish a) => Maybe a -> a
eliminate (Just a) = a
eliminate Nothing  = nada

Notice I only changed 0 to nada, and the rest is the same. Let's give it a spin!

ghci> eliminate (Just 2)
2
ghci> eliminate (Just "foo")
"foo"
ghci> eliminate (Just (Just 3))
Just 3
ghci> eliminate (Just Nothing)
Nothing
ghci> :t eliminate
eliminate :: (Nothingish t) => Maybe t -> t
ghci> eliminate Nothing
error! blah blah blah...**Ambiguous type variable**

Looks great for values and stuff. Notice the (Just Nothing) turns into Nothing, see? That was a weird example, a Maybe in a Maybe. Anyways...what about eliminate Nothing? Well, the resultant type is ambiguous. It doesn't know what we are expecting. So we have to tell it what type we want.

ghci> eliminate Nothing :: Int
0

Go ahead and try it out for other types; you'll see it gets nada for each one. So now, when you use this function with your combine function, you get this:

ghci> let combine a b c = (eliminate a, eliminate b, eliminate c)
ghci> combine (Just 2) (Just "foo") (Just (Just 3))
(2,"foo",Just 3)
ghci> combine (Just 2) Nothing (Just 4)
error! blah blah Ambiguous Type blah blah

Notice you still have to indicate what type your "Nothing" is, or indicate what return type you expect.

ghci> combine (Just 2) (Nothing :: Maybe Int) (Just 4)
(2,0,4)
ghci> combine (Just 2) Nothing (Just 4) :: (Int, Int, Int)
(2,0,4)

Or, you could restrict the types that your function allows by putting its type signature explicitly in the source. This makes sense if the logical use of the function would be that it is only used with parameters of the same type.

combine :: (Nothingish a) => Maybe a -> Maybe a -> Maybe a -> (a,a,a)
combine a b c = (eliminate a, eliminate b, eliminate c)

Now it only works if all three Maybe things are the same type. That way, it will infer that the Nothing is the same type as the others.

ghci> combine (Just 2) Nothing (Just 4)
(2,0,4)

No ambiguity, yay! But now it is an error to mix and match, like we did before.

ghci> combine (Just 2) (Just "foo") (Just (Just 3))
error! blah blah  Couldn't match expected type  blah blah
blah blah blah    against inferred type         blah blah

Well, I think that was a sufficiently long and overblown answer. Enjoy.


From the standard Prelude,

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

Given a default value, and a function, apply the function to the value in the Maybe or return the default value.

Your eliminate could be written maybe 0 id, e.g. apply the identity function, or return 0.

From the standard Data.Maybe,

fromJust :: Maybe a -> a
fromJust Nothing = error "Maybe.fromJust: Nothing"
fromJust (Just x) = x

This is a partial function (does not return a value for every input, as opposed to a total function, which does), but extracts the value when possible.


I'm new to Haskell too, so I don't know if this exists in the platform yet (I'm sure it does), but how about a "get or else" function to get a value if it exists, else return a default?

getOrElse::Maybe a -> a -> a
getOrElse (Just v) d = v
getOrElse Nothing d  = d