2014-11-16 4 views
2

Я вижу эту функцию в книге Функциональное программирование в Swift , но я не понимаю эту подпись функции, что означает тип возврата этой функции?Swift: как вы понимаете эту функцию: func curry <A, B, C> (f: (A, B) -> C) -> A -> B -> C

func curry<A, B, C>(f: (A, B) -> C) -> A -> B -> C 
{ 
    return { x in { y in f(x, y) } } 
} 

Edit:

Является ли эта функция используется, как это?

fun add(a: Int, b: Int) -> Int { 
    return a + b 
} 

let curriedAdd = curry(add) 

//to add 1 and 2 
let resultOf1Plus2 = curriedAdd(1)(2) 
+0

о радости видеть Mac программистов задают вопросы о функциональных типах. ... спасибо яблоко! – nicolas

+0

Я нахожу в Swift, что удаление пробелов и добавление круглых скобок к составным типам делает такой код намного, многое, _much_ более легким для чтения. Поэтому я бы написал первую строку вашей функции как ** 'func curry (f: (A, B) -> C) -> (A) -> (B-> C)' ** –

+0

Кроме того, typealiases могут сделать функцию-тип-args намного легче читать, поэтому, если бы это был мой собственный код, я бы, вероятно, остановился на чем-то вроде ** 'typealias CurryInFunc = (A, B) -> C; typealias CurryOutFunc = (A) -> ((B) -> C); func curry (f: @escaping CurryInFunc ) -> CurryOutFunc {...} '** _ (тестирование и работа в Swift 3) _. –

ответ

2

Это функция, которая принимает один параметр типа (A, B) -> C (то есть функция, которая принимает два аргумента и возвращает один) и возвращает A -> B -> C (то есть, A -> (B -> C) то есть функция, которая принимает один аргумент и функция возвращает B -> C).

Currying «breaks» функция двух аргументов в два этапа. Currying two argument function дает функцию одиночного аргумента, которая возвращает еще одну функцию аргумента. Эта последняя функция эквивалентна исходной функции с первой привязкой к параметру.

Например (в псевдокоде, так как я не знаю Swift):

Наличие:

f: (X,Y) -> Z 
cf = curry(f) 

Тогда f(x,y) должно быть эквивалентно cf(x)(y) для любого x,y.

В вашем примере, resultOf1Plus2 должен дать 3. Тем не менее, вы можете «раскол» процесс в середине, и называют

let increment = curriedAdd(1) 
increment(2) // 3 
increment(5) // 6 
let addFive = curriedAdd(5) 
addFive(5) // 10 

, что невозможно с обычной add функции.

См Wikipedia article on currying

+0

Просто мое любопытство, A-> B-> C считается здесь A -> (B-> C), почему он не считается (A-> B) -> C, существуют ли здесь правила грамматики Swift? – CarmeloS

+0

Спасибо, я понимаю, карри, моя проблема - это подпись типа этой функции здесь, эту функцию следует понимать так, как в вашем ответе, моя проблема заключается в уровне грамматики. – CarmeloS

+2

См. [Документация по Apple] (https://developer.apple.com/library/ios/documentation/swift/conceptual/Swift_Programming_Language/Types.html#//apple_ref/doc/uid/TP40014097-CH31-XID_1117): "* * Типы функций функции curried сгруппированы справа налево **. Например, тип функции Int -> Int -> Int' понимается как «Int -> (Int -> Int)» - то есть, функция, которая принимает 'Int' и возвращает другую функцию, которая принимает и возвращает' Int'. –

1

curry принимает функцию, которая принимает пару аргументов tyes А и В, и возвращает C. Это завершает эту функцию таким образом, что результат curry является функцией, которая принимает единственный аргумент типа A и возвращает другую функцию. Эта другая функция принимает один аргумент типа B и возвращает значение C.

Эффект заключается в том, что, когда ранее вам приходилось одновременно поставлять как аргументы A, так и B, с версией в карри, вы может сначала поставить аргумент A и сохранить результат с захваченным значением A, а затем передать аргумент B позднее.

0

Это «эквивалент», чтобы иметь функцию из двух аргументов и иметь функцию одного аргумента tat возвращает функцию одного аргумента.

Способность переходить от одного к другому и обратно определяет то, что называется изоморфизмом.

в конце

curry . uncurry оставляет функция одного аргумента дает функцию одного аргумента нетронутой uncurry . curry оставляет функцию два аргументов нетронутых

Смежные вопросы