Вы делаете свою функцию карри.
Это как раз тот случай, когда curry , который является техникой для формулирования ваших функций таким образом, чтобы они принимали параметры, так сказать, «один за другим». Математически такая функция принимает ровно один параметр и возвращает другую функцию, которая принимает второй параметр. Как то так:
let curriedPowInt = fun n -> fun x -> powInt (x, n)
Этот способ определения функций является обычным явлением. На самом деле, он настолько важен для самой природы ML-языков (из которых F #), что для него существует специальный синтаксис:
let curriedPowInt n x = powInt (x, n)
Посмотрите, как я просто перечисляю свои параметры в одной строке, разделяя их пробелом, например n x =
? Это синтаксический сахар для fun n -> fun x ->
. Логически он определяет функцию, которая принимает параметры «один за другим», а не оба сразу как кортеж.
Теперь, когда у вас есть такая функция, вы можете частично применить it - то есть дать ей только один параметр, а не оба:
let pow2 = curriedPowInt 2
Это работает, потому что - помните? - моя функция curriedPowInt
принимает n
и возвращает другую функцию, которая принимает x
. Тип pow2
теперь int -> int
. Это функция, которая принимает int
и повышает его до второй степени.
И, конечно, вы также можете использовать этот трюк:
let powIntList (xs: int list) = List.map (curriedPowInt n) xs
Также обратите внимание, как я изменил порядок параметров. Сначала я поставил параметр n
, а последним параметр x
. Это общее правило, делающее ваши функции более полезными: ваш «самый важный» параметр ставится последним, а «наименее важный» - первым. Например, посмотрите на List.map
: список, над которым он работает, является последним аргументом двух.
Наконец, вместо объявления powInt
, а затем отдельно curriedPowInt
, я рекомендую вообще не объявлять первое. Просто сделайте все ваши функции карри. Функции карри гораздо полезнее. На самом деле, я так редко видел случаи, когда неиспользуемые функции были бы полезны, и с таким же успехом никогда не видел.
Итак, подведем итог:
let powInt n x =
let rec loop acc n =
match n with
| 0 -> acc
| v -> loop (acc * x) (v-1)
loop 1 n
let powIntList (xs: int list) = List.map (powInt n) xs