It's not in contradiction. Nothing
is a value, and its concrete type may be any possible instantiation of Maybe a
.
Otherwise said, values of type Maybe a
continue to have concrete types Maybe Int
, Maybe String
, Maybe Whatever
, and in particular, Nothing
is able to be typed by each of them, depending on the context. That's because its constructor, which is again called Nothing :: Maybe a
, does not take any parameters and therefore it can be called as-is to generate values of type Maybe a
. We will have one per concrete type, if you wish.
Without a context, of course ghci will give you the most general type it can infer for Nothing
, which is Maybe a
, but it's not its concrete type. That will depend on the individual expressions you will use Nothing
in. E.g.:
ghci> Nothing
Nothing
it :: Maybe a
This is what you probably typed, or something like that. There is no further context, therefore Nothing
doesn't get typed with a concrete type.
ghci> Nothing :: Maybe Int
Nothing
it :: Maybe Int
Here I forced it to assume the concrete type Maybe Int
.
ghci> 1 + fromMaybe 2 Nothing
3
it :: Integer
If I mix it with a sum of integers (fromMaybe :: a -> Maybe a -> a
takes a default value and a Maybe a
and returns either the value in the Just
or the default with Nothing
), then Nothing
will get typed as Maybe Integer
by the system, since you expect to extract an integer from it. There's none, so in this case we sum 1 with the default 2.
ghci> 1 + fromMaybe 2 (Nothing :: Maybe Integer)
3
it :: Integer
Same here, to double check. We force Nothing
to have the concrete type we assumed it had before in the same expression.
ghci> 1 + fromMaybe 2 (Nothing :: Maybe Char)
<interactive>:1:15:
No instance for (Num Char)
arising from the literal `2'
Possible fix: add an instance declaration for (Num Char)
In the first argument of `fromMaybe', namely `2'
In the second argument of `(+)', namely
`fromMaybe 2 (Nothing :: Maybe Char)'
In the expression: 1 + fromMaybe 2 (Nothing :: Maybe Char)
To triple-check, if we force it to assume another concrete type, as you see its value will be completely different, resulting in a type error (unlike C, in Haskell Char
doesn't act as a number).
Maybe
is not a concrete type and can't have values.Maybe a
is a concrete type for anya
.Nothing
is a value forMaybe a
for anya
. – Sassa NF*
. This is what seems to be causing all the confusion. According to the book's definitionMaybe a
is concrete, andMaybe
alone is not. So there's absolutely no problem withNothing
being of typeMaybe a
. That being said, "concrete" is in no way an official term, and everybody uses it differently. – kosmikusNothing
is really of type/\a. Maybe a
, meaning that if you give it a concrete typea
you get a value of the concrete typeMaybe a
. However, this passing of the typea
is implicit in Haskell. – Tom Ellis