the Maybe
type is something you can combine with another type
Maybe
is not a type†. It's a type constructor, i.e. you can use it to generate a type. For instance, Maybe Float
is a type, but it's a different type from Float
as such. A Maybe Float
can not be used as a Float
because, well, maybe it doesn't contain one!
But to calculate the square root, you need a Float
. Well, no problem: in the Just
case, you can just unwrap it by pattern matching! But pattern matching automatically prevents you from trying to unwrap a Float
out of a Nothing
value, which, well, doesn't contain a float which you could compare to anything.
Incidentally, this does not mean you to need trace every possible failure by pattern matching, all the way through your code. Luckily, Maybe
is a monad. This means, if your function was a Kleisli arrow
maybe_sqrt :: Float -> Maybe Float
maybe_sqrt x
| x >= 0 = Just (sqrt x)
| otherwise = Nothing
(which is fine because it does accept a plain float) then you can still use this very easily with a Maybe Float
as the argument:
GHCi> maybe_sqrt =<< Just 4
Just 2.0
GHCi> maybe_sqrt =<< Just (-1)
Nothing
GHCi> maybe_sqrt =<< Nothing
Nothing
†As discussed in the comments, there is some disagreement on whether we should nevertheless call Maybe
type, or merely a type-level entity. As per research by Luis Casillas, it's actually rather Ok to call it a type.
Anyway: my point was that Maybe Float
is not “an OR-combination of the Maybe
type (giving failure) and the Float
type (giving values)”, but a completely new type with the structure of Maybe a
and the optionally-contained elements of Float
.