Когда выполняются вызовы функций F #; лениво или сразу?

Выполненные функции в F #. Я получаю бит, где передача в подмножестве параметров дает функцию с пресетами. Я просто задавался вопросом, не отличается ли все параметры. Например:

let addTwo x y = x + y
let incr a = addTwo 1
let added = addTwo 2 2

incr - это функция, принимающая один аргумент. Является ли added int или функцией? Я могу представить себе реализацию, где "добавлено" оценивается лениво только при использовании (например, Schroedinger Cat при открытии коробки). Есть ли гарантия того, когда добавление выполняется?

Ответы

Ответ 1

F # является нетерпеливо оцененным языком, поэтому выражение, подобное addTwo 2 2, будет немедленно оценено до значения типа int.

Haskell, напротив, лениво оценивается. Выражение типа addTwo 2 2 не будет оцениваться до тех пор, пока значение не понадобится. Однако тип выражения все равно будет единственным целым числом. Тем не менее, такое выражение, несмотря на его лень, не рассматривается как функция; в Haskell такое неоценимое выражение называется thunk. Это в основном означает "произвольно сложное выражение, которое еще не оценивалось".

Ответ 2

added не является функцией; это просто значение, которое вычисляется и привязывается к имени на месте. Функция всегда требует хотя бы одного параметра; если нет ничего полезного для передачи, это будет unit значение ():

let added () = addTwo 2 2

Ответ 3

incr - функция, принимающая один аргумент. Добавлен int или функция?

added, в этом случае, является именованным связыванием, которое оценивается как int. Это не функция.

Я могу представить себе реализацию, где "добавлено" оценивается лениво только при использовании (например, Schroedinger Cat при открытии коробки). Есть ли гарантия того, когда выполняется добавление?

Добавление будет выполняться немедленно при создании привязки. Нет лени.

Как описанный TeaDrivenDev, вы можете изменить added как связанную функцию вместо связанного значения, добавив параметр, который может быть unit:

let added () = addTwo 2 2

В этом случае это будет функция, поэтому добавление не произойдет, пока вы ее не назовете:

let result = added () // Call the function, bind output to result

Ответ 4

Нет. Но вроде да. Но на самом деле, нет.

Вы можете построить чистый функциональный язык, который имеет только функции и ничего другого. Лямбда-исчисление является полной алгеброй, поэтому существует теория. В этой модели added можно рассматривать как функцию без параметра (в отличие от, например, random(), где имеется один параметр единицы типа).

Но F # отличается. Поскольку это довольно прагматичное сочетание императивного и функционального программирования, результат не является функцией [1]. Вместо этого это значение, как локальное в С#. Это не деталь реализации - это фактически часть спецификации F #. У этого есть недостатки - это означает, что у него может быть двусмысленное определение, где определение может быть либо значением, либо определением функции (14.6.1).

[1] - Хотя в чистой функциональной программе вы не можете отличить ее - это то же самое, что просто делать замену функции с кешированным значением, что совершенно законно.