Почему некоторые функции OCaml принимают() в качестве параметра?

Пример в модуле Unix:

val environment : unit -> string array

Почему не просто:

val environment : string array

?

Ответы

Ответ 1

Потому что он обозначает функцию, которая принимает значение единицы типа в качестве своего параметра. Тип устройства заселен только значением "()". Обычно это означает, что функция выполняет какой-то IO или вызывает побочный эффект и не нуждается в вводе. Подпись второго типа, которую вы указали, является сигнатурой для значения, а не функцией, которая может быть применена. Если какое-то выражение привязано к этому имени, это выражение будет оцениваться в момент привязки значения, а не в момент его ссылки (как в случае с приложением функции).

Ответ 2

Параметр unit () аналогичен параметру void в C. Он обозначает функцию, которая не использует свой аргумент для вычисления чего-либо.

В вашем примере среда может быть изменена программой, поэтому она не может быть просто статическим значением, вычисленным в начале программы, но в то же время его значение не зависит от его аргумента.

Например:

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

И вы можете видеть, что e1 и e2 разные, поэтому Unix.environment не может быть только типа (string * string) array, но должен быть функцией.

Ответ 3

Если бы вы были на ленивом языке, таком как Haskell, без побочных эффектов и объектов, которые оценивались только по мере необходимости, не было бы необходимости в этих фиктивных аргументах.

В OCaml требуется аргумент типа unit (единственное значение которого ()) служит для замораживания вычисления до тех пор, пока не будет предоставлен аргумент. В этом случае он замораживает вычисление до тех пор, пока не будет вычислено значение Unix.environment (), что особенно важно, поскольку оно может иметь разные значения во времени (опять же, OCaml имеет побочные эффекты).