Swift 2.2+中Type的上下文类型推断

时间:2016-05-26 17:39:06

标签: swift generics types

我想在Swift中使用一阶公民类型来决定调用哪个函数。

func sf(v: [Float]) -> Float{
}

func  df(v: [Double]) -> Double {
}

func f<T: RealType>(seq ls: [T]) -> T {
  if T.self == Float.self {
    return sf(ls) // 1. where sf: Float -> Void
  } else if T.self == Double.self {
    return df(ls) // 2. where df : Double -> Void
  }
}

类型推理系统无法注意到在一个分支T == Float和Double在另一个分支下?

这是一个缺少的功能,复杂的功能还是错误?

修改

typealias RealType = protocol<FloatingPointType, Hashable, Equatable, Comparable, FloatLiteralConvertible, SignedNumberType> 

我的原型但将成为协议

1 个答案:

答案 0 :(得分:1)

您正在尝试将泛型给出的静态分辨率与运行时决策结合起来,但这是不可能的。

您可以简单地为fFloat重载Double以获得所需内容:

func f(seq ls: [Float]) -> Float {
    return sf(ls) // 1. where sf: Float -> Void
}

func f(seq ls: [Double]) -> Double {
    return df(ls) // 2. where df : Double -> Void
}

但是,如果您希望RealType成为通用占位符,可以使用FloatDouble以外的其他类型,那么您可以执行以下操作:

protocol RealType {
    static func processArray(v: [Self]) -> Self
}

extension Float: RealType {
    static func processArray(v: [Float]) -> Float {
        return sf(v)
    }
}

extension Double: RealType {
    static func processArray(v: [Double]) -> Double {
        return df(v)
    }
}

func sf(v: [Float]) -> Float{
    return 0
}

func  df(v: [Double]) -> Double {
    return 0
}

func f<T: RealType>(seq ls: [T]) -> T {
    return T.processArray(ls)
}

这将为您提供类型安全性,这是Swift的主要优势之一,以及可扩展性,因为无论何时需要在f上添加对其他类型的支持,您只需将该类型声明为符合{{ 1}},并实现RealType方法。