Почему некоторые функции 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 имеет побочные эффекты).