25
votes

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.

5
Pretty interesting question. Nothing is not a value, but constructor. Constructor is a function (well, not exactly) which is a value of certain type.user3974391
Function is a value of a certain type? How should I understand this? Could you please explain what you mean by this in some more detail?jhegedus
Maybe is not a concrete type and can't have values. Maybe a is a concrete type for any a. Nothing is a value for Maybe a for any a.Sassa NF
The book defines "concrete type" to mean "fully applied type constructor", or more formally, type of kind *. This is what seems to be causing all the confusion. According to the book's definition Maybe a is concrete, and Maybe alone is not. So there's absolutely no problem with Nothing being of type Maybe a. That being said, "concrete" is in no way an official term, and everybody uses it differently.kosmikus
This is a little bit subtle, and I am far from the most knowledgeable person here on this, but I do believe that in the language underlying Haskell (a variant of lambda calculus), Nothing is really of type /\a. Maybe a, meaning that if you give it a concrete type a you get a value of the concrete type Maybe a. However, this passing of the type a is implicit in Haskell.Tom Ellis

5 Answers

13
votes

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).

5
votes

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).

3
votes

In some sense, you're right. There are no values of type forall a.Maybe a. Every Maybe value you construct will actually have some definite type Maybe tau, where tau may be known or not, but is some definite type.

The notation Nothing :: forall a.Maybe a just tells us that whenever we use the expression Nothing, it will construct a value of the expected Maybe type.

1
votes

The Maybe type has two constructors: Nothing and Just a, where a is a type variable. Nothing itself does not determine (constrain) the type, but in any reasonable context you'll find something like (I do not claim it to be syntactically correct Haskell but something I would have written 10 years ago):

if (foo == 5)
then Nothing
else Just 5

And then type inference will tell you that (assume 5 was an argument to this code snippet 'foo' of type Int) that foo has type:

foo :: Int -> Maybe Int

But as the previous poster pointed out, Maybe a is a perfectly good type. You'll find the same non-issue with [] ie the list type with [] (the constructor for an empty list).

0
votes

This talk at 26:00 answers the question: "what is the type of [ ]?" which is a related question to "what is the type of Nothing?".

Also Hudak's book has a nice paragraph on this :

enter image description here