13

In some Haskell code I came across:

put :: s -> m ()

What does the () mean here?

I'd use a search engine, but I can't find one that handles () correctly.

Lara
  • 2,594
  • 4
  • 24
  • 36
  • Possible duplicate of [() in Function Variable and Application](http://stackoverflow.com/questions/29970012/in-function-variable-and-application) –  Oct 14 '15 at 08:47
  • @Elyse, I don't see that question as an ideal dup target. It's a bit muddled. – dfeuer Oct 16 '15 at 14:50

4 Answers4

38

() means "Boring". It means the boring type which contains one thing, also boring. There is nothing interesting to be gained by comparing one element of the boring type with another, because there is nothing to learn about an element of the boring type by giving it any of your attention.

It is very different from the empty type, called (by people I wish had chosen a better name like the one I suggested) in Haskell Void. The empty type is very exciting, because if somebody ever gives you a value belonging to it, you know that you are already dead and in Heaven and that anything you want is yours.

But if somebody gives you a value in (), don't get excited. Just throw it away.

Sometimes it's fun to take type constructors parametrised by an "element type" and fill the parameter in with (). You can see just what information is inherent in the type constructor, rather than coming from the elements. E.g, Maybe () is a version of Bool, with Just () or Nothing. Also, [()] amounts to the (possibly infinite) natural numbers: the only information you have is a length.

So, () means "Boring", but it's often a clue that something interesting is happening somewhere else.

pigworker
  • 43,025
  • 18
  • 121
  • 214
  • 3
    What was your suggestion? `False`? `Initial`? `Ridiculous`? – dfeuer Oct 14 '15 at 06:59
  • 1
    May I suggest "died in an explosion and gone to heaven"? – dfeuer Oct 14 '15 at 07:17
  • 3
    The only place where `()` is `Reassuring` rather than `Boring` would be [`rnf`](https://hackage.haskell.org/package/deepseq-1.4.1.2/docs/Control-DeepSeq.html#v:rnf). –  Nov 07 '15 at 13:27
  • 1
    @dfeuer The principle of explosion, I presume. – PyRulez Nov 25 '15 at 21:12
  • @PyRulez, yes, that's the idea. Ex falso quodlibet. – dfeuer Nov 26 '15 at 04:03
  • 1
    I just realized that `Void` is itself dually boring as a contravariant argument. Having something of type `Void -> A` is as boring as having something of type `()`. This can also be used to think about surrounding structure. For example, given `data Foo a = Foo Int (a -> Bool)`, `Foo Void` is pretty much the same a `Int`; there's a function in there, but you can never call it. – dfeuer Feb 23 '18 at 20:41
20

If not for the weird special syntax, it could be defined as

data () = ()

It's about the most boring type there is. The syntax is supposed to make you think of tuples: (a,b) is a pair, (a,b,c) is a triple, etc., and () is a 0-tuple. The only thing missing is a 1-tuple, which can't have that syntax because it would clash with the usual use of parentheses.

() is very often used as the result of something that has no interesting result. For example, an IO action that is supposed to perform some I/O and terminate without producing a result will typically have type IO (). It can also be used when you need some uninteresting input; GHC has special syntax for this, but in Haskell 98 the way to mimic Lisp's cond is like this:

case () of
  () | c1 -> e1
     | c2 -> e2
     ...
     | otherwise -> e3

It's perfectly valid, but also perfectly boring, to ask what value of type () you have; there's only one legitimate one that you could have.

From the "Haskell-as-almost-category" standpoint, () is a final object. That is, for any type X, there is exactly one legitimate function of type X -> (), namely const (). From the other direction, the Void type pigworker mentions is an initial object. For any type X, there is exactly one legitimate function of type Void -> X, namely absurd. If you're in the mood for categorical reasoning, initial and final objects can be useful to have around.

dfeuer
  • 48,079
  • 5
  • 63
  • 167
6

It's called the "unit type". You can think of it as Haskell's equivalent of void, in some respects. It's a type that has only one value (also ()).

mipadi
  • 398,885
  • 90
  • 523
  • 479
  • 3
    FTR, it's Haskell's equivalent of _what C-like languages call `void`_... except it's not really a type at all in those languages. Also, “void” a bit of a misnomer, since the unit type is not in fact empty. Haskell also has a [`Void` type](http://hackage.haskell.org/package/base-4.8.1.0/docs/Data-Void.html), which is really empty (and that means, it behaves very different from `()` or C-style `void`). – leftaroundabout Oct 13 '15 at 21:52
  • 4
    The whole `Void` in Haskell versus `void` in C and `()` in Agda versus `()` in Haskell makes me sad. When I proposed the type that is now `Void` in Haskell, I called it `Zero` which is more evocative, if only by counting its (non-bottom) inhabitants. I'm (pleasantly) surprised that it's in the library at all. It was a practical joke, by which I mean I suggested it as a joke, but it's also practical. – pigworker Oct 14 '15 at 02:07
  • 2
    @pigworker: perhaps your practical jokes [need to get a bit less subtle](https://xkcd.com/516/)... — I agree that `Zero` would probably be a less confusing name to the general programmer populace, but if it weren't for C, the `Void` name would be perfectly fine. Of course, what would be really good is if Haskell named the free ADT types consequently – in particular, `Either` should always have been `+`! – leftaroundabout Oct 14 '15 at 08:43
  • "`Either`" is better than "`+`", for the general programmer populace. You need to be a mathematician to understand what "`+`" type means, but "`Either`" actually *explains* what it is. – Will Ness Aug 23 '18 at 07:10
5

There are excellent search engines specialised for Haskell.

http://hayoo.fh-wedel.de/?query=() will give you immediately the correct answer:

Data ()
ghc-prim -GHC.Tuple


The unit datatype () has one non-undefined member, the nullary constructor ().
leftaroundabout
  • 117,950
  • 5
  • 174
  • 319