Карри функции F#
У меня есть вопрос, касающийся двух типов int -> (int -> int) и (int -> int) -> int. В чем разница между этими двумя?
Где-то здесь я читал, что первое можно интерпретировать как функцию, которая принимает int и возвращает функцию, которая принимает и int и возвращает int, что совпадает с int -> int -> int. Это правильно?
4 ответа
Разница между int -> (int -> int)
а также int -> int -> int
ничтожно мал (вам действительно будет важно, если вам придется взаимодействовать с другим языком). Это карри функции, которые эффективно принимают два целых числа и возвращают целое число (например, встроенный оператор сложения имеет тип вдоль этих строк).
Тем не менее, оба они очень отличаются от (int -> int) -> int
, который берет функцию из целых чисел в целые и возвращает целое число. Как уже упоминалось, единственный простой пример такой функции - применить данную функцию к определенному значению (например, fun (f:int->int) -> f 13
).
Хороший вопрос, я подозреваю, что функционально нет большой разницы. Я потратил некоторое время, пытаясь понять, как вообще получить эти две подписи. (Джон Палмер let fun1 i = fun j -> i + j
просто дает int -> int -> int
для меня)
let add a b = a + b // int -> int -> int
let inc a = add a // int -> (int -> int)
Я не мог придумать необдуманный пример для второй подписи:
let foo fn : int -> fn 1 // (int -> int) -> int
(Это не дает прямого ответа на ваш вопрос, но может дать кому-то что-то, что можно пережевывать)
Я действительно не знаю F#, но это кажется довольно интуитивным (многие другие языки имеют те же понятия).
- Функция принимает int и возвращает функцию, которая принимает int и возвращает int
- Является ли функция, принимающая функцию, которая принимает int и возвращает int, и возвращает int
Первое было бы как функция карри.
Итак, давайте посмотрим, как будут выглядеть реализации:
первый
let func1 i = fun j -> i+j
это имеет подпись int -> (int -> int)
Обратите внимание, что func1 2 3
не должно работать
РЕДАКТИРОВАТЬ: Оказывается, из-за того, как ассоциативность работает, это на самом деле хорошо
но это отличается от
let func2 i j= i+j
который имеет тип int -> int -> int
Вот func2 1 2
Это хорошо
другой пример, который мы можем создать так:
let func4 a = a 1
это будет иметь подпись ('t->int) -> u
выбирая бетон a
буду работать. Обратите внимание, что func4 1 2
точно не скомпилируется