Swift中单参柯里化函数可接收双参函数的编译异常问题
Swift中柯里化函数的类型匹配问题
问题重现
这段代码看起来明显不符合类型要求,但居然能编译通过:
func curry<A, B>(_ f: @escaping (A) -> B) -> (A) -> B { print("is called") return f } func sum(a: Int, b: Int) -> Int { a + b } curry(sum)
编译器自动把f推断成了((Int, Int)) -> Int类型——这不是bug,是Swift的特性:多参数函数会被自动转换为接受对应元组的函数。
如何避免这种类型不匹配的传参
- 显式指定泛型参数:调用时明确给出泛型类型,让编译器严格校验:
curry<Int, Int>(sum) // 直接编译报错,因为sum不符合(Int)->Int的类型 - 修改curry函数签名:如果你的目标是柯里化多参数函数,直接针对多参数场景写签名,比如双参数的柯里化:
func curry<A, B, C>(_ f: @escaping (A, B) -> C) -> (A) -> (B) -> C { return { a in { b in f(a, b) } } } // 调用后得到真正的柯里化函数 let curriedSum = curry(sum) let result = curriedSum(1)(2) // 输出3 - 用类型约束限制输入:如果要确保传入的是严格单参数函数,可通过泛型约束排除元组(Swift没有直接的元组约束,可借助其他协议或条件):
// 示例:用Sendable约束(根据你的场景调整) func curry<A, B>(_ f: @escaping (A) -> B) -> (A) -> B where A: Sendable { print("is called") return f } // 此时传入sum会编译报错,因为元组(Int, Int)默认不遵循Sendable(需手动扩展或调整约束)
补充说明
原代码里的curry是实现通用可变参数柯里化过程中的一步,所以用了这个命名,但当前函数只是单参数函数的包装,没有处理多参数柯里化逻辑,这才让编译器有机会把多参数函数转成元组函数。
内容的提问来源于stack exchange,提问作者Roman
相关产品推荐
相关产品推荐

