Swift:您如何理解此函数签名:func curry<;A、 B、C>;(f)(A、B)——>;C)——>;A->;B->;C

Swift:您如何理解此函数签名:func curry<;A、 B、C>;(f)(A、B)——>;C)——>;A->;B->;C,swift,Swift,我在Swift函数编程一书中看到了这个函数,但我不理解这个函数签名,这个函数的返回类型是什么意思 func curry<A, B, C>(f: (A, B) -> C) -> A -> B -> C { return { x in { y in f(x, y) } } } 它是一个函数,它接受一个(a,B)->C类型的参数(即接受两个参数并返回一个参数的函数),然后返回a->B->C(即,a->(B->C),即接受一个参数并返回函数B->C) c

我在Swift函数编程一书中看到了这个函数,但我不理解这个函数签名,这个函数的返回类型是什么意思

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

它是一个函数,它接受一个
(a,B)->C类型的参数(即接受两个参数并返回一个参数的函数),然后返回
a->B->C
(即,
a->(B->C)
,即接受一个参数并返回函数
B->C

curry将两个参数函数“打断”为两个步骤。对两个参数函数进行curry运算将生成返回另一个单参数函数的单参数函数。最后一个函数等价于第一个参数有界的原始函数

例如(在伪代码中,我不知道Swift):

具有:

f: (X,Y) -> Z
cf = curry(f)
然后,对于任何
x,y
,f(x,y)
应等同于
cf(x)(y)

在您的示例中,
resultOf1Plus2
应该产生3。但是,你可以“分裂”中间的过程,并调用< /P>
let increment = curriedAdd(1)
increment(2) // 3
increment(5) // 6
let addFive = curriedAdd(5)
addFive(5) // 10
使用普通的
add
功能是不可能的


请参见

curry
接受一个函数,该函数接受一对类型为a和B的参数,并返回一个C。 它以这样的方式包装此函数:
curry
的结果是一个函数,它接受一个类型为a的参数并返回另一个函数。另一个函数接受一个类型为B的参数,并返回一个C


其效果是,在以前必须同时向原始函数提供A和B参数的情况下,对于curry版本,可以先提供A参数,然后使用捕获的A值存储结果,然后在以后提供B参数。

具有两个参数的函数和具有一个参数的函数是“等价的”,tat返回一个参数的函数

从一个到另一个再回到另一个的能力定义了所谓的同构

到头来

咖喱。uncurry
保留一个参数的函数,使一个参数的函数保持不变
uncurry。curry
让一个两个参数的函数保持不变

只是我的好奇,a->B->C在这里被认为是a->(B->C),为什么它不被认为是(a->B->C,这里有快速语法规则吗?谢谢,我理解curry,我的问题是这个函数的类型签名,这个函数应该按照你的答案理解,我的问题是在语法层面。请参阅:“一个常用函数的函数类型是从右到左分组的。例如,函数类型
Int->Int->Int
被理解为
Int->(Int->Int)
——也就是说,一个函数接受
Int
,然后返回另一个函数,该函数接受并返回
Int
”我认为这是从Haskell这样的纯函数式语言中借来的功能,因为它是那里的标准功能。。。。谢谢你,苹果!我在Swift中发现,删除空格并在复合类型中添加括号可以使这样的代码更容易阅读。所以我会把函数的第一行写成
func curry(f:(A,B)->C)->(A)->(B->C)
而且,类型别名可以使函数类型参数更容易阅读,所以如果这是我自己的代码,我可能会选择
typealias curryfunc=(A,B)->C;typealias CurryOutFunc=(A)->(B)->C);func curry(f:@escaping curryfunc)->CurryOutFunc{…}
(在Swift 3中测试和工作)。
let increment = curriedAdd(1)
increment(2) // 3
increment(5) // 6
let addFive = curriedAdd(5)
addFive(5) // 10