Недавно я начал изучать F # и сталкивался с карьерами для простых примеров, таких как:
Рассмотрим функцию, которая вычисляет продажи, умножая цену p
на количество проданных единиц n
.
let sales (p,n) = p * (float n);;
Тип этой функции задается как
val sales : p:float * n:int -> float
то есть. возьмите пару float
и int
и верните a float
.
Вместо этого мы можем написать это как карриную функцию
let salesHi p n = p * (float n);;
Тип этой функции задается как
val salesHi : p:float -> n:int -> float
то есть. принимает значение float
и возвращает функцию от int
до float
.
В простых случаях это, по-видимому, не имеет значения
sales (0.99, 100);;
salesHi 0.99 100;;
Оба дают
val it : float = 99.0
Однако с помощью функции curried я могу указать цену для определенных элементов для получения новых функций. Например.
let salesBeer = salesHi 5.99;;
let salesWine = salesHi 14.99;;
Тогда salesBeer 2
дает 11.98
и salesWine 2
дает 29.98
.
Кроме того, я заметил, что встроенные операторы, такие как +
, определяются как функции, поэтому я могу написать, например:
let plus2 = (+) 2;
List.map plus2 [1;3;-1];;
и получим
val it : int list = [3; 5; 1]
Это похоже на хорошую вещь. Поэтому, когда я хочу реализовать функцию на императивном языке, который бы принял аргументы n > 1
, должен ли я, например, всегда использовать функцию curries в F # (если аргументы независимы)? Или я должен использовать простой маршрут и использовать регулярную функцию с помощью n
-tuple и curry позже, если это необходимо? Или что-то еще?
Как программисты F # решают, когда делать функцию в карри или использовать регулярную функцию с кортежем?