17

Example in Unix module:

val environment : unit -> string array

Why not just:

val environment : string array

?

BenMorel
  • 34,448
  • 50
  • 182
  • 322
qrest
  • 3,083
  • 3
  • 25
  • 26

3 Answers3

19

Because it denotes a function that takes a value of type unit as its parameter. The unit type is only inhabited by the value "()". This is usually used to mean that the function is going to perform some kind of IO or induce a side-effect, and needs no input. The second type signature you provided is the signature for a value, not a function that can be applied. If some expression were bound to this name, that expression would be evaluated at the time the value binding takes place, not at the time it is referenced (as is the case with function application).

Gian
  • 13,735
  • 44
  • 51
  • 4
    So the difference is that, by having a function take *some* parameter, you force evaluation to be done when it is referenced, hence getting the IO to be effected at the time intended? – qrest Aug 16 '10 at 15:43
  • 6
    Precisely! Unit just provides a convenient value to act as a parameter. For this reason it is often use in this context, because it's a value but doesn't really represent anything meaningful. I kinda used weasel words when I said "referenced". I should have said "applied" (functions are values, and therefore names with functions bound to them can be referenced without being applied). – Gian Aug 16 '10 at 15:53
4

The unit () parameter is similar to a void parameter in C. It denotes a function that does not use its argument to compute something.

In your example, the environment can be changed by the program, so it cannot just be a static value computed at the beginning of the program, but at the same time, its value does not depend on its argument.

For example:

let e1 = Unix.environment ();;
Unix.putenv "USER" "somebody_else";;
let e2 = Unix.environment ();;
e1 = e2;;

And you can see that e1 and e2 are different, so Unix.environment cannot just be of type (string * string) array, but needs to be a function.

Fabrice Le Fessant
  • 4,222
  • 23
  • 36
0

If you were in a lazy language, such as Haskell, with no side effects and objects being evaluated only when needed, there would be no need for these dummy arguments.

In OCaml, requiring an argument of type unit (whose only value is ()) serves to freeze the computation until the argument is supplied. In this case, it freezes the computation until Unix.environment () is to be computed — which is especially important since it can have different values throughout time (again, OCaml has side effects).

David Monniaux
  • 1,948
  • 12
  • 23
  • Does not quite sound correct. OCaml functions always take one parameter, so if evaluation were lazy it would not change anything to the need to provide a parameter. – Str. Aug 03 '15 at 18:41