As others have said, ()
in Haskell is both the name of the "unit" type, and the only value of said type.
One of the confusing things in moving from imperative programming to Haskell is that the way the languages deal with the concept of "nothing" is different. What's more confusing is the vocabulary, because imperative languages and Haskell use the term "void" to mean diametrically different things.
In an imperative language, a "function" (which may not be a true mathematical function) may have "void" as its return type, as in this pseudocode example:
void sayHello() {
printLn("Hello!");
}
In this case, void
means that the "function," if it returns, will not produce a result value. (The other possibility is that they function may not return—it may loop forever, or fail with an error or exception.)
In Haskell, however, all functions (and IO
actions) must must produce a result. So when we write an IO
action that doesn't produce any interesting return value, we make it return ()
:
sayHello :: IO ()
sayHello = putStrLn "Hello!"
Later actions will just ignore the ()
result value.
Now, you probably don't need to worry too much about this, but there is one place where this gets confusing, which is that in Haskell there is a type called Void
, but it means something completely different from the imperative programming void
. Because of this, the word "void" becomes a minefield when comparing Haskell and imperative languages, because the meaning is completely different when you switch paradigms.
In Haskell, Void
is a type that doesn't have any values. The largest consequence of this is that in Haskell a function with return type Void
can never return, it can only fail with an error or loop forever. Why? Because the function would have produce a value of type Void
in order to return, but there isn't such a value.
This is however not relevant until you're working with some more advanced techniques, so you don't need to worry about it other than to beware of the word "void."
But the bigger lesson is that the imperative and the Haskell concepts of "no return value" are different. Haskell distinguishes between:
- Things that may return but whose result won't have any information (the
()
type);
- Things that cannot return, no matter what (the
Void
type).
The imperative void
corresponds to the former, and not the latter.