如何在Swift中检查/断言函数类型?

如何在Swift中检查/断言函数类型?,swift,types,functional-programming,swift3,occurrence-typing,Swift,Types,Functional Programming,Swift3,Occurrence Typing,例如: func f(x: Int) -> Int { return x } func h(f: @escaping (Int) -> Any) { if (f is (Int) -> Int) { print(f(1)) } else { print("invalid") } } h(f: f) func f(x:Int)->Int{ 返回x } func h(f:@escaping(Int)->Any){ 如果(f是(I

例如:

func f(x: Int) -> Int { return x } func h(f: @escaping (Int) -> Any) { if (f is (Int) -> Int) { print(f(1)) } else { print("invalid") } } h(f: f) func f(x:Int)->Int{ 返回x } func h(f:@escaping(Int)->Any){ 如果(f是(Int)->Int){ 印刷品(f(1)) }否则{ 打印(“无效”) } } h(f:f)
我希望它打印出
1
,但实际上它打印出
无效的

使用泛型有一个解决方法:

func intF(x: Int) -> Int {
    return x
}

func stringF(x: Int) -> String {
    return "\(x)"
}

func h<T>(f: (Int) -> T) {
    if (T.self == Int.self) {
        print(f(1))
    } else {
        print("invalid")
    }
}

h(f: intF)    // prints: 1
h(f: stringF) // prints: invalid
func intF(x:Int)->Int{
返回x
}
func stringF(x:Int)->String{
返回“\(x)”
}
func h(f:(Int)->T){
if(T.self==Int.self){
印刷品(f(1))
}否则{
打印(“无效”)
}
}
h(f:intF)//打印:1
h(f:stringF)//打印:无效

使用
任何
几乎都是代码气味的标志,您应该尽可能依赖Swift提供的类型安全性。您可以通过将
h
设置为泛型来实现这一点,这样就可以在编译时进行验证

// the overload that does the actual stuff
func h(f: @escaping (Int) -> Int) {
    print(f(1))
}

// this maps to all other types
func h<T>(f: @escaping (Int) -> T) {
    print("invalid")
}

h { _ in return "15" }  // Invalid
h {  2 * $0 }           // 2
//执行实际操作的重载
func h(f:@escaping(Int)->Int){
印刷品(f(1))
}
//这映射到所有其他类型
函数h(f:@escaping(Int)->T){
打印(“无效”)
}
h{{uu'返回“15”}//无效
h{2*$0}//2

见鬼,您甚至可以放弃泛型重载,这样您就可以免费进行编译检查,而不是运行时故障(非常、非常可靠和可预测)

您可以将
h
重写为泛型函数:

func h<T>(f: @escaping (Int) -> T) {        
    if T.self == Int.self  {
        print(f(1))
    } else {
        print("invalid")
    }
}
func h(f:@escaping(Int)->T){
如果T.self==Int.self{
印刷品(f(1))
}否则{
打印(“无效”)
}
}

但是为
h
编写特定于类型的重载以及为其余部分编写通用的catch all(如果您需要的话)的更好方法是:
如果f(1)是Int{
我怀疑实例的类型是“wrapped”在编译器看来,
f
{arg in;/*…*/;return someInstanceOfTypeAny}形式的闭包
。只有通过实际研究闭包
f
返回的实际实例的类型,才能确定
someInstanceOfTypeAny
是否为类型
Int
,例如,正如@vacawama所建议的那样。下面的答案使用一个模板解决方法,其中
T
实际上是一个具体类型(不是运行时包装器!)在将
f
传递到
h
时,每次调用
h
@dfri,编译器都知道
f
的类型是
(Int)->Int
,我想知道为什么它不能将
(Int)->任何
缩小到子类型
(Int)->Int
f
不是没有类型注释的匿名闭包。
f
注释很好。@weakish
Any
这里没有一个类型保持器(它保持符合
Any
的任何类型)同样,下面的答案中使用了泛型类型持有者
T
。如果您尝试用自定义类
Base
替换
Any
,返回类型为
func f(…
,使用
派生的
派生的
),并测试提供的闭包是否为
(Int)->Derived
,您将看到,在向
h
提供
(Int)->Derived
闭包时,仍然会输入
“invalid”
主体,因为
h
中的参数
f
被显式类型注释为
(即使提供了
(Int)->Derived
).我写了
Any
,所以
(Int)->Int
(Int)->Any
的子类型。这是为了使代码示例简短,而不定义很多类。这与@nils答案相同吗?