I'm at page 118 of the book "Learn You a Haskell for Great Good!"
It is written there:
ghci> :t Nothing Nothing :: Maybe a
Here is my question:
If I understand correctly, Nothing
is a value and only concrete types can have values, but Maybe a
is not a concrete type. So how can it have the value Nothing
?
The book also says:
Notice that the type of Nothing is Maybe a. Its type is polymorphic.
What does polymorphic type mean? How should I understand this? Is this not in contradiction with the rule that only concrete types can have values?
EDIT:
From the PDF version of the book :
We say that a type is concrete if it doesn't take any type parameters at all (like Int or Bool), or if it takes type parameters and they're all filled up (like Maybe Char). If you have some value, its type is always a concrete type.
The type has two constructors, Just a and Nothing . When a type has multiple constructors, it means that a value of the type must have been constructed with just one of the possible constructors. For this type, a value was either constructed via Just or Nothing , there are no other (non-error) possibilities.
From HaskellWiki. An empty type is one that has no values. They're often used with phantom types or type arithmetic.
In Haskell, every statement is considered as a mathematical expression and the category of this expression is called as a Type. You can say that "Type" is the data type of the expression used at compile time. To learn more about the Type, we will use the ":t" command.
The Haskell standard data type Maybe is typically declared as: data Maybe a = Just a | Nothing. What this means is that the type Maybe has one type variable, represented by the a and two constructors Just and Nothing. (Note that Haskell requires type names and constructor names to begin with an uppercase letter).
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).
Is this not in contradiction with the rule the only concrete types can have values?
Since functions are first-class values in Haskell, this purported rule would mean that polymorphic functions such as map
and foldr
would be impossible to implement.
There are, in fact, a lot of polymorphic non-function values in Haskell, such as
1 :: Num a => a Nothing :: Maybe a [] :: [a] Left 1 :: Num a => Either a b
etc. These values exist for every instantiation of a
(and b
).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With